The team of expert analysts at GoSecure Titan labs have reverse-engineered a new TrickBot cleverly hidden in a Zoom job interview email through a sample obtained from GoSecure Titan Inbox Detection and Response (IDR). The email message contained a shortcut (LNK) file entitled Interview_details.lnk and that LNK file downloads a loader which will be examined in this blog. GoSecure Titan Labs named the loader TrickGate because it uses the Heaven’s Gate technique to load TrickBot, one of the world’s most prevalent botnets.
The initial infection vector is via malspam. The email (906379938be59269713995cf29058f42), shown in Figure 1, is entitled FINAL interview – September 3 and congratulates the user on passing an internal interview. It provides a link purporting to be zoom details for a final interview. The link downloads an LNK file (6e49d82395b641a449c85bfa37dbbbc2) from hxxps://workdrive[.]zohoexternal[.]com/file/6c8ha295582e90c3e4655b87b82bb100f011b.
Figure 1: Zoom Interview Malspam
Once executed, the LNK file, displayed in Figure 2, opens Notepad as a decoy, then uses curl –silent to download TrickGate, a 32-bit C/C++ compiled portable executable (PE), from hxxp://185[.]14[.]31[.]112/images/moonfrontmars[.]png. The LNK file then saves TrickGate (442f1e3d2825d51810bf9929f46439d2) in the %TEMP% directory as tmp.exe and executes it using the start command.
Figure 2: LNK Contents
In TrickGate’s .rsrc section, the file HTML/DATA contains over 255 KB of encrypted shellcode. The shellcode is decrypted directly in the .rsrc section using the decryption key planbetufernasoberpalade. It should be noted that the decryption key varies from sample to sample. The decryption routine is depicted in Figure 3.
Figure 3: TrickGate’s Initial Decryption Routine
Once decrypted, the shellcode (87dc309108bbf70e3e67efbf9d4c09da) is copied to memory and executed there. Besides executable code, the shellcode also contains an encrypted 64-bit portable executable. Figure 4 shows the PE in the process of being decrypted. As can be observed from the decryption routine, the decryption simply involves XORing a byte from the decryption key with a byte from the encrypted PE. The decrypted PE (8da11d870336c1c32ba521fd62e6f55b) only contains headers and a .text section, which is later written to yet another section of memory.
Figure 4: 64-bit PE Decryption Routine
Next, the shellcode calls kernel32.CreateProcessInternalW, as depicted in Figure 5. Since the second parameter, lpApplicationName, is null, the process to be created is specified by the third parameter, lpCommandLine, which contains a pointer to the path for Windows Error Reporting Manager (wermgr.exe). The seventh parameter, dwCreationFlags, which specifies flags that define options for the created process, contains the value 0x800000C. This value corresponds to the flags CREATE_NO_WINDOW, DETACHED_PROCESS, and CREATE_SUSPENDED. Thus, wermgr.exe will be created in a suspended state, without a console window. This is the beginning of process hollowing, a technique used to inject and execute malware in a legitimate process.
Figure 5: Create Suspended wermgr.exe Process
At this point, we expected to simply continue stepping through the disassembled code and observe the remaining process hollowing steps. However, as displayed in Figure 6, the shellcode makes a far call to 0x33:2F60011, which in turn, makes a call to 0x10001000, which is where the 64-bit code from the decrypted PE’s .text section is located. Also displayed in Figure 6, on the left, is Process Hacker, which shows the process wermgr.exe outlined in black, signifying that it is suspended. When we try to step into the far call, instead of stepping into the instructions at address 0x2F60011, the debugger executes for a few moments, then the instruction pointer returns to the previous function. Afterwards, wermgr.exe is no longer outlined in black, meaning that something has resumed the process, but we could not observe it being resumed or whether code was injected into it before it was resumed. Furthermore, setting breakpoints on API calls associated with process hollowing did not cause the debugger to pause. So, what just happened? Enter Heaven’s Gate.
Figure 6: Far Call
Heaven’s Gate, first introduced in 2009, is a technique used to execute 64-bit code from a 32-bit process by using a far call, far return, or far jump. Unlike regular calls, jumps, and returns, which only specify the memory address, far ones also specify the code segment, allowing them to call, jump, or return to a different code segment. 0x23 specifies a 32-bit code segment whereas 0x33 specifies a 64-bit code segment. Thus, when 0x33 is specified with a far call within a 32-bit process, it switches the context of the 32-bit process to that of a 64-bit process. Since we are analyzing the sample with x32dbg, which can only analyze 32-bit code, the debugger is not capable of handling the process after it switches to 64-bit, and we only regain control of the process when it returns from the far call and reverts back to 32-bit. Most debuggers will behave in the same manner, except for WinDbg, a debugger created by Microsoft that can debug both 32-bit and 64-bit code. Using WinDbg, we can step seamlessly through Heaven’s Gate and analyze the 64-bit code being executed. Figure 7 displays the disassembly in WinDbg before and after crossing Heaven’s Gate. We can see that the registers before the call pertain to a 32-bit architecture whereas 64-bit registers are being used after the call. Moreover, the code segment (CS) register now holds the value 0x33.
Figure 7: Stepping Through Heaven’s Gate
Even though WinDbg can handle the context switch, it is still confused in regard to breakpoints on API calls. This fact is illustrated in Figure 8. When a breakpoint is set for ntdll.NtWriteVirtualMemory, WinDbg sets it for the 32-bit ntdll.dll, as revealed by the x86 identifier and ntdll.dll’s address, 0x77912d70, which falls in the 32-bit address space. However, the actual version of ntdll.NtWriteVirtualMemory being called by TrickGate is 64-bit, as its address, 0x7ff8’570ed4a0, lies in the 64-bit address space. Therefore, the debugger will not pause at the requested breakpoint unless it is manually set at the appropriate address. This exemplifies just how pernicious Heaven’s Gate can be. By hiding API calls, it makes malware detection and analysis very difficult. This is why Heaven’s Gate was initially used by many malware authors. However, the use of Heaven’s Gate has greatly declined since Microsoft introduced Control Flow Guard (CFG) in Windows 8.1. CFG places restrictions on addresses called by executing code and, as such, can mitigate Heaven’s Gate. There has been some malware in recent years, such as HawkEye Reborn Keylogger and Remcos RAT, abusing Heaven’s Gate to avoid detection. Publications on the topic state that malware still using Heaven’s Gate does so to target legacy machines, since CFG should terminate the execution on modern systems. However, we at GoSecure Titan Labs ran TrickGate on a Windows 10 machine with CFG enabled, and it fully executed.
Figure 8: Call to ntdll.NtWriteVirtualMemory
As anticipated, the 64-bit shellcode in Heaven’s Gate completes the process hollowing that begin in the 32-bit shellcode. Looking once again at Figure 8, we see that the value in rdx is 0x7ff7a77a650. This is the second argument passed to ntdll.NtWriteVirtualMemory and it specifies the base address to where data should be written. Also displayed in Figure 8 is the memory map view in x64dbg, which we had opened at this point and attached the suspended wermgr.exe process to. It can be seen that the base address to be written to falls within the .text section of wermgr.exe. r8 contains an address to the buffer containing the bytes to be written and r9 contains the number of bytes to be written, which is 0x10, or 16 in decimal. The memory window in the top right corner displays the data stored at the address in r8. Therefore, the call to ntdll.NtWriteVirtualMemory writes the bytes 48 b8 00 10 6f 9d d0 01 00 00 40 0b c0 50 c3 00 to the .text section of wermgr.exe. The 64-bit shellcode then calls ntdll.NtResumeThread to resume the execution of wermgr.exe, completing the process hollowing. Before wermgr.exe was resumed, we placed a breakpoint on the address in wermgr.exe where the bytes were written. As displayed in Figure 9, these bytes replace the return address of the current function with the address 0x1D09D6f1000 and then returns, passing execution to that address.
Figure 9: Injected Code in wermgr.exe
So, what exactly is stored at this address? Back in Trickgate’s 64-bit shellcode, another call to ntdll.NtWriteVirtualMemory was made before resuming wermgr.exe. As can be observed from Figure 10, 0x28bd4 bytes, which is a little over 166 KB, was written to memory beginning at address 0x1D09D6f0000. This written shellcode is TrickBot (8da11d870336c1c32ba521fd62e6f55b), the entry point to which is at address 0x1D09D6f1000. Thus, TrickGate’s 64-bit shellcode injected code into wermgr.exe so that it would execute a section of memory containing TrickBot. Therefore, TrickBot is executed disguised as Microsoft’s Windows Error Reporting Manager.
Figure 10: ntdll.NtWriteVirtualMemory Writing TrickBot To Memory
TrickBot’s Latest Variant
As TrickBot is very well-known malware, discussed in many publications, we will only focus on interesting aspects of the current TrickBot variant. It creates a folder in the C:\Users\<username>AppData\Roaming\ directory. The folder’s name is UniLiteGames with 4 characters appended to it, such as UniLiteGames5UIH. It then copies the original PE, TrickGate, and an obfuscated batch file, named command.bat to this folder. The batch file, shown in Figure 11, is obfuscated with simple string replacements. Once deobfuscated, the file contains the command start C:\Users\<username>\AppData\Roaming\UniLiteGames<4-characters>\<trickgate-pe-name>.
Figure 11: Obfuscated Batch File
TrickBot then creates a COM object for an interface of Task Scheduler, which it uses to create a scheduled task to run command.bat every time the user logs on, as depicted in Figure 12. The name of the scheduled task is UniGamesSoft followed by the same 4 characters used when creating the aforementioned folder, and the Author is UniGamesSoft.
Figure 12: TrickGate Scheduled To Execute at Logon
TrickBot contains 18 command and control (C2) IP addresses, listed in the IoCs section below. All C2 communication occurs over HTTPS and uses Windows HTTP Services (WinHTTP), as can be seen in Figure 13, which displays the initial check-in. The third argument passed to winhttp.HttpOpenRequest, which creates the HTTP request handle, is /rob128/<computer_name>_W10019077.19D16C537142D197E33B9D65DF03B33E/5/file/, which specifies the path on the target server. All following information sent to the C2 server is sent in similar GET requests. For example, information pertaining to the victim machine’s network address translation (NAT) status is sent as /rob128/<computer_name>_W10019077.33A1A5DD03BBFF0FD7BA9BB14F9FBCDF/14/NAT%20status/client%20is%20behind%20NAT/0/. As this demonstrates, the data sent to and from the C2 server is not encrypted or obfuscated in any way, presumably since TrickBot is using HTTPS to encrypt communication.
Figure 13: TrickBot’s Check-in Request
The C2 URL path follows the same format observed in previous variants of TrickBot. rob128 follows TrickBot’s convention of using alphabetic characters followed by a decimal value at the beginning of the path. rob128 was observed in all other samples of the current campaign. Next is the computer name of the compromised machine, followed by _W, which is hardcoded in all TrickBot samples we have encountered. A decimal number always follows the _W. Next is a decimal followed by a hexidecimal string 32 characters long. This string is created based on system time and involves using the function kernel32.GetTickCount and the instruction RDTSC, which is a time stamp counter. The next value in the path appears to signify the type of request being made and corresponds to values used in a switch statement that controls the flow of requests, displayed in Figure 14. For example, the initial check-in, which was created in case 5, has the value 5 for this part of its path. Likewise, the URL containing the NAT status uses the value 14, as it was created in the function corresponding to case 14.
Figure 14: C2 Communication Switch Statement
An interesting feature observed in this variant is that after TrickBot obtains the public IP address of the victim machine, it will query IP blacklist services to determine the reputation of the IP address. As we can see in Figure 15, TrickBot calls ws2_32.getaddrinfo, which queries information about a specified IP. The value passed to its first parameter is .zen.spamhaus.org. zen.spamhaus.org is a domain name system blacklist (DNSBL) service. Prepended to this is the victim machine’s IP address in reverse order. TrickBot also uses other DNSBL services to check the victim machine’s IP address. These include cbl.abuseat.org, b.barracudacentral.org, dnsbl-1.uceprotect.net, and spam.dnsbl.sorbs.net.
Figure 15: IP Reputation Check
TrickBot will then send a request to its C2 server stating the results of the reputation checks. As displayed in Figure 16, an example of the URL path generated for such requests is rob128/<computer_name>_W10019077.33A1A5DD03BBFF0FD 7BA9BB14F9FBCDF/14/DNSBL/not%20listed/0/. Of course, if any of the DNSBL services report the IP as blacklisted, not%20listed will be changed to listed in the URL path.
Figure 16: Reporting DNSBL Status to C2 Server
The notorious botnet and information stealer, TrickBot, has remained active since 2016 and continues to live up to its name, as it regularly incorporates new tricks into its already long list of abilities. TrickGate Loader is the latest addition to those tricks, and a very impressive one at that, since its use of Heaven’s Gate allows it to effectively conceal API calls used to load TrickBot.
Through close monitoring, analyzing, and reverse engineering, GoSecure Titan Labs, as part of our GoSecure Titan Managed Detection and Response offering, have created signatures to detect the emerging threats discussed in this report. One such signature, listed below in the Detection section, is a file detection signature for the TrickBot shellcode entitled malware_trickbot_4, which was created using binlex, an opensource genetic binary trait lexer library and utility. By unpacking TrickBot shellcode from numerous samples of TrickGate, we were able to utilize binlex to extract the common traits and thus, to create an effective signature.
Increased work from home and remote work have led to a rise in these types of threats for users. Tools like GoSecure Titan IDR, which can be installed in desktop, mobile and web applications, allow users to send suspicious emails for expert analysis. This can help identify and remove potentially harmful threats from the environment before they spread—while also delivering samples to experts for documentation and reverse-engineering.
Malware Analyst: Sean Mahoney
Indicators of Compromise
GoSecure Titan Labs are providing the following signatures to help the community in detecting and identifying the threats discussed in this report.
This content was originally published here.