This article explains how to unpack sample sha256 5b9049c392eaf83b12b98419f14ece1b00042592b003a17e4e6f0fb466281368
which was served from http://videofullizlesite9356[.]site/ApiServices-Files92752/Down at the beginning of January 2022 (see this tweet). The malware poses as a Video player and appears to be a member of the Bian Lian malware family (see former analysis 1 and 2). Although the malware has similarities with BankBot, I believe this precise sample is not a banker malware (it does not attempt to steal your banking credentials or steal from your bank account) but the Bian Lian bot (bulk send of SMS, USSD calls etc).
Update Jan 17, 2022. Let’s try and clarify. Bian Lian is a “generic” bot. It may be used to steal passwords of banking apps. Some current samples seem to be particularly interested in stealing credentials from turkish banks.
Kudos to @U039b with whom I began this reverse engineering, and @ReBensk, @malwrhunterteam.
Summary (spoiler?) for those who don’t want to read it all :)
The malware does not use
DexClassLoader
to unpack the payload DEX. Instead it loads the payload as a secondary DEX through multidex support. The packer re-implements multidex support and mainly changes names & adds asset decryption.You can use my Java program to decrypt the asset and access the payload.
What makes this sample difficult to unpack
The most common packing mechanism consists in loading a hidden DEX with DexClassLoader
. The sample does not use DexClassLoader
(nor PathClassLoader
or InMemoryDexClassLoader
). Therefore, we cannot unpack by creating a hook on DexClassLoader
that dumps its first file argument.
Many dynamic tools fail (let me know if you find one that works): RMS times out while trying to launch the app, House fails, and Dexcalibur fails to load the malware’s project due to a bug.
This malware uses another mechanism to side load its payload. I’ll discuss at the end of the article (section “So, how is the DEX loaded if not with DexClassLoader?”). But first, let’s unpack, because actually if your goal is to analyze the payload, you don’t really need to understand how it is loaded.
Detecting it is packed
The main activity is com.pmmynubv.nommztx.MainActivity
, which is not present in the wrapping APK but in the contained payload.
Unpacking
Understanding the packing mechanism takes a little bit of time, because all strings are obfuscated (fortunately JEB decrypts nearly all of them) and DexClassLoader
— typically to load a DEX — is not used.
The flow is the following. The manifest references com.brazzers.naughty.g
as the application. Indeed, g
extends Application
and can be seen as the main entry point of the app. One of the first methods to be called is the protected method attachBaseContext
.
From attachBaseContext
, the malware calls a cascade of functions which (1) locate an asset named G9ugwFtlG1.jwi
, (2) deflates it and (3) finally decrypts it using a home-made algorithm with hard coded key GIUh9JHGUIGIUHGokfewrofij58YV6UhYUF7gjhgv
.
The strings G9ugwFtlG1, .jwi, GIUh9JHGUIGIUHGokfewrofij58YV6UhYUF7gjhgv
are found in a malware’s configuration class com.brazzers.naughty.h, but note they are all obfuscated.
The obfuscation is not complex: a XOR with a fixed character, nevertheless I was happy JEB did the work automatically for me!
If you want to follow the calls:
- com.brazzers.naughty.g.attachBaseContext(Context)
- com.brazzers.naughty.a.a(Context)
- com.brazzers.naughty.a.a(Context, File, File…)
- com.brazzers.naughty.b.a(Context, String…)
- com.brazzers.naughty.b.c()
- com.brazzers.naughty.b.a(ZipFile, ZipEntry…)
- com.brazzers.naughty.k.a(String, InputStream, OutputStream)
We’ll see later the malware is actually following the normal flow for loading secondary DEXes, except the names are obfuscated.
Automating the unpacking
I basically copied the malware’s unpacking code in com.brazzers.naughty.k.a
, did a little adaptation, and finally worked out a Java program that automatically unpacks the malware (get the code here). Run the program in the directory where G9ugwFtIG1.jwi
is available (./assets/7G8Uwty
), and it will unpack and create a unpacked.zip
which contains the payload DEX.
$ unzip -l unpacked.zip
Archive: unpacked.zip
Length Date Time Name
--------- ---------- ----- ----
906456 2022-01-14 11:05 classes.dex
--------- -------
906456 1 file
So, how is the DEX loaded if not with DexClassLoader?
The malware uses the multidex scheme to load the payload as secondary DEX. This method has existed for a couple of years (e.g. Android/Rootnik using it in 2017), but I hadn’t seen it for a while. In 2022, it seems we have a new packer in the wild which uses this technique as the same packer is used here in a sample of Flubot.
The technique consists in re-writing the way applications load multiple DEX. The Android code can be found here. The classes MultiDex
and MultiDexApplication
are the core of the functionality. They implement support of APKs with multiple DEX. Everything begins in indeed in attachBaseContext
of MultiDexApplication.
The malware re-implements MultiDexApplication
, MultiDex
and MultiDexExtractor
with little changes part code re-organization and obfuscated names:
MultiDexApplication
is found incom.brazzers.naughty.g
MultiDex
is within incom.brazzers.naughty.a
- and
MultiDexExtractor
iscom.brazzers.naughty.b
The two main functional changes are :
- Changes in file and folder names. The extracted DEX will be located in a directory named
hf8U6UUIwiqaGgo
instead of the standardsecondary-dexes
name, the extracted suffix will be.weg
instead of.zip
, and some other minor details like the lock file name is changed toT9etIiaI.uw87
instead ofMultiDex.lock
. The goal is obviously to complicate reverse engineering, but also to make the files less noticeable should they be spotted during extraction on the device. - Deflating and decryption of the secondary DEXes. Compare the original code with the malware’s version below.
The next article will deal with the reverse engineering of the payload DEX.
More recent samples of January 14 (today)
Some newer samples of that malicious video application have been released today: see Twitter. I haven’t looked in all samples yet, but at least the first one, 01658_Video_Oynatıcı.apk (sha256: d105764cd5383acacd463517691a0a7578847a8174664fc2c1da5efd8a30719d
) does not use the same packer. It uses the common DexClassLoader
method, actually the same packing mechanism as this sample. Watch for the unpacked payload in a file named maXclr.json
.
generic_x86_64:/data/data/com.friend.bronze/app_DynamicOptDex # ls
maXclr.json maXclr.json.prof
The payload DEX (maXclr.json
) is a Bian Lian sample.
— the Crypto Girl