On November 3, 2017, some users of Reddit noticed two WhatsApp applications with the same developer name “WhatsApp Inc.” and started to investigate what looked like a fake update for the WhatsApp application. They quickly realized that the application has been downloaded more than one million times.
As a part of Zimperium’s zLabs research team, I analyzed the Fake WhatsApp… and then discovered another threat through an ad served up by it: malware called “Cold Jewel Lines”. The analysis of both the Fake WhatsApp and secondhand malware, Cold Jewel Lines, is the focus of this post.
Fake WhatsApp Metadata:
Application Name: Update WhatsApp Messenger
Company Name: WhatsApp Inc. (with a trailing NO-BREAK SPACE)
Package Name: whyuas.fullversion.update2017
Play Store Link: https://play.store.com/store/apps/details?id=whyuas.fullversion.update2017
After installation, the application can’t be seen on the launcher because the developer set an empty app_name value and a transparent ic_launcher.png icon; nevertheless it can be started from the launcher by clicking on the “empty” icon present at the end of the list of applications in the launcher. In the Android settings, the application can be easily spotted and uninstalled also if it doesn’t have a name.
After launching it, different advertisements are shown to the user. By clicking the install button, the user is redirected to the Play Store to install the displayed application. It’s clear that the main focus of the app is Ad click fraud. But during execution, the user can also select different “Update servers” from which the fake WhatsApp update should theoretically be downloaded.
The code simply loads the index1.html to index11.html from the assets and expects the user to click the download button. The page displays a download server number, a download button with the text “Download Update” plus the filename and size of the APK the user expects to download. Once clicked, the button redirects to a shortened URL offered by bitly.com (which is now marking the link as potentially harmful).
The following is a video showing the behavior of the application:
Cold Jewel Lines Analysis: Secondhand Malware
During the Fake WhatsApp investigation, one of the ads displayed a really suspicious application. As can be seen in the behavior video, the first “Install” button loads a Play Store application named Cold Jewel Lines.
Summary of malicious activity:
After a drop phase, the malware main goals are:
- Opening a communication channel with a C&C server waiting for commands;
- Execute Ads-autoclicking activities;
- Exfiltrate sensitive information from the device;
- Parse and extract information from received SMS;
- Possibly execute other malicious payloads (e.g. exploits);
- Possibly execute shell commands to extract additional data;
Application Name: Cold Jewel Lines
Company Name: kbtjgbqv
Package Name: en.cold.jewel.th.lines
Play Store Link: https://play.google.com/store/apps/details?id=en.cold.jewel.th.lines
Archived Play Store Page: https://web.archive.org/web/20171120165502/https://play.google.com/store/apps/details?id=en.cold.jewel.th.lines
The application has been reported to Google on November 20, 2017 and has been removed on November 21, 2017.
The application itself is a fully working game, and the malware is executed as soon as the application is started. In fact, the developer decided to inject a malicious call to the infiltration.outcry class from the android.support.multidex.MultiDexApplication class. In particular, the infected method is attachBaseContext. During the statical initialization of the outcry object, the library libseconhand.so is loaded and then the native method init is called, passing the Context and the string “NzZmBCp6IFcbCSQPb2NWa2ViBWNKekMGew==” arguments. The “NzZmBCp6IFcbCSQPb2NWa2ViBWNKekMGew==” string will be later referenced by the malware as apiKey.
The libsecondhand.so library is available for ARM, ARM64, x86, x86-64, MIPS and MIPS64, and the only purpose is to drop a malicious APK and dynamically load the embedded classes.dex. All the library strings and the embedded malicious APK are encoded with block-XOR encryption.
The drop phase is executed entirely by the native code using JNI functions:
- A random UUID is generated and the malicious APK is decoded and dropped in the files folder;
- a DexClassLoader object is created using the path to the dropped APK as argument;
- the ClassLoader.loadClass method is called with infiltration.Main as argument;
- the static method init of the infiltration.Main class is retrieved and called by the native code before quitting.
All the strings/variables/classes in the dropped classes.dex are obfuscated; the strings can be retrieved decompiling the code (e.g. with jadx) and executing the StringDecoder.py script that can be found in the Attachments section.
The init method is clearly the main entry point for the malicious code and executes some tasks before spawning a background service that will carry on the malicious activities:
- The init method receives the path to the dropped APK and the apiKey string;
- the infiltration.Main class is basically a slightly modified version of the Android system android.support.multidex.MultiDex class and once the dropped classes.dex is fully loaded the dropped files are deleted from the file system;
- a SharedPreferences file F.xml is created and the pkgName and apiKey are saved;
- the service implemented in the infiltration.rate class is started.
The rate class will handle the communication with the C&C server (systemofram.com) and will execute all the received tasks; a basic mechanism of request/response with acknowledge of the received or completed task is in place and each task has its own id. All the messages have a JSON structure and before being sent are encrypted.
The downfall class it’s a BroadcastReceiver and will handle the intents with the following main actions:
- android.provider.Telephony.SMS_RECEIVED: extracts the sender and the body from an SMS message and, based on the receiveSms and smsFilters commands (see below) will parse and match their contents.
- com.android.vending.INSTALL_REFERRER: sets the referrer field of another class object that will be later used during Ads clicking functionalities.
- android.net.conn.CONNECTIVITY_CHANGE: determines the current connectivity state and informs the server about it (if possible).
- c: if the waiting interval is not over, it delays the intent by the remaining time.
The following list briefly explains the commands supported by the malware:
- init: It’s the initialization command sent by the client. The private key is sent to the server; the server will answer acknowledging the private key and requesting the info to the client. The client will finalize the message exchange acknowledging the server of the correct termination of the init task. The other messages will use the same acknowledging system.
- ok: It’s a message sent by the server to notify the client that a blob of data has been correctly received.
- url: The server sends an URL to the client, which saves it in an instance of a class which implements a getter that unfortunately is not used anywhere. Looks like an in-progress functionality.
- info: The server requests information about the device, the client will send the following information: version, androidUuid, apiKey, appId, operator, WiFi, Battery, locale, manufacturer, model, androidVersion, screen, forGooglePlay, debug, userAgent, androidSdkVersion, androidBuildVersion, fingerprint, hardware, device, wifiNetworks (name, mac, level), currentWifiNetwork, mobileDataEnable, rootAvailable, simInfo, installedApps, simCount, androidId, imei, imsi, isPhone, referrer. This kind of information can be (and is) used to fingerprint the device and execute specific actions.
- interval: The server sends the amount of time to make the client sleep; it seems to be in the order of minutes.
- receiveSms: Enables or disables the SMS filtering; if the device doesn’t have a SIM or available connection to receive messages, the code will try to detect the possibility to enable it.
- smsFilters: The server sends a list of tuples made of regural expressions to match the received SMS messages; phoneExp are regexes used to match the sender of the SMS (be it a number or a service name), while textExp are regexes used to match the body of the text message and extract useful information from it. Once the matching and information extraction have been executed, the data are sent back to the server.
- silentMode: The server sends a huge amount of time to make the client sleep; it’s expected to be hours or days.
- server: The server notifies the client about a new C&C server.
- shell: The server sends a list of commands to be executed by the device. It looks like that if root is available on the device, the su shell can be used, otherwise the commands are executed with sh -c. The results (or error messages if they occur) are sent back to the server.
- download: The server specifies a file to be downloaded by the client. Although none of the messages contained a download action item, we can expect the server to execute a fingerprinting phase with the info command, download a compatible exploit to the device, and execute it with the shell command.
The communication with the server is encrypted, but a simple Xposed module has been developed to hook the drop phase, log all the exchanged messages and fake the root status of the device. It can be further modified to tamper the communication with the C&C server if needed, because the hooked methods give access to the sent and received JSON strings.
The communication with the C&C server has been monitored for two days, but only a subset of the commands have been detected. In particular, no occurrence of the silentMode, server, shell and download commands was detected. In the next snippet of code, you will find the logged messages dialog, showing how the malware is able to:
- Exfiltrate sensitive data: Personally identifiable data such as IMEI, IMSI, androidUuid, operator, WiFi networks, MACs, manufacturer, root status, user agent and others are all sent to the server;
- SMS message parsing: The server sends to the app a list of regexes to be applied to the received SMS to extract information; messages received from Billinfo, 1232111, o2.Team, o2.Info, Bouygues, Orange and others services matched via regexes are targeted;
Frida and Xposed
During the investigation, both Frida and the Xposed framework were used to quickly gather information about the messages exchanged with the C&C server. Initially Frida has been selected to carry on the task of logging all the communication, but has been lately dropped because it caused some problems while instrumenting two methods with the same name (but different Java signature), even if the overload procedure was implemented. The code has been ported to an Xposed module that can be safely used to achieve early instrumentation and in particular hooking the dynamically loaded code as soon as it’s dropped and loaded by the libsecondhand.so library.
The module has been based on the DexHook code from the RedNaga team and in particular the infinite recursion problem that popped out while hooking the ClassLoader.loadClass method has been solved thanks to the Issue#188 on the Xposed repository.
Although the code is small and just a PoC, the idea is powerful enough to guarantee early instrumentation on an Android process employing dynamic class loading based on:
- dalvik.system.BaseDexClassLoader(dexPath, optimizedDirectory, librarySearchPath, parent);
- dalvik.system.DexFile.openDexFile(sourceName, outputName, flags);
Aside from the support for the dynamic class loading, the code installs some hooks in the methods used to communicate with the C&C server, in particular:
- infiltration.AdfdI9FaQBbbW3Hgur24m6n0.vvgQM33AjqPJZjX(String s, PrivateKey k): hooking the result of this method will let us log all the data received from the server;
- infiltration.AdfdI9FaQBbbW3Hgur24m6n0.vvgQM33AjqPJZjX(String s, PublicKey k): hooking the first parameter of this method will let us log all the data sent to the server;
- infiltration.AdfdI9FaQBbbW3Hgur24m6n0.jNWow5lMF5gpMRlovjqsFg(): hooking the result of this method will let us force the root detection flag; the idea was to force the result to false each time the code asked for the root status, and see if the server would have sent a command to download and execute an exploit on the device.
In the Attachments section you can find a link to both the Frida and Xposed solutions.
Some additional information has been collected about the C&C server. For example, the domains alfa-aaa.site and ex2cloud.xyz seem to be part of the same network, because the systemofram.com/b/test/ URL is pointing to an HTML with embedded JS code referencing the other domains.
Further investigation will be needed to collect additional information about the C&C structure and detect more samples possibly available on the Play Store.
This is a list of useful resources that have been developed during the analysis of the sample, they can be found on the repository:
- Decoded.apk: This is the APK dropped by libsecondhand, the SHA256 of the dropped APK is 7300a2f8f93dd5a612c3d62ca49a742c1b761dbd454141407018173aca7ac1e1.
- DecodeDropped.c: This is the C code to decode the dropped APK. The code to decode the encrypted strings in the libsecondhand.so library is basically the same, but each encoded strings starts with 1 byte indicating its length.
- StringDecoder.py: This is a simple script that uses the decompiled code from the dropped APK as input and extracts (or tries to) all the encoded strings.
- HookC2.py: This is the Frida script used to log the communication between the client and server; it’s not working on my device, feel free to reach me if you have a solution (address on the script comment).
- Hooker: This is the Xposed module used to log the communication between the client and server; it’s fully functional and guarantees early instrumentation of the sample.
- Fake WhatsApp: 80fe0de24e58eb1c485d55c94d20ffd710fc4b8a05f2c20d9d0d42cabb683fad
- Jewel Miner: 1daa6ff47d451107b843be4b31da6e5546c00a164dc5cfbf995bac24fef3bc6d
- Fake WhatsApp Bitly URL: http://bit.ly/2xDkNhy
- Jewel Miner C&C URL: https://systemofram.com
I would like to thank all the zLabs researchers, especially Rani Idan (@raniXCH) and the rest of the Malware Team (@evilsocket and @Matrix86_) for the suggestions they gave me about information gathering on the C&C server network.