GuLoader: A fileless shellcode based malware in action

By

A good thief steals without leaving any footprint behind, the similar job is done by file less malware in the threat world.  Additionally if a file less malware getting the work done without involving Potable Executable (PE) file, not even in the memory is like ‘icing on the cake’. GuLoader is a file less shellcode based malware, recently observed by SonicWall threat research team.  A VBS script inside an archive file is delivered to the victim’s machine as an email attachment which loads GuLoader shellcode into PowerShell executable. GuLoader further downloads and executes other malware in the  memory of a legitimate process:

Infection Cycle:

VBSCRIPT

The obfuscated VBScript contains code broken into variables which is concatenated on execution. The VBScript stores the shellcode into registry entry HKEY_CURRENT_USER\Software\Fordyred6 which varies across the variants. A PowerShell script is then executed to read the registry value and continue the infection process:

PowerShell Script

The PowerShell script allocates memory into powershell.exe using API ZwAllocateVirtualMemory and reads the shellcode data from the registry entry. The shellcode is copied into allocated memory using RtlMoveMemory and executed inside powershell.exe:

Shellcode

An error window saying “This program cannot be run under virtual environment or debugging software!” can be seen on execution of the shellcode in a controlled environment. While analyzing the shellcode, a malware researcher should be habitual of seeing this window again and again, because the shellcode is full of anti debug and anti VM techniques:

 

Initial 0x41 bytes of the shellcode works as decryptor bytes for the remaining shellcode. The decryption is done using a XOR operation with a constant value:

 

After decrypting the remaining shellcode, the decryptor code ( initial 0x41 bytes) are replaced with 0x90 (NOP instruction) and control is transferred to the decrypted shellcode:

 

The shellcode uses PEB traversal method to get the API addresses by comparing API names with its own list of hashes. The malware uses custom DJB2 hashing algorithm to avoid detection from various security software. If custom DJB2 algorithm is not used, DJB2 hashes of the various APIs would be same across the malware variants which makes the detection pretty easy for the security software:

 

 

The malware involves various anti debug and anti VM techniques. It keeps all the strings encrypted which are decrypted and used on demand basis. It encrypts the code before calling the API and decrypts it back after calling the API.

Strings Decryption

The malware keeps the string encrypted which are being decrypted just before using them. The malware keeps a DWORD value before encrypted string, which is XOR with a constant value to get the string size. The malware contains a decryption key of size 0x2B bytes which is used to decrypt the encrypted strings using XOR operation:

Anti API Hook

The malware traverses the ntdll.dll memory starting from the code section and looks for bytes [0xb8, 0x00, ??, ??, 0xBA] to get the code responsible for making the system calls. These system calls are hooked by many security software to change the control flow to the their code for investigating the API calls. If the system calls code is patched, the malware restores them back to the original bytes:

Anti Dump

The malware encrypts the shellcode just before calling any API, to prevent event based memory dumps or analysis. After the API is called shellcode is decrypted back:

 

Anti Debug

 

Software Breakpoints

The malware checks for software breakpoints before calling the API by comparing initial bytes of the API with 0xCC (INT3) and initial word with 0x03CD (INT 3) and 0x0B0F (UD2). If any of these breakpoint instructions is found, the malware shows the error window message mentioned in the beginning and terminates the execution:

 

Vectored Exception Handler

The malware registers vectored exception handler with malware defined callback module which checks for INT3 (0xCC) exception and computes the next Extended Instruction Pointer (EIP) address by XOR the next byte of current EIP, to continue after the exception. The INT3 instruction is handled by the debugger which misleads the control flow to incorrect execution path:

 

However adding this vectored exception handler is an anti debugging technique, moreover in this malware this can be named as irritating technique for a researchers, because the code is full of INT3 instructions along with opaque predicate and arithmetic calculations. The researcher needs to either bypass the instruction by calculating the next EIP which will make him tired, or he needs to write a plugin code to bypass the instruction, which is again time consuming:

 

KUSER_SHARED_DATA

Similar to user mode GetTickCount API, kernel mode ZwGetTickCount reads values from the KUSER_SHARED_DATA page. This page is mapped read-only into the user mode at address 0x7FFE0000. The malware reads the values directly from KUSER_SHARED_DATA before and after executing some instructions and calculates the difference. The difference is calculated multiple times and added to a variable which is compared to the threshold value to check for debugging environment. If the computed value does not meet the threshold condition it will continue the execution in a infinite loop:

 

DbgBreakPoint

The malware modified the memory protection to ntdll.dll to  PAGE_EXECUTE_READWRITE  using ZwProtectVirtualMemory API and replaces INT3 instruction with NOP instruction inside DbgBreakPoint API to disallow attaching debugger:

 

DbgUiRemoteBreakin

The malware replaces code inside DbgUiRemoteBreakin to invoke ExitProcess API with exit code 0:

 

ThreadHideFromDebugger

The malware invokes ZwSetInformationThread API by setting ThreadInformationClass argument as ThreadHideFromDebugger which detaches the debugger and terminates the process immediately, if running under a debugger:

 

Anti VM

The malware gets the virtual memory using API ZwQueryVirtualMemory and searches for string “vmtoolsdControlWndClass” and if finds the string, the malware considers the execution in controlled environment. If malware finds any evidence of running under virtual environment, it shows the error message window and terminates the execution:

 

CPUID

The malware executes the CPUID instruction with EAX = 1 (to get processor features) as input and examines result value in ECX register. If the 31st bit is of the ECX register is set, the malware considers the execution inside the Virtual Machine (VM):

QEMU Emulator

The malware checks for the presence of files related to QEMU emulator:

  • C:\Program Files\Qemu-ga\qemu-ga.exe
  • C:\Program Files\qga\qga.exe

Enumerate Windows

The malware enumerates windows using EnumWindows API and checks the windows count, if count is less then 0xC then the malware considers the execution in controlled environment:

 

Enumerate Device Drivers

The malware retrieves load addresses of the device drivers using API EnumDeviceDrivers and gets the name associates with each load address using API  GetDeviceDriverBaseNameA . The malware computes custom DJB2 hash value of device driver names and compares them with its list of hashes:

  • D82B79F9
  • 72FCC347
  • 55C69E11 (vmmouse.sys)
  • 6538B8EE (vmusbmouse.sys)
  • 907D9998
  • 83277DEB (vm3dmp.sys)

 

Enumerate Installed Software

The malware enumerates installed products using MsiEnumProductsA API and retrieves the product name using API MsiGetProductInfoA. The malware computes custom DJB2 hash value of product names and compares them with its list of hashes:

  • 30565F59
  • E5AB7D36
  • 4F3EA1F6
  • 27D195CB

 

Enumerate Services

The malware opens specified service control manager database using API OpenSCManagerA and retrieves the service names using API EnumServicesStatusA. The malware computes custom DJB2 hash value of service names and compares them with its list of hashes:

  • C99647C9
  • ACBC4B26 (VMware Tools)
  • F1D665FC (VMware Snapshot Provider)
  • 82D0D13B
  • 1605A96C
  • CE8609AB
  • 9D86D771

 

Debug Port

The malware invokes API ZwQueryInformationProcess with parameters ProcessInformationClass as ProcessDebugPort. If the API call succeeded, the malware considers the execution under the debugger:

 

Code Injection

The malware creates process “C:\Windows\Microsoft.NET\Framework\v2.0.50727\caspol.exe” in CREATE_SUSPENDED mode. The malware creates a section and tries to map the section into the suspended process at 0x400000 but it failed with 0x40000003 (STATUS_IMAGE_NOT_AT_BASE). The malware allocates virtual memory into the suspended process using API ZwAllocateVirtualMemory.

 

The malware writes the shellcode bytes (0x8D000) into the suspended process using API ZwWriteVirtualMemory:

 

The malware modifies the EIP of the suspended process from its entrypoint to the injected shellcode using API ZwSetContextThread:

 

The malware resumes the suspended process using API ZwResumeThread. The shellcode again starts from the beginning but in the context of a new process. The shellcode again executes all the anti debug and anti VM techniques but this time additionally it also downloads the payload data:

 

The malware downloads encrypted payload from URL h[t][t]ps://onedrive.live.com/download?cid=5E3278A18A104B1A&resid=5E3278A18A104B1A%21117&authkey=ABLIkl0zjTxzpTk by setting user agent as “Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko”. The malware downloads in a loop, 0x10000 bytes each time using InternetReadFile until the complete payload data is downloaded:

Downloaded data contains 0x40 garbage bytes in the beginning. Instead of keeping hardcoded decryption key, malware computes the key after downloading the encrypted data. The malware contains a constant byte array of 0x30b size. The malware executes in a loop, picks the first word from the constant byte array XOR it with loop index and again XOR it with the word after 0x40 garbage bytes in the downloaded data and if the value comes to “4D5A”, the malware breaks the loop. Now the loop index is XOR with the constant byte array to get 0x30B bytes decryption key:

 

The malware decrypts the payload data using the decryption key, which is the NanoCore RAT for this variant. However the other variants also downloads AgentTesla, NetWire RAT and Ramcos RAT etc.:

 

The file is detected by only a few security vendors on popular threat intelligence sharing portal VirusTotal at the time of writing this blog, this indicates its spreading potential:

 

Evidence of the detection by RTDMI(tm) engine can be seen below in the Capture ATP report for this file:

Security News
The SonicWall Capture Labs Threat Research Team gathers, analyzes and vets cross-vector threat information from the SonicWall Capture Threat network, consisting of global devices and resources, including more than 1 million security sensors in nearly 200 countries and territories. The research team identifies, analyzes, and mitigates critical vulnerabilities and malware daily through in-depth research, which drives protection for all SonicWall customers. In addition to safeguarding networks globally, the research team supports the larger threat intelligence community by releasing weekly deep technical analyses of the most critical threats to small businesses, providing critical knowledge that defenders need to protect their networks.