October 2020 saw the TrickBot Trojan, a prominent cybercrime gang’s tool of choice, suffer a takedown attempt by security vendors and law enforcement. Unfortunately, the takedown was not effective, and beyond coming back to life shortly after, TrickBot’s operators released a new and more persistent version of the malware.
In this post, IBM Trusteer examines the new TrickBot version versus its precedent and looks into the components its developers kept or modified.
What can be said about the TrickBot banking malware and botnet that has not been covered yet by the security community? After it emerged in 2016, built upon the ruins of the Dyre Trojan, TrickBot’s developers have not laid down their cyber-arms. Looking back at the past two years, not only has TrickBot continued to plague the online banking applications that cater to businesses, it has also ventured into collaborations with other elite cybercrime gangs. Additionally, it has worked with Ryuk and other ransomware on big game hunting attacks, deployed cryptominers and was a concerning factor in election interference in 2020.
Like many other botnets, TrickBot has garnered a lot of attention from law enforcement and suffered a takedown attempt in October 2020. Unfortunately, despite losing a large proportion of its infrastructure, TrickBot not only re-emerged, but it also launched a new, and more persistent version than ever, using a UEFI/BIOS bootkit to help it remain undetected on infected devices. This bootkit was dubbed TrickBoot by those who first analyzed and reported about it.
Our team at IBM Trusteer research examined what changed between the two most recent versions of the TrickBot malware. Let’s take a closer look at some of the components that keep TrickBot persistent and stealthy over time.
This comparison will look into a few major components from previous versions 1000512 and 1000513 versus the newer version 100003. Unusually, the version number jumped backward.
- Persistence mechanism
- Injection technique
- Bot configuration with a random twist
- Mutex naming concept
- Compromise check
Persistence Mechanism – Modified in New Version
Most malicious software developers implement some sort of persistence mechanism to ensure the malware is not wiped from the device on reboot. TrickBot’s long-standing persistence method uses a scheduled task that is set to run on set time lapses. This tactic was modified in the newer version.
In the previous version, the scheduled task appeared under the name Clean Master.
Figure 1: TrickBot’s scheduled task created under the task directory
This task’s executable file’s path is directly in the ‘Programs’ menu:
Figure 2: Task’s executable location
The malware further copies itself into a new subdirectory as part of its stealth tactics, thereby making Clean Master appear as yet another legitimate program and not suspicious at first sight.
In the new version, although TrickBot maintained the persistence mechanism of using the Windows Task Scheduler as the way to reload the malware, the task’s destination is now changed to a batch file. This is a stealthier choice by TrickBot’s developers, helping the malware evade scans by antivirus and security tools that typically look for malicious executables in the autorun and task scheduler.
Figure 3: Autorun snippet of the new task
A quick look into the batch file location exposes TrickBot’s executable, named ‘newb’ in this case.
Figure 4: TrickBot’s batch file along its executable
Further in the batch file, we also see an obfuscated script:
Figure 5: A part of TrickBot’s obfuscated batch file
De-obfuscating the script reveals its more obvious purpose as running the TrickBot executable (newb.exe) from the following patch:
|start C:\Users\[name here]\AppData\Roaming\Identities1793959193\newb.exe
Scroll to view full table
Choice of Injection Mechanism – Retained
The injection of malicious code into legitimate Windows processes is one of the most common tactics malware developers use. The code injection can take different forms, but a highly popular way to implement code injection is process hollowing, in which legitimate content is removed and replaced by the attacker’s code.
TrickBot uses process hollowing as its code injection tactic, and that has remained the same in the previous and current versions of the malware. This method has a couple of advantages:
- Allows for the termination of the main suspicious process
- Presents the malware’s operations as being performed by legitimate processes
Here’s what TrickBot’s process hollowing does:
- Creates process wermgr.exe in suspend mode using CreateProcessInternalW. This Windows process is inherently responsible for handling errors.
- Allocates memory for its payload shellcode using NtAllocateVirtualMemory
- Writes into memory using NtWriteVirtualMemory
- Reads remote process’s Process Environment Block (PEB) using NtQueryInformationProcess
- Reads first module wermgr.exe’s address using the PEB structure
- Goes to the 0xF0+0x28=0x118 offset in the wermgr.exe address to find its entry point:
Figure 6: Wermgr’s entry-point address
- Writes a trampoline to the entry point 0x80F0 and the module’s base address to jump to the shellcode using NtWriteVirtualMemory. A trampoline is a small piece of code which is constructed on the fly on the stack when the address of a nested function is taken.
- Calls NtResumeThread to resume the thread.
Figure 7: Example of TrickBot’s trampoline
Bot Configuration Receives Randomization Twist
Bot configuration is the way the malware configures its own file on initial setup when a new machine is infected or when it is updated on infected devices. The initial configuration contains data such as encryption keys, IDs, credentials, URLs and communication patterns it will use to send information to its botmaster.
Bot configurations are easy to modify and are changed by malware operators in their various campaigns and attacks, offering agility and stealth.
TrickBot’s initial configuration elements are traditionally split between its embedded XML ‘mcconf’ configuration file and Base64 encrypted strings stored within the unpacked TrickBot core. The ‘mcconf’ file contains a list of C2 server IP addresses, along with the TrickBot version number, Bot ID and default modules. Remaining configuration elements such as install directory and scheduled task name are stored as custom Base64 encoded strings.
TrickBot retained the same bot configuration scheme from its previous versions and continued to use the same one in current versions, only this time, it added some randomization to data inside the file to delay detection and analysis.
When we looked at the details, we saw that only task names have been modified, but all the data and purposes remain the same. We will come back to task names later.
Figure 8: TrickBot configuration elements from decrypted base64 strings — excerpt comparison from previous and current versions
TrickBot’s configuration is embedded within the unpacked TrickBot core binaries. The extraction process takes place as follows:
- Upon execution, TrickBot is unpacked. TrickBot makes use of a variety of different packing techniques; in this case, the malware is stored as a resource of the parent executable and decrypted using a modified implementation of the RC4 cipher with a hardcoded key embedded within the file. This technique is also commonly used by Emotet.
The only difference between the standard RC4 and this modified version is the change of the standard RC4 constant value from 256 to 1147.
- The resulting binary is the TrickBot Loader. This is a highly obfuscated binary that decrypts its other functions and payloads as required using a XOR operation. This loader is responsible for decrypting and loading the TrickBot core binaries. The loader decrypts the appropriate 32/64 bit core binary using XOR and decompresses it using an LZO algorithm.
- Within the TrickBot core binary, the ‘mcconf’ configuration file is embedded and encrypted using AES and XOR. The binary also contains a list of custom base64 encoded strings separated by the NULL byte ‘\x00’.
Figure 9: Part of the encoded TrickBot configuration, separated by NULL bytes
- The last string is picked to become a custom Base64 encoding index.
- When required, every string the malware calls is then pushed to a Base64 decoding function that uses the custom index to decode the configuration. This way, the specific configuration is in plaintext only when it’s used, which can make both dynamic and static analysis by outsiders take longer.
The Base64 binary data encoding uses an index table of 64 characters, which typically includes basic characters such as: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
With TrickBot’s configuration, the index table used in our sample was:
A closer look revealed that TrickBot’s encryption methods are customized by its developers. For example, Trickbot uses different implementation for the RC4 cipher and a modified Base64 decoding algorithm, incorporating a custom table in order to make analysis more difficult. These choices are likely there since most crypto detection scripts are not likely to find such functions automatically.
Bot Configuration Changes
In the beginning of this section, we mentioned that only task names in the bot configuration were modified. These names change frequently and, in the newer samples, task names are appended a randomized 10-digit number that modifies the name each time. For example, for the task name ‘identities’ we will now see a string like ‘Identities1793959193’. The developer likely uses this random twist to eliminate the ability to search for constants with detection tools.
The randomization itself is achieved by a couple of additional calculations and XOR operations on two values that TrickBot fetches. In this case, it uses the result that is produced at that moment from the computer’s processor’s read time-stamp counter command (RDTSC) and the result from the Windows GetTickCount  function.
Fully Randomized Mutex Naming – Retained
The mutex — the mutual exclusion object that synchronizes access to a resource — is very commonly used by malware developers. As a result, mutexes are part of the indicators of compromise to look for when trying to determine if a device has been infected by specific malware. Searching for mutexes is also something malware does to ensure it does not re-infect a device and cause instability, or to kill the processes of a rival malware.
TrickBot uses a mutex naming algorithm to create random, unique mutexes across infected devices that it manages to control. Since mutexes are a definitive indicator of compromise, TrickBot’s developers were creative in creating the algorithm used here, staying away from relying on system artifacts that can be more easily figured out.
In current versions, TrickBot’s mutexes are created as fully randomized 32-digits consisting of a 16- byte globally unique identifier (GUID).
Figure 10: An example of a TrickBot mutex name
In the process of creating the mutex name, ‘get_random’, TrickBot splits it into two parts:
- Random [8 Random bytes]
- Related [8 Related bytes]
To randomize the strings, TrickBot uses the GetTickCount function and the RDTSC assembly instruction.
Figure 11: TrickBot’s simple get_random function
The second part, or ‘related part’, is built upon the first. It’s a combination of some XORing operations of the first, ‘random part’ with the computer’s volume C serial number. Finally, the Windows StringFromCLSID  function is used to give the mutex its GUID form.
What’s important in the mutex name here is not the value, but the correlation between its first and second halves.
Previous Version Checks
Before the TrickBot malware infects a device, it runs a detection process to ensure that device has not already been infected.
This detection takes us back to TrickBot’s mutex, which is what it looks for on the device. Since mutex names are randomized, it cannot directly look for a name. Rather, it examines the relation between the first half and the second half of the mutex, and then infers whether the resulting GUID has or has not been generated in the past.
Let’s take a closer look at the mutex enumeration process that TrickBot performs:
- It. begins by enumerating all system handles. In Windows-based devices, a handle is a pointer to an object, such as a mutex, a file, etc. The malware does that by calling the ZwQueryInformation Native API with SYSTEM_HANDLE_INFORMATION (0x10) as the parameter.
- Next, it uses the NtQueryObject function it queries for information about each object, and in our case each handle, to search mutex names.
- Then it uses the OpenProcess function to open the process the mutex handle belongs to.
- Lastly, it uses the DuplicateHandle function to duplicate the handle to that mutex so it can access it.
Note that the first two functions are Windows Native APIs belonging to the NTDLL.dll library. Usually, when calling a Windows API function from the KERNEL32.dll, it calls its Windows Native API counterpart function in NTDLL.dll that address the Windows kernel.
At this point, if the device is deemed infected, TrickBot initiates an ExitProcess to abandon a second installation of the malware.
TrickBot Lives On – A Reminder to Stay Vigilant
As we kick off 2021, the TrickBot Trojan and the cybercrime syndicate around it are in full swing, operating on the bank fraud front as well as high-stakes ransomware attacks.
If your security team detects TrickBot on networked devices, those should become high priority to clean or reimage as needed. This malware can be a foot in the door for a number of attacks, the worst of which can be an all-out ransomware and extortion operation against your organization.
IBM Trusteer fights threats like TrickBot and has been helping customers mitigate attacks since 2006. Our fraud detection and advanced risk-based authentication help banks protect consumers and businesses, and our research team is pivotal in detecting highly modular, modern-day malware like TrickBot and its components.
To learn more about IBM Trusteer, visit www.ibm.com/security/fraud-protection/trusteer.
 RDTSC loads the current value of the processor’s time-stamp counter into the EDX:EAX registers.
 Retrieves the number of milliseconds that have elapsed since the system was started, up to 49.7 days.
 The StringFromCLSID function converts a CLSID into a string of printable characters. Different CLSIDs will convert to different strings.
 The Native API is a lightweight application programming interface (API) used by Windows NT and user mode applications.