Modules and components
Zloader consists of different modules and components:
Downloader – initial infector
Backdoor – main module, exists in x86 and x64 versions
VNC module (x86 and x64)
Web Injects – received from C&C
Additional libraries (openssl, sqlite, zlib, Mozilla libraries)
Backdoors, VNC modules and additional libraries have assigned module IDs that are used by other components to refer to them.
Distribution
Zloader was distributed using classic email spam. In 2021 the attackers abused Google AdWords to advertise sites with fake Zoom communication tool which actually installed Zloader. Another campaign in 2021 used fake pornsites, where users needed to download additional software to watch video. Downloaders are distributed in a packed form sometimes signed with a valid digital signature.
Code peculiarities
Zloader code is very recognizable.
First of all, it is diluted with functions which will never be called. Downloader module may contain functions from the Backdoor module and vice versa. In total, about a half of the code will never be called.
Second, simple x86 instructions like CMP, ADD and XOR are replaced with special functions.
These functions contain a lot of useless code to complicate the analysis and they can call other “replacement” functions.
To add more insult to the injury multiple “replacement” functions exist for a particular instruction. Also some constants are calculated in runtime using aforementioned “replacement” functions.
Strings are encrypted with a simple XOR algorithm.
Samples have very little imported functions. APIs are resolved in runtime by the hashes of their names.
As a result, more than a half of the file size is useless and serves as an obfuscation of simple operations.
Configuration
Both Downloader and Backdoor modules have built in configuration encrypted with RC4.
The decryption key is stored in a plaintext and looks like vcvslrpvwwfanquofupxt.
The structure of earlier versions (1.0.x, for example) differs from later versions (1.6.x and 1.8.x). Modern versions store the following information in config:
Botnet name (divader on the picture below)
Campaign name (xls_s_2010)
List of hardcoded C&Cs
RC4 key (03d5ae30a0bd934a23b6a7f0756aa504)
Registry usage
Zloader modules (at least Downloaders and Backdoors) use a registry to store various data necessary for their work. The ROOT_KEY for this data is HKEY_CURRENT_USERSoftwareMicrosoft
The most important and interesting data structure, stored by the Zloader in the registry is called MAIN_STRUCT. It’s subkey in the ROOT_KEY and the value name is derived from the RC4 key found in the configuration. analysts suppose that bots from one actor use the same RC4 key, so they can easily find and read the MAIN_STRUCT.
MAIN_STRUCT is encrypted using RC4 with the key from the configuration. It stores:
Registry paths to other storages, used by Zloader
Files and directories path, used by Zloader
Encryption key(s) to decrypt those storages
Files usage
Root path is %APPDATA%. Zloader creates directories with random names inside it to store modules, stolen data and logs. These paths are stored into the MAIN_STRUCT.
Networking
As was mentioned before, communication between the bot and C&C is done using BinStorages.
Depending on the actual type of the message, field list may be changed, but there are 5 constant fields sent to C&C:
Some DWORD from the Configuration
Botnet name from the Configuration
BotID, derived from the system information
Debug flag from the Configuration
16 random bytes
Requests are encrypted using the RC4 key from the Configuration.
C&C responses are signed with RSA.
PING request
This request is used to check if C&C is alive.
Response contains only random bytes sent by a bot.
DOWNLOAD MODULE request
This request is used to download modules by their ID from the C&C.
The response is not in a BinStorage form!
GET CONFIG request
Used to receive configuration updates: new C&Cs, WebInjects, tasks for downloading etc.
C&Cs and DGA
As was shown before, built in configuration has a list of hardcoded C&Cs.
Actually, these lists have not changed for years. To bypass blocking of these hardcoded C&Cs, Zloader uses DGA – Domain Generation Algorithm.
In the Zloader, DGA produces 32 domains, based on the current date and RC4 key from the configuration.
There is a 3rd type of C&Cs – received in the response from the server.
They’re stored into the Registry.
Main function
Just after the start of the Downloader module, junk code is started.
It consists of many junk functions, which forms a kind of a “network”.
In the image below there is a call graph from just a single junk function. These functions also trying to read, write and delete some *.txt files %TEMP%. The purpose of this is to delay the execution of the payload and, analysts suppose, to complicate the emulation, debugging and analysis.
The second and the last task of the Main function is to start msiexec.exe and perform the PE injection of the code into it.
Injected data consists of two buffers: the big one, where the Downloader is stored in the encrypted form and the small one (0x42 bytes) with decryption code. Just after the injection Downloader terminates himself.
Injected code
Control flow passed to the small buffer, which decrypts the Downloader in the address space of msiexec.exe After the decryption, Downloader begins to execute its main task.
First of all, the injected code tries to read MAIN_STRUCT from the registry. If this fails, it thinks it was not installed on this system and the installation process begins: MAIN_STRUCT is created, Downloader module is copied into %APPDATA% and added to the autorun key HKCUSoftwareMicrosoftWindowsCurrentVersionRun with random value name.
In any case, the Backdoor module is requested from the disk or from the network and executed.
Backdoor module
Analysis based on version 1.6.28.0, c7441a27727069ce11f8d54676f8397e85301b4d65d4d722c6b239a495fd0282
There are actually two Backdoor modules: for 32-bit systems (moduleID 0x3EE) and for 64-bit systems (moduleID 0x3E9).
Downloader always requests a 32-bit Backdoor.
Backdoors are much more complicated than Downloaders. If analysts compare the size of our samples (after unpacking), Backdoor will be twice bigger.
Key Backdoor abilities:
Starting VNC module
Injecting WebInjects into the pages visited using browsers
Downloading and execute arbitrary file
Keylogging
Making screenshots
Stealing files and sending to C&C
Stealing files
The largest group of software from which Zloader steal files is crypto wallets:
Electrum
Ethereum
Exodus cryptowallet
Zcash
Bitcoin-Qt
Etc.
It also steals data from browsers: cookies from Chrome, Firefox and IE; saved logins from Chrome. And, finally, it is able to steal accounts information from Microsoft Outlook.
Hooking
To achieve his goals, Zloader performs WinAPI hooking. In order to perform it, Backdoor module enumerates processes and injects itself into the following ones:
explorer.exe
msiexec.exe
iexplore.exe
firefox.exe
chrome.exe
msedge.exe
64-bit version of Backdoor is injected into 64-bit processes, 32-bit version – into 32-bit processes.
Injected code hooks the following WinAPI functions:
NtCreateUserProcess
NtCreateThread
ZwDeviceIoControlFile
TranslateMessage
CertGetCertificateChain
CertVerifyCertificateChainPolicy
Hooks might be divided in 3 groups, depending on the purpose:
NtCreateUserProcess and NtCreateThread are hooked to inject a Backdoor module to newly created threads and processes.
ZwDeviceIoControlFile, CertGetCertificateChain and CertVerifyCertificateChainPolicy are hooked to support WebInjection mechanism
TranslateMessage is hooked to log the keys pressed and to create screenshots
Web Injecting
First of all, browsers must have a Backdoor module injected.
At this moment, there are multiple instances of Backdoor Modules running in the system: one, started by Downloader which is “Main Instance” and others, running in browsers.
Main Instance starts Man-in-the-browser proxy, other modules hooks ZwDeviceIoControlFile and cert-related WinAPIs (see above). Proxy port number is stored in the BinStorage structure into the Registry, so it is synchronized between Backdoor instances.
Hooked ZwDeviceIoControlFile function is waiting for IOCTL_AFD_CONNECT or IOCTL_AFD_SUPER_CONNECT and routing connections to the proxy. Hooked cert-related functions inform browsers what everything is good with certificates.
WebInjects
Injected code is usually small: from dozens of bytes up to 20 kb. To perform its tasks, it loads JavaScript code from external domains, controlled by bad guys. Analysis of these domains allowed us to find connections between Zloader operators and other cybercrime groups.