Malvertising campaign targeting IT teams with MadMxShell
Backdoor Details – Binary Analysis
Stage 1 injector
The analysis in this blog is based on this ZIP archive: Advanced-ip-scanner.zip (SHA256:7966ee1ae9042e7345a55aa98ddeb4f39133216438d67461c7ee39864292e015)
.
The ZIP archive contains two files:
Advanced-ip-scanner.exe
: A renamed copy of the legitimate Microsoft EXEoleview.exe
.IVIEWERS.dll
: A 22 MB DLL, which contains the stage two payload. This DLL is padded with an unused overlay of 10 MB which prevents scanning by security products that limit the size of analyzed files.
When Advanced-ip-scanner.exe
is run, it sideloads IVIEWERS.dll
which executes a series of heavily obfuscated shellcodes extracted from various locations within the .rsrc
section of the DLL. The final shellcode extracts and decodes an executable file with the XOR key 5dsadas435235bgdsgdfbvb3253453425345gfdsgfdgdf
from resource AT21
of the DLL and injects it into a new Advanced-ip-scanner.exe
process via process hollowing.
Stage 2 dropper
The injected EXE file contains the next stage payloads in resource ID 202
, encoded with a hardcoded 8-byte XOR key F2 09 CD 2D 85 CD 1D A3
and compressed with zlib. Each encoded byte in this resource is padded with seven null bytes, resulting in a 10MB file, likely as another anti-scanning technique. This is shown in the figure below.
Figure 4: The encoded and compressed stage 3 payload in the resource.
After decoding and decompressing the resource, two files, OneDrive.exe
and Secur32.dll
, are dropped into %LOCALAPPDATA%MicrosoftOneDriveUpdate
.
The dropper deletes the stage 1 EXE with the following command before executing the dropped OneDrive.exe
with ShellExecuteExW
:
cmd.exe /C for /l %x in (0,0,0) do (ping -n 3 127.0.0.1 > NUL & for %p in ("<PATH>Advanced-ip-scanner.exe") do (del /f /q %p & if not exist %p exit))
Stage 3 launcher
OneDrive.exe
, a legitimate signed Microsoft EXE, is abused to sideload Secur32.dll
which sets up persistence for OneDrive.exe
before executing the embedded stage 4 shellcode.
Data from Secur32.dll
’s icon resource ID 202
is XOR decoded to obtain the stage 4 shellcode. This is shown in the figure below.
Figure 5: The icon resource with the encoded stage 4 payload.
The first 16 bytes of the resource contain an encoded key for the payload that follows it. Each of the first 8 lowercase characters (onedrive) of the current process filename is added to every second byte of the encoded key to derive the XOR key F2 78 CD 9B 85 32 1D 07 33 C4 A0 21 98 A2 95 E3
, as shown in the figure below. This prevents the correct decoding of the next stage payload if Secur32.dll
was not sideloaded by OneDrive.exe
.
Figure 6: Generating the XOR key to decode the stage 3 shellcode.
The malware then attempts to disable Windows Defender by setting HKLMSOFTWAREPoliciesMicrosoftWindows DefenderDisableAntiSpyware
to 1
in the registry.
It configures a scheduled task named “OneDrive Update” that executes %LOCALAPPDATA%MicrosoftOneDriveUpdateOneDrive.exe
when the current user logs on to Windows before redirecting to the next stage.
Stage 4 backdoor
The shellcode is a backdoor that allows the threat actor to collect system information, execute commands via cmd.exe
, and perform basic file manipulation operations such as reading, writing, and deleting files.
To deter analysis and detection, the malware decodes the code of each function with an 8-byte XOR key F2 09 CD 2D 85 CD 1D A3
(same key used in stage 2), calls the function, and then immediately re-encodes the code. In the figure below, the code excerpt on the right is decoded from the original bytes on the left. We can observe that even after decoding, it still needs to perform an additional step of decoding the get_c2_domain
function before it can call it. The function code is re-encoded back to its original state before execution continues. This ensures that there is never a fully decoded copy of the shellcode in memory at any point of execution. Most sensitive strings and data, such as the C2 domain, lookup table for encoding/decoding C2 communications, and aforementioned XOR key, are also stored as stack strings to hinder analysis.
Figure 7: Function bytes before and after decoding. Note that the decoded function includes calls to decode and encode other functions called within it.
The malware generates a 4-byte session ID with the CryptGenRandom
API and a victim ID by concatenating the hard disk serial number, computer name, and username, and taking the first 8 bytes of its MD5 hash.
C2 Protocol
The malware communicates with the C2 server, litterbolo[.]com, by sending requests and receiving commands encoded within DNS MX queries and responses.
The malware supports the requests described in the table below.
Type | Name | Description |
0 | Heartbeat | Indicates that the malware is ready to accept the next command. |
1 | Registration | Sent as the first request of a session or when the C2 issues a re-registration command (type 1 command). |
2 | Command acknowledgement | Acknowledges the receipt of C2 commands. |
4 | System info command result | Contains system information collected for type 4 commands. |
5 | Shell command result | Contains shell output for type 5 commands. |
6 | File command result | Contains file and/or directory data for type 6 commands. |
Table 1: A table describing the requests supported by the malware during C2 communication.
Figure 8: A diagram depicting the MadMxShell C2 communication loop.
For each session, the malware first sends a registration request (type 1) to the C2 server.
Once the C2 server acknowledges the registration request, the malware sends a heartbeat request (type 0) to the C2 server.
The C2 server will respond with any of the following commands from the table below.
Command Type | Subcommand | Description |
0 | N/A | Sends a heartbeat. |
1 | N/A | Re-register with C2. |
2 | N/A | C2 acknowledges receipt of specified packet and indicates that the malware should send the next packet (for request messages split into multiple packets). |
4 | N/A |
Collects system information, like:
|
5 | 0 | Start cmd.exe process. |
1 | Terminate cmd.exe process. |
|
2 | Execute command via existing cmd.exe process created with subcommand ID 0 . |
|
6 | 0 | List files and directories if path is specified, otherwise list all drives. |
1 | Write or append content to file. | |
2 | Read from file. | |
3 | Delete file or directory. Files are deleted with the DeleteFileW API, while directories are deleted with this command: cmd.exe /c rmdir "<DIR_NAME>" /s /q . |
Table 2: The commands and subcommands supported by the malware.
The malware then acknowledges the command with a command acknowledgement request (type 2) before executing the specified command.
After completing the commands for types 4, 5, and 6, the malware sends the results to the C2 server. The malware then repeats the entire process by sending a heartbeat request (type 0) to retrieve the next command.
Data Encoding
The malware sends requests to the C2 server by encoding the data in the subdomain(s) of the Fully Qualified Domain Name (FQDN) in a DNS MX query packet. The C2 responds similarly by encoding its commands as subdomain(s) in the corresponding DNS MX response packet.
Each byte of binary data is converted into a pair of alphanumeric characters using a custom encoding scheme involving a hardcoded 36-character lookup table. Blocks of 60 alphanumeric characters are separated by a “.” character to represent a subdomain name. Python code for decoding these subdomains into the original request and C2 messages can be found in our GitHub repository.
Because the malware uses a maximum of 224 characters for the FQDN and the C2 domain name cannot be used to encode data, each DNS packet can only transfer up to 103 bytes. Requests and commands that exceed this size are split into multiple DNS packets and are sent sequentially after the other party has acknowledged receipt of the previous packet.
Possibly due to the limited bandwidth of the C2 protocol, this malware is configured with relatively short intervals (3 seconds) between requests. Because of this, its C2 traffic is significantly more noisy than the typical malware utilizing HTTP for C2 communication.
Commands received from the C2 (after decoding) are structured as shown in the table below.
Offset | Length | Name | Description |
0x0 | 4 | Query number | Starts from 0 per session. |
0x4 | 4 | Checksum | Adler-32 checksum of entire message data. |
0x8 | 4 | Packet number | A single message may be split into multiple packets. Starts from 0 for each message. |
0xC | 4 | Message length | Total length of the message. This field is only present in the first packet of a message. |
0x10 | Varies | Message data | The first byte of the message contains the command ID. The structure of subsequent bytes differs slightly for each command type. |
Table 3: The C2 message structure.
For example, the C2 server for this sample always responds with 33qqooggxr77mdxx88jj6600ev44yyzz9bee99wwuu.litterbolo.com
upon receiving a registration request. This is decoded as 00 00 00 00 03 00 0f 00 00 00 00 00 05 00 00 00 02 00 00 00 00
and represents the following message:
- Query number:
0
- Checksum:
0xF0003
- Packet number:
0
- Message length:
5
- Data:
02 00 00 00 00
(this is an acknowledgement from the C2 that it received packet0
)
Likewise, the requests sent to the C2 server (before encoding) are structured as shown in the table below.
Offset | Length | Name | Description |
0x0 | 4 | Session ID | An ID randomly generated when the malware is started. |
0x4 | 8 | Victim ID | The first 8 bytes of an MD5 hash of the hard disk serial number, computer name, and user name. |
0xc | 4 | Query number | Starts from 0 per session and is incremented for each DNS query sent to the C2 server. |
0x10 | 4 | Checksum | The Adler-32 checksum of entire message data. |
0x14 | 4 | Packet number | A single message may be split into multiple packets. Starts from 0 for each message. |
0x18 | 4 | Message length | Total length of the message. This field is only present in the first packet of a message. |
0x1c | Varies | Message data | The first byte of the message contains the request type. Data for the specific request follows it (for example: system information for request type 4). |
Table 4: The request message structure.