An In-depth Look at MailTo Ransomware, Part One of Three
In February, an Australian transportation company called Toll Group was hit by a ransomware attack that reportedly spread to over 1000 servers and caused major disruption for the company and its clients. Recently the same ransomware family was seen attached to phishing emails targeting people's fear of COVID-19, a trend we've also been seeing quite a bit of. We got a hold of a sample of the ransomware and decided to take a closer look to see what makes it tick. The ransomware in question is named MailTo but also NetWalker. MailTo was a name given to the ransomware based on the format of the encrypted file names. NetWalker was a name given based on the ransomware’s decryption tool. In this blog, we will refer to the ransomware as MailTo.
This series of blog posts will cover the internals of how the MailTo ransomware works, but as a start, here's an overview of the full attack flow:
Initialize and Install
The MailTo ransomware initialization involves the following steps:
- Resolving obfuscated API calls
- Configuration Decryption and Parsing
- Data collection
- Persistence and Installation
Resolving Obfuscated API Calls
Doing basic static analysis on the MailTo ransomware, it is apparent that the ransomware is obfuscating many of its API calls due to a lack of found imports.
Figure 2 – MainTo Imports Unresolved
This is more apparent when opening the ransomware in a disassembler and analyzing the first function call. Inside of the first function call, we can see hardcoded CRC32 hashes for module and function names.
We can quickly denote that an array of function pointers is being built with the function pointer addresses being resolved through a function iterating over the exports of a module, hashing the name of the export with CRC32 and then comparing it with a hardcoded CRC32 hash to know if it has the correct address. A list of loaded modules is scanned to find if the module for the export is loaded or not. If the module is found to not be loaded, it is loaded into memory via “LdrLoadDll” and added to a list of loaded modules.
Figure 4 – MailTo API Call Resolving
The modules are also being resolved in a similar way but work differently by iterating over the “InLoadOrderModuleList” located in the processes process environment block (PEB) and comparing a CRC32 hash of the iterated “InLoadOrderModuleList”’s “FullDllName->Buffer” member.
Figure 5 – MailTo Module Resolving
In the sample we analyzed, a total of 149 function calls were resolved, with many being undocumented functions such as “NtGetContextThread”, “NtQueueApcThread”, and more.
Configuration Decryption and Parsing
The configuration for the MailTo ransomware can be found under the resource section of the executable as a resource labeled with the name “1337”.
Figure 6 – Encrypted Configuration Resource (Resource Hacker)
The configuration is extracted using typical resource extraction functions such as “FindResource”, “LoadResource”, “LockResource”, and “SizeOfResource”.'
Figure 7 – Function Used for Retrieving the Resource
One function of interest to note is the “FindModuleBase” (not apart of the standard Windows API). We suspect this function is used in place of the “GetModuleHandle” Windows API function as when the ransomware is injected, it is not linked in the PEB->InLoadOrderModuleList meaning that “GetModuleHandle” will not be able to return the image base of the ransomware, thus leaving the ransomware to resolve the image base on its own. This function works by ANDing the address of itself with “0xFFFFF000”, this gives us the start of the memory page that the code relies on. The ransomware then subtracts by 512 bytes until the ransomware reaches a “MZ” header. The expected “MZ” header will be the start of the ransomware mapped file itself.
Figure 8 – Returns Image Base of Ransomware
The configuration is encrypted using the RC4 algorithm. Luckily the key and key length are easily determined by the first bytes of the resource. In this sample the first four bytes determine the length of the RC4 encryption key. The following bytes dictated by the previous read length, is the encryption key. This encryption key is then used with the RC4 algorithm over the size of the entire resource to decrypt the ransomware’s configuration. The decrypted configuration data is finally parsed into a global structure.
Figure 9 – Encryption on the Left, Decryption on the Right
The below table is a description of the configuration of the MailTo ransomware.
One field of interest is “mpk”. We presume this field stands for “my public key” as this is a base64 encoding of the attacker’s public key. This field is of interest to us because it is one of the first indicators that the ransomware's encryption will not be decryptable without the attacker’s private key. “white”, “kill”, “net”, and “unlocker” are also fields of interest as they help us guess the functionality we should see within the ransomware.
There are two main global structures used throughout the MailTo ransomware. One structure contains data about the system and holds information for encryption, and the other structure contains data that has been parsed from the configuration. The first structure we named “MachineInfo” and has much of its data initialized right after the configuration has finished decrypting. The “MachineInfo” structures holds, and is initialized with, some of the following data:
- Major/Minor version of operating system
- If the operating system is 64bit or not
- If the ransomware is running under the local system account
- If the ransomware is running with TokenElevationTypeFull
- Process ID of the ransomware
- CRC32 hash of its process name
- Various encryption data (encryption keys, length, hashes, data, etc)
- Ransomware file path
- Ransomware name length and path length
The data in this structure is read from, and wrote to, throughout the ransomware’s execution.
Persistence and Installation
One of the first installation steps the MailTo ransomware will take is to generate a unique name with a size based on the field “namesz”, in this sample, 8 characters.
The next step is to find out if the ransomware process is running under SysWOW64. If the ransomware determines that it is running under SysWOW64, then it will create a copy of itself to the following path:
- Program Files (x86)/<uniqueName>/<uniqueName.exe>
Otherwise, if the ransomware determines that the opposite is true, it will copy itself to the following path:
- Program Files/<uniqueName>/<uniqueName.exe>
If the ransomware has been executed without administrative privileges, it will copy the file to:
After it has been copied to a path, the ransomware will delete itself from the original execution location.
MailTo makes use of registry keys to store encryption keys and to set up persistence on the victim’s machine.
When the ransomware sets up a registry key for persistence it will make use of the following registry key:
A value is then placed under this registry key with a path to the ransomware:
Figure 11 – Persistence registry key
If the ransomware fails to place the value at this registry key (often when it has not been run with administrative privileges), it will attempt to place the value under this registry key instead:
MailTo also creates its own registry key and value named under its generated unique name. The value holds a 140-byte binary blob of data which stores encryption key information necessary for encryption and decryption (used with the attacker's decryptor which has their private key).
At this point, MailTo has installed itself on the victim's system, initialized all of the important configuration options (like the encryption keys it will use) and, finally, set up a process for persistence so that the malware will be able to relaunch itself even after a reboot. In the next two parts of this series, we'll show you how the malware executes, embeds itself and starts the process of encrypting the victim's valuable data.