Tracking Android/Joker payloads with Medusa, static analysis (and patience)

@cryptax
4 min readJun 20, 2022

--

I am looking into a new sample of Android/Joker, reported on June 19, 2022 by @ReBensk:

afeb6efad25ed7bf1bc183c19ab5b59ccf799d46e620a5d1257d32669bedff6f

Android/Joker is known for using many payloads: a first payload loads another payload, which loads another one etc. Matryoshka dolls-style šŸ˜. See an analysis of a previous Joker sample. This sample uses many payloads too, but the implementation to load the payloads is a bit different. Iā€™ll detail.

Medusa

I recently discovered Medusa and like it very muchā€¦ for dynamic analysis (I still prefer static analysis, everybody knows that by now?). Medusa is easy to use and comes with a collection of ready-to-use Frida hooks. Launch an Android emulator, a Frida server, install the sample, then launch Medusa python3 medusa.py.

Select the hooks you want to use (search through hooks with the search command, then use to use a given hook, finally compile the list of hooks). Those are the hooks you need (I recently contributed to the last two hooks):

use http_communications/uri_logger
use encryption/cipher_1
use code_loading/dump_dyndex
use code_loading/load_class

Finally, start the malware (run -f package_name, or run -n 0 if you have a single sample installed on your emulator).

I use URI hooks (http_communications/uri_logger) in Medusa and see the malware calls those URLs. Android/Joker is known to use URLs such as xxx[.]aliyuncs.com.

As Android/Joker samples usually donā€™t make things simple for malware analysts, I somewhat expected those URLs to be encrypted. Medusa has decryption hooks too.

Bingo! The look4.oss-ap[..]aliyuncs.com URL is encrypted. The decryption hooks, encryption/cipher_1, with shows the decrypted value.

My dynamic DEX dumper + the convenient loadClass hooks show several files are dynamically loaded:

DexClassLoader called: /data/user/0/com.designemoji.keyboard/files/audience_network.dex
[+] Dumped /data/user/0/com.designemoji.keyboard/files/audience_network.dex to dump_1
loadClass: com.designemoji.keyboard.EnableActivity
loadClass: com.facebook.ads.internal.dynamicloading.DynamicLoaderImpl
...
PathClassLoader(f,p) called: /data/user/0/com.designemoji.keyboard/cache/nuff
[+] Dumped /data/user/0/com.designemoji.keyboard/cache/nuff to dump_2
loadClass: seek
...
DexClassLoader called: /data/user/0/com.designemoji.keyboard/files/seek
[+] Dumped /data/user/0/com.designemoji.keyboard/files/seek to dump_3
DexClassLoader called: /data/user/0/com.designemoji.keyboard/files/Yang
[+] Dumped /data/user/0/com.designemoji.keyboard/files/Yang to dump_4
loadClass: com.xjuys
loadClass: com.android.installreferrer.api.InstallReferrerClient

The first DEX (audience_network.dex) belongs to Facebook. I am not after this. The 3 other DEXes (nuff, seek and Yang) are far more promising. Note they are loaded by PathClassLoader for nuff, and DexClassLoader for the other 2.

Loading nuff (payload 1)

DroidLysis doesnā€™t detect any use of DexClassloader, PathClassLoader or InMemoryDexClassLoader. So, how is the first payload loaded? Letā€™s locate the URL (look4[ā€¦]aliyuncs.com). It is encrypted, so I search where encrypted is used in DroidLysisā€™ detailed report.

## Cipher
- file=./emojikeyboard.apk-afeb6efad25ed7bf1bc183c19ab5b59ccf799d46e620a5d1257d32669bedff6f/smali/f/a/a/a.smali no= 25 line=b'.method private b()Ljavax/crypto/Cipher;\n'
- file=./emojikeyboard.apk-afeb6efad25ed7bf1bc183c19ab5b59ccf799d46e620a5d1257d32669bedff6f/smali/f/a/a/a.smali no= 63 line=b' invoke-static {v0, v1}, Ljavax/crypto/Cipher;->getInstance(Ljava/lang/String;Ljava/lang/String;)Ljavax/crypto/Cipher;\n'

Fortunately, there are not many different locations, and I directly head to the good one: f.a.a.a. Encrypted strings are decrypted using PBEWithMD5AndDES. I write a static decryptor.

Decrypted=https://look4[.]oss-ap-southeast-5[.]aliyuncs.com/designemoji
Decrypted=getClassLoader
Decrypted=loadClass
Decrypted=seek
Decrypted=melody

The URL gets a JAR, stores it in a cache directory of the application, and then loads it via ā€¦ getClassLoader ! Thatā€™s why DroidLysis didnā€™t see it! (to be fixed).

Code loading the JAR with getClassLoader, then invokes a method named melody()

Static analysis of nuff (payload 1)

The JAR contains a classes.dex with a single class named seek, and a method named melody. It is simple to understand:

  1. It downloads DEX file from https://look4.oss-ap-southeast-5[.]aliyuncs[.]com/nunber

2. It stores that DEX in the applicationā€™s file directory, with filename seek

3. It loads the DEX using DexClassLoader

4. It invokes cantus.bustle() in that DEX

Code of payload 1. Download URL for payload 2 ā€” we also see that class cantus, method bustle is called.

Static analysis of payload 2

Just guess what cantus.bustle() does? It downloads yet another DEX from https://xjuys.oss-accelerate[.]aliyuncs.com/xjuys !

Payload 2 is loading ā€¦ Payload 3

This time, the payload will be stored in a file named Yang, and it will search for class com.xjuys and method xjuys.

Static analysis of payload 3

This com.xjuys JAR had been already used in several other samples of Joker (sha256: 2edaf2a2d8fd09a254ea41afa4d32b145dcec1ab431a127b2462b5ea58e2903d).

It loads dynamically 2 other ZIPs:

  1. https://xjuys.oss-accelerate[.]aliyuncs.com/fbhx1. We have already seen this payload. It is the same as in this article and contains facebook hooks.
  2. https://beside.oss-eu-west-1[.]aliyuncs.com/af2. It stores the file in the appā€™s file directory, with filename KBNViao. Then, it loads com.appsflyer.AppsFlyerLib and methods init() then startTracking() [love the name of the method, donā€™t we? šŸ˜]. This is Apps Flyer SDK, a mobile analytics library.
Connect to remote URL and download payload 4.

Summary

The initial DEX is quite heavily obfuscated

  • Payload 1 (designmoji/nuff) has no other use than loading Payload 2
  • Payload 2 (nunber/seek) enables notification listeners (we havenā€™t detailed this in this article) and loads Payload 3
  • Payload 3 (xjuys/Yang) has yet more malicious code (not detailed here) and loads 2 additional DEX: one for Facebook, the other one contains Apps Flyer SDK.
  • Payload 4a and 4b: Facebook hooks + Apps Flyer SDK.

ā€” Cryptax

--

--

@cryptax

Mobile and IoT malware researcher. The postings on this account are solely my own opinion and do not represent my employer.