Guloader Malware Analysis
Overview
Malware downloaders are becoming extremely popular among malicious actors as it provides a way to gather information about the victims system. Guloader is popular downloader malware and famous for its anti-debugging and anti-vm capabilities. The evasion tactics make it hard to analyse the malware.
Contents
- Sandbox analysis
- Runtime API address resolution
- Anti-Analysis Techniques
- Shellcode injection
- Indicators of compromise
- MITRE ATTACK TTPs
Sandbox Analysis
44 vendors on Virus Total are able to recognize the file as malware, more precisely as Trojan Downloader. Some vendors detect it as PonyStealer because of the similarity between the code. Joe Sandbox is able to detect is correctly as Guloader malware.
Runtime API Address Resolution
The malware is packed and decrypts the required code in memory and directly jumps to it as shown below.
The malware at various points uses hashes of API names to retrieve the desired API address. Some of the APIs required for important functionality for the are given below. The stack address are also given below which will be useful to understand the disassembly later.
60AF076D | kernel32!TerminateProcess | |
B76339E | kernel32.ExitProcess | |
82962C8 | NtProtectVirtualMemory | |
321C9581 | ntdll.DbgBreakpoint | |
6F0BDB18 | ntdll.DbgUiRemoteBreakpoint | |
EB96C5FA | kernel32.CreateFileA | |
54212E31 | NtSetInformationThread | |
6793C34C | ntdll.ZwAllocateVirtualMemory | |
9E0E1A44 | ntdll.NtGetContextThread | [ebp+28] |
308BE0D0 | NtSetContextThread | [ebp+2C] |
95F3A792 | ntdll.ZwWriteVirtualMemory | [ebp+30] |
D02E20D0 | ntdll.NtCreateSection | [ebp+38] |
231F196A | ntdll.NtMapViewOfSection | [ebp+3C] |
C29C5019 | NtOpenFile | [ebp+FC] |
8B8E133D | ntdll.ZwClose | [ebp+40] |
2C7B3D30 | NtResumeThread | [ebp+118] |
4DA0ACCC | kernel32.CreateProcessInternalW | [ebp+50] |
E19E5FE | kernel32.Sleep | [ebp+BC] |
7F08F451 | kernel32.CreateThread | [ebp+C0] |
ECCDA1BA | kernel32.WaitForSingleObject | [ebp+34] |
87AE6A46 | kernel32.TerminateThread | [ebp+C4] |
EB96C610 | kernel32.CreaterFileW | [ebp+78] |
663CEC80 | kernel32.WriteFile | [ebp+B0] |
3870CA07 | kernel32.CloseHandle | [ebp+54] |
7891C520 | kernel32.GetFileSize | [ebp+120] |
71019921 | kernel32.ReadFile | [ebp+124] |
Anti-Analysis Techniques
The malware uses ZwProtectVirtualMemory() to change the rights of ntdll in memory to write and executable.
The malware then patches the APIs DbgBreakPoint() with NOP and DbgUiRemoteBreakin() with a call to ExitProcess() API.
The malware uses rdtsc and cpuid for anti-debugging and anti-vm. The rdtsc instruction is called twice and the difference between the two timings obtained is ued to judge if the malware is running inside a debugger.
As shown in the above image, cpuid is used with a value of 1 being passed to eax. This returns CPU feature information in ecx register. The 31st bit of the 32 bit value returned determines if the environment is a hypervisor or not. If inside a hypervisor, the malware process ends.
The malware uses the EnumWindows() API. The EnumWindows() API emumerates all the process and executes a callback function for each process. In this case, it just increments a counter and later compares it with 0xc. Depending on the value, the malware proceeds or exits.
Guloader malware then uses an anti-vm technique. The malware check for the availability of C:\Program files\Qemu-ga\qemu-ga.exe and C:\Program Files\qga\qga.exe. These file are present when the system is running under Qemu virtualized environment.
The API NtSetInformationThread() is used to hide the tread as shown below.
The NtSetInformationThread() API here is called with the value of 0x11 for the second parameter ThreadInformationClass. This will cause the main thread to be hidden and no information will be passed to the debugger. If any breakpoint is placed in the code insde this thread then the debugger becomes unresponsive.
The function fcn.01f281cf retrieves the address of the API NtSetinformationthread using the hash value 0x54212e31. The function is repeatedly used to retrieve addresses of API’s. The method to retrieve the address of the API involves using the Export Address Table of the PE file by parsing the PE header in memory.
The malware before calling the actual Windows API first retrieves the address from the hash of the API using the function fcn.01f281cf. It then calls the function fcn.01f29eee which calls the required windows API. This pattern is repeated most of the time. The function fcn.01f29eee does anti-debug checks before calling the API.
Function fcn.1f29eee first uses the GetContextthread API to get the thread context which contains the values of the debug registers DR1, DR2 etc. The values of these registers are then compared to 0 to check if hardware breakpoints are setup.
After hardware breakpoints, the malware checks for software breakpoints by comparing the starting address of the API with bytes 0xCC, 0x3CD, 0xB0F as seen below.
After finishing the anti-vm and anti-debug phase and retrieving the addresses of the required API, the malware moves to the process injection phase. The process injection phase involves the following APIs.
kernel32.CreateProcessInternalW |
ntdll.NtCreateSection |
ntdll.NtMapViewOfSection |
ntdll.ZwAllocateVirtualMemory |
ntdll.ZwWriteVirtualMemory |
ntdll.NtGetContextThread |
ntdll.NtSetContextThread |
ntdll.NtResumeThread |
This version of Guloader malware uses the executable file namely C:\Windows\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe for process creation. The windir path is derived using the PEB, the address of PEB is derived using Thread Environment Block located at fs:[18]. The instruction mov eax, dword [eax+48] moves the pointer to the environment variables to register eax. This pointer is then used to retrieve the address of windir which is C:\Windows. The rest of the string is retrieved from the malware binary itself.
The malware first create a process using CreateProcessInternalW API setting the file parameter as C:\Windows\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe. It then obtains the handle to the file C:\Windows.syswow64\msvbvm60.dll using the Kernel32.CreateFileA API and passes the handle to the ntdll.NtCreateSection. The ntdll.NtMapViewOfSection API is used to map this section to the RegAsm.exe process created previously.
In the images above the pattern is visible where the malware pushes the address of the API on to the stack and the function fcn.01f29eee is called. This function does anti debugging as previously discussed and calls the required API. The malware then uses the ZwAllocateVirtualMemory and ZwWriteVirtualMemory to allocate memory inside the process and write shellcode to that memory.
NtGetContextThread and NtSetContextThread APIs are used to change the entry point of the process to that of the start of the shellcode in the process. Finally, NtResumeThread API is used to resume the suspended process.
Indicators of Compromise
sha256 | 759c87f02d5850ee317454dc8242067d042a320f653946c9162b645c0ae68ba6 | .exe file |
MITRE ATTACK TTP
T1106 | Execution | Native API | malware uses native APIs like ZwAllocateVirtualMemory |
T1027.002 | Defense Evasion | Obfuscated Files or Information -> Software Packing | Initial payload is decrypted in memory and executed |
T1027.002 | Defense Evasion | Obfuscated Files or Information -> Dynamic API Resolution | API address are retrieved at runtime |
T1622 | Defense Evasion | Debugger Evasion | Malware uses rdtsc and cpuid etc mechanisms |
T1497.001 | Defense Evasion | Virtualization/Sandbox Evasion -> System Checks | Malware looks for file artifacts like qemu-ga.exe |
T1055.003 | Defense Evasion | Process Injection -> Thread Execution Hijacking | malware uses NtSetContextThread API to change process context |