2013-12-02
Abstract
The Android/FakeKakao trojan monitors incoming and outgoing SMS messages, sends SMS spam and gathers sensitive information as well as incorporating anti-debugging and anti-emulator tricks and disabling some security software. Zhe Li and Dong Xie take a closer look.
Copyright © 2013 Virus Bulletin
The Android/FakeKakao trojan disguises itself as a KakaoTalk security plug-in as a means to lure users to install it. Once installed, it monitors incoming and outgoing SMS messages, sends SMS spam, gathers sensitive information and communicates with its remote server. Moreover, it incorporates anti-debugging and anti-emulator tricks and disables some security software.
Unlike other malware, the trojan’s DEX (Dalvik Executable) is mainly used as a loader; the payload is transplanted into a native library. In this article, as well as dissecting the behaviour of the malware, we will look at some debugging and analysis methods.
The loader registers three components: MainActivity, ActionReceiver and MoriService. The MainActivity component is designed to start up an elaborate user interface to mislead victims (Figure 1, comments are translated online). The ActionReceiver component is used to receive the android.intent.action.USER_PRESENT broadcast, which is sent out by the system as the device wakes up.
To ensure the broadcast is received as early as possible, the malware sets the intent filter priority value of the receiver to 0x7FFFFFFF. When the broadcast is received, the MoriService component is launched in the background. The service’s calling methods come from a native library, libEglsv1.so, which is dropped by the malware when the APK (Android package file) is installed. In order to run the application smoothly, the malware requests the following permissions:
READ_SMS
READ_CONTACTS
READ_PHONE_STATE
SEND_SMS
WRITE_EXTERNAL_STORAGE
WRITE_SMS
INTERNET
RECEIVE_SMS
The launched service first loads the dropped library into the malware’s process address space. When the library is initialized, the malware attempts to check whether it is being debugged or running in an emulator. If one of the following is detected, it will set an anti-debug/emu flag for future use:
strace
ltrace
android_server
gdbserver
gdb
tcpdump
ro.kernel.qemu
/system/bin/qemu-props
/system/bin/qemud
After the initialization, six native methods are registered (Figure 2) by calling RegisterNatives(). Then the malware calls the SetJNIEvn() method to initialize the JNI (Java Native Interface) environment variables which are prepared for calling other native methods. However, if the anti-debug/emu flag is set, the other native methods will do nothing.
The malware collects private information from the compromised device, then encrypts the information using the AES-192 algorithm [1], which is utilized by most of the encryption and decryption routines in this library. Before sending the gathered information, the malware retrieves the C&C server list from the encrypted config.js file, which is included in the installed APK file. Besides using the AES-192 algorithm in order to decrypt the configuration file, an extra decompression is required for the server list, which calls the uncompress() API. Figure 3 shows the decrypted server list. We can see that there are two server entries in this file. The first is used for an internal test. The second entry is the real C&C server.
The collected information is divided into two parts, we refer to them as the ID part and the MD part. The ID part includes the following information:
id | IMEI |
token | product brand and model |
target | build version |
rd | flags existence of /system/bin/su or /system/xbin/su |
fo | compromised phone number |
And the MD part includes the following information:
md | same as id |
fo | compromised phone number |
ds | contact name and number list |
The malware first sends the ID part to the C&C server to register the compromised device. If the server’s response data is ‘0’, it will send the MD part. If the server’s response data is ‘1’, the MD part won’t be sent. Figure 4 shows examples of such communication.
Next, the malware requests filter rules from the C&C server. The rules are used to filter the incoming text messages and the SMS database. The malware uses the following keywords for screening messages (the content may vary):
plist | matches phone number of message |
klist | matches message content |
blist | matches nickname of message |
allmsgs | spam message content |
snumber | specific phone number by malware |
smsg | message which is sent to snumber |
allmsg | another spam message content |
checked | flag, sends spam message or not |
unlock | flag, stores the contact list or not |
Figure 5 and Figure 6 show an example of the filter rules.
The malware records the time of each start-up of the service. When the service is started the next time, it will resend the collected information and request new filter rules if the interval is longer than 30 minutes.
In order to monitor incoming text messages, the malware first registers a new broadcast receiver by calling registerReceiver(). Then it sets the receiver’s intent filter priority with the value 0x7FFFFFFF to make sure it has a higher priority than other receivers. As a result, it can process the messages first.
Whenever a message comes in, it will filter it using the rules – for example, matching the phone number, searching the message content and so on. It will call abortBroadcast() to stop handing over the messages it is interested in to other low priority receivers.
To monitor the changing of the SMS database, the malware registers a content observer by calling registerContentObserver(). Whenever the database is changed, it checks each message in the same way as it does for incoming messages. Whether the matched message comes from the receiver or observer, it will be encrypted and sent to the remote server. Whenever the receiver or the observer is triggered, the malware resends the collected information and requests an update of filter rules.
The sending of the spam message is based on the value of the keywords ‘checked’, ‘allmsgs’ and ‘allmsg’ in the filter rules. If ‘checked’ is not zero, and ‘allmsgs’ or ‘allmsg’ are not empty, it will send the spam message to each address in the contact list. The interval between sending spam messages is 40 seconds. If the compromised phone number is empty, it sends the content of the ‘smsg’ keyword to a specific number which is indicated by the ‘snumber’ keyword. Either way, it deletes its sending record from the local database to erase the evidence.
In this part, the malware tries to drop FOTAKill.apk to the /system/app/ folder. FOTAKill is a third-party application that can be used to stop the FOTA (Firmware Over-The-Air) [2] update service. The purpose of utilizing FOTAKill is probably to stop the update erasing some obtained privileges, such as root access. To drop the file, the malware checks the user identification (UID) by calling the getuid() API. If the UID is root, it reads /data/system/packages.list, which records all the APKs installed on the device. If the list contains any of the following security related strings, the malware resorts to the ‘pm disable’ command to close it:
com.avira.android
com.antivirus
com.kms
com.wsandroid.suite
com.qihoo360.mobilesafe
com.ijinshan.duba
com.tencent.qqpimsecure
com.anguanjia.safe
com.lbe.security
com.netqin.mobileguard
com.avast.android.mobilesecurity
com.estsoft.alyac
com.lookout
com.zoner.android.antivirus
com.symantec.mobilesecurity
com.drweb.pro
com.drweb
com.drweb.pro.market
com.symantec.mobilesecurity
com.symantec.monitor
As we know, one of the disadvantages of using native code on the Android platform is that it increases the application’s complexity. However, the malware takes advantage of this feature to protect itself against reverse engineering. A commonly used method for debugging a native library is to attach the debugger to the target process on the remote server. However, in this case we may lose the chance to attach to the process, since the application has run over the address at which we want to stop.
Therefore, we need to know how to set the first breakpoint at the address we want to go to. The simplest and most effective way to do this is to use a single instruction to perform an infinite loop. At the address at which we need to set a breakpoint, an unconditional jump can be used to replace the original instruction. Since the native library is based on ARM architecture (at present, Android supports ARM, ATOM and MIPS), the modified instruction for ARM and THUMB is as follows:
Set | Format | Byte code |
---|---|---|
THUMB | 1110 0XXX XXXX XXXX | FE E7 |
ARM | 1110 1010 XXXX XXXX XXXX XXXX XXXX XXXX | E FF FF EA |
Instead of repacking the modified native library into the APK, we can replace the corresponding library on the remote server. This also bypasses the malware’s inspection of the integrity of the APK. Usually, if we use an Android emulator, the library can be found in the /data/data/<app name>/lib/ folder or the /data/app-lib/<app name>/ folder.
When it comes to static analysis, thanks to IDA’s powerful comment functionalities, a calling convention named __usercall can be used. For this ARM ELF file, the general format looks like this:
int __usercall FunctionName<R0>(int P1<R0>, char* P2<R1>, int P3<R2>);
If there are lots of references to a function, it is very helpful for analysis purposes to add comments to the function parameters.
Use of the native library, anti-debugging tricks and encrypted strings to increase the complexity of reverse engineering, as well as the dropping of the FOTAKill application, all give us a hint that this malware may still be under development, and we are likely to see more features added to it soon.
[1] Advanced Encryption Standard. Wikipedia. http://en.wikipedia.org/w/index.php?title= Advanced_Encryption_Standard&oldid=582028381.
[2] Over-the-air programming. Wikipedia. http://en.wikipedia.org/w/index.php?title=Over-the-air_programming&oldid=581843956.