Over the past couple of weeks, we have been observing a new Trojan on GooglePlay. So far, we have detected it in 24 apps with over 472,000+ installs in total. The malware — going by the name “the Joker” (which was borrowed from one of the C&C domain names) — delivers a second stage component, which silently simulates the interaction with advertisement websites, steals the victim’s SMS messages, the contact list and device info.

The automated interaction with the advertisement websites includes simulation of clicks and entering of the authorization codes for premium service subscriptions. For example, in Denmark, Joker can silently sign the victim up for a 50 DKK/week service (roughly ~6,71 EUR). This strategy works by automating the necessary interaction with the premium offer’s webpage, entering the operator’s offer code, then waiting for a SMS message with a confirmation code and extracting it using regular expressions. Finally, the Joker submits the extracted code to the offer’s webpage, in order to authorize the premium subscription.

The Joker malware only attacks targeted countries. Most of the infected apps contain a list of Mobile Country Codes (MCC) and the victim has to be using a SIM card from one of these countries in order to receive the second stage payload. The majority of the discovered apps target the EU and Asian countries, however, some apps allow for any country to join. Furthermore, most of the discovered apps have an additional check, which will make sure that the payload won’t execute when running within the US or Canada. The UI of C&C panel and some of the bot’s code comments are written in Chinese, which could be a hint in terms of geographical attribution.

The full list of 37 targeted countries includes: Australia, Austria, Belgium, Brazil, China, Cyprus, Egypt, France, Germany, Ghana, Greece, Honduras, India, Indonesia, Ireland, Italy, Kuwait, Malaysia, Myanmar, Netherlands, Norway, Poland, Portugal, Qatar, Republic of Argentina, Serbia, Singapore, Slovenia, Spain, Sweden, Switzerland, Thailand, Turkey, Ukraine, United Arab Emirates, United Kingdom and United States.

Besides loading the second stage DEX file, the malware also receives dynamic code and commands over HTTP and runs that code via JavaScript-to-Java callbacks. Such an approach provides an extra layer of protection against static analysis, since a lot of instructions in this case are not hard-coded into the malicious app on GooglePlay.

Loader

In most of the apps the developers have inserted the Joker initialization component into one or another advertisement framework. The little package of malicious code typically consists of:

• Target country checking via MCC

• Minimum C&C communication — just enough to report the infection and receive the encrypted configuration

• DEX decryption & loading

• A notification listener — when a new SMS message arrives, this listener captures it and sends out a broadcast for the Core (second stage) component to pick up.

Often, an app would contain a so-called “Splash” screen — an activity, which displays the app’s logo, while performing various initialization processes in the background. Some of the Joker apps use such activity for initialization as well.

310 and 302 are the MCC codes for USA and Canada

The Joker employs custom string obfuscation schemes for all of the configuration/payload/communication parsing procedures. The code listing below displays an example of an obfuscated MCC code list, (DEFAULT_COUNTRY_ISO) separated by the underscore symbol.

In this case, a method for de-obfuscation dynamically builds a string “28 Ux0-” and removes it from these strings

After the initialization is done, the malware will download an obfuscated and AES-encrypted configuration from the payload distribution C&C server. Joker composes the AES key for the configuration string decryption using yet another string scheme, which would concatenate the app’s package name with MCC code string and shuffle the symbols around in a specific way. Eventually, the settings for the second stage retrieval decrypt to a message of the following format:

#x#https://tb-eu-jet.oss-eu-central-1.aliyuncs.com/s8-all#x#18#x#32#x#com.plane.internal.Entrance#x#initialize#x#http://joker2.dolphinsclean.com/#x#swfyXB

The configuration string above contains the necessary information about the second stage code — the core component of the Joker. Being split by a 3-symbol delimiter, the configuration string above contains (ordered):

1. The URL for the Joker Core DEX file — this file is obfuscated

2. The de-obfuscation “keys” — indexes of the obfuscated read buffer

3. The initialization class name — the class, which implements the initialization method

4. The initialization method name — which method to call upon loading

5. The C&C URL

6. The campaign tag

The Loader downloads the DEX and starts the de-obfuscation routine. The said routine reads the DEX file in a buffer 128 bytes at a time. The de-obfuscation “keys” are the positional indexes for this buffer. For each iteration, the routine reads the bytes of the obfuscated buffer only between these positions and writes them into a file, producing a valid DEX file in the end.

Core

This malware kit stands out as a small and a silent one. It is using as little Java code as possible and thus generates as little footprint as possible. After all of the Loader’s MCC checks and payload loading — the Core component begins its work. It is designed in a job-scheduler fashion, meaning that it periodically requests new commands from the C&C server. When found, it executes them in strict order and then reports the results, depending on the type of the given task. The below figure is an example of a command (truncated).

A job message from Joker’s C&C

When Joker receives such message, it proceeds to open the offer URL, injects the JavaScript commands one by one and waits for an authorization SMS (if any). When the SMS message arrives, the malware extracts the necessary authorization code using case-specific regular expressions. At other times, it simply sends a SMS message to a premium number, with a specific code from the offer page.

Snippet of JavaScript from a premium offer page

The Joker knows when to send a premium SMS message when it opens a premium offer page and finds an attribute with value starting with “sms:”.

Joker builds a SMS to be sent to a premium number, using data from the premium offer webpage

Whenever the malware extracts a code from a SMS message — it also reports it to the C&C after the job is complete. Hypothetically, the botnet operator can craft a job, which would result in all incoming SMS messages being stolen.

Joker’s SMS data exfiltration, encrypted with AES

The figure above is a sample of the second stage communication with the C&C and it contains the full text of a stolen test SMS message. It can be decrypted into a JSON object. The clear-text communication can also be observed using a debugger.

A portion of decrypted report, containing the stolen SMS message

The final important thing worth mentioning about the Joker is the phone book contact list theft. The core component collects all numbers in the contact list and sends them over to the C&C in an encrypted form:

Contact list harvesting

A total of 12 unique builds of the second stage payload were observed among the 24 infected apps. The version names come from the payload URLs and data inside the sample’s configuration class:

-s8-release

-s8–5-release

-s8–5-dsp-release

-s8-all

-s9–6-release

-s9–6–3

-s9–3-sendsms

-s9–6–2-release

-Y12-all-no-log

-Y12-no-log

-Y13-all

-Y13-all-v2-no-log

Summary

The described trojan employs notably stealthy tactics to perform quite malicious activities on GooglePlay, while hiding within the advertisement frameworks and not exposing too much of its malicious code out in the open. The earliest occurrence of the Joker in the wild that we can pinpoint comes from DNS metadata, which suggests that the Joker malware family has begun its recent campaigns in early June 2019. However, the major version digits in the build names give an impression of a slightly longer life cycle, potentially with more campaigns in the past.

Despite the volume (24 apps) Google seems to be on top of this threat as much as it is possible. Some of the apps do rack up 100,000+ installs before they get removed, however, the install number can always be artificial to some degree due to the common astroturfing practices. Throughout this investigation, Google has been removing all of these apps without any note from us.

We recommend paying close attention to the permission list in the apps that you install on your Android device. Obviously, there usually isn’t a clear description of why a certain app needs a particular permission, which means that whenever you are downloading any app — you are still relying on your gut feeling to some extent.