GuLoader is one of the well-known downloader malware of 2020, as its prevalence was very high during the first half of the year. Its common payloads were FormBook, Agent Tesla, LokiBot, Remcos RAT, just to name a few, which were delivered by abusing storage services like OneDrive, Google Drive etc. Our 1st encounter with the GuLoader binary was in March 2020 when it was delivering FormBook in a spam campaign. Later, Check Point revealed their findings about the similarities between GuLoader and CloudEye, a protector for binaries.
Recently, we got our hands on the latest GuLoader binary which was submitted to bazzar[.]abuse[.]ch by JAMESWT (@JAMESWT_MHT). It came as an email attachment as depicted in Figure 1. The email seemed interesting because the sender’s name was Amit Saini claiming to be from Coca-Cola, Bangalore, India.
The infection vector hasn’t changed yet but we at K7 Labs still keep track of GuLoader because of the efforts taken by them to keep improving their code for detecting the Virtual/Debug environment. Although some of the tricks are old, they still get the job done. In this blog, we’ll see the improvements that have been made to the code over time.
Anti-Analysis & Anti-VM/Debug Techniques
GuLoader in March 2020
- Debugger Anti-Attach technique – using ntdll.ZwSetInformationThread() with parameter 0x11
- Patching ntdll.DbgBreakPoint() and ntdll.DbgUiRemoteBreakin()
- Patching User mode hooks – patching the 1st 5 bytes of unconditional jump (0xe9 ????????) set by some AV & sandboxes
GuLoader after July 2020
In addition to previous techniques mentioned above, there were some more tricks found in the binary which was received after the end of June and they are
- ZwQueryVirtualMemory() – to detect execution with in virtual machine
- Check breakpoints
- Enumerating the active windows using EnumWindows() API
- Checking for qemu-ga.exe and qga.exe under Program Files.
While all these were documented tricks there are 2 tricks in particular which were quite interesting to us.
- RDTSC and CPUID instruction combination as depicted in Figure 2.
It uses RDTSC instruction to get the elapsed time in EAX:EDX and performs OR operation between EAX & EDX and saves it in ESI. Then it calls CPUID instruction with EAX=1 and checks if the 31st bit (0x1f) is set (by default it is 0 & if run under virtual machine it will be set) and then exits execution by displaying a popup message stating “The program cannot be run under virtual Environment or debugging software!”.
Again it calls RDTSC instruction and performs the OR operation between EDX and EAX and subtract the new result with the previous result stored in ESI. In normal execution, the difference between 2 RDTSC instructions will never be 0, but the code checks if the difference is less than or equal to 0 which results in an endless loop.
- Apart from the infinite loop mentioned above, it also uses one more loop which executes for 0x186a0 times (that is 100000 times). The value 0x186a0 is stored in ECX and performs addition between EDI (EDI=0 initially) and the result received after the difference between two RTDSC instructions (mentioned above). This loop is executed till ECX becomes 0 and if the value in EDI after the loop ends is greater than 0x68e7780 it again returns to the start of the check where it again sets ECX to 0x186a0.
- Retrieves the name of the active window and creates a hash with it and matches it with the predefined hash stored in the code as depicted in Figure 4.
The GuLoader sample which was analyzed recently had almost every check mentioned above except for the active window hash comparison. Instead they have a different hash comparison technique.
- Using MsiEnumProductsA() and MsiGetProductInfo() function
First it calls MsiEnumProductsA() function with iPoductIndex as 0 and increments it by 1 for subsequent calls. It returns a product code which is a 38 character GUID with a null terminating character making it 39 character long. This GUID is given as input to MsiGetProductInfo() function to retrieve the product name installed and this loop is executed for 0xff times as depicted in Figure 5.
The result received after a call to MsiGetProductInfo() is the name of the product in strings which needs to be converted to a hash for comparison. This eliminates performance overhead since comparing each character sequentially takes time. The hashing function used here is djb2 as depicted in Figure 6 which is quite simple and lightweight.
The hashes used in the code (like 0x7c8aa9fd, 0x9b8ffb51) are unknown to us at this point in time but anyone can guess that it must be mostly related to check if AV, sandboxes or debuggers are installed.
- Use of NtQueryInformationProcess() with processInformationClass parameter as 0x07 (process debug port) as depicted in Figure 7. This API usage is well documented and is an old trick to detect if the process is being debugged.
- Code implementation changes – to make the process of reversing/debugging a little harder they have implemented spaghetti code which is a code having a lot of jumps and calls.
Once all these Anti-VM and Anti-Debugging checks are over it proceeds to download the encrypted binary from the domain stated and copies it to a buffer space and decrypts it as depicted in Figure 8.
The domain is still live and seems to be bogus because the domain name mentioned in the contact section of the page is repair-electronics[.]com whereas the domain name active is repair-electrons[.]com and the “created by Mohamad Chedid” line under copyright symbol has a HTML href tag, which is blank and doesn’t redirect anywhere. When viewing the source of the page there is a commented line saying “Free HTML5 template developed by FREEHTML5.CO” as depicted in Figure 9.
Threat actors are always evolving by modifying their tools with improved techniques and tricks to evade detection and make the analysis harder. Here at K7 Labs we actively monitor such malware and have proactive detection for all the files. So stay safe from these kinds of attacks in this pandemic situation by using a reputed AV product such as K7 products.
Indicators Of Compromise (IOCs)
File Name: EXTERNAL RFP – PAN India Epoxy PU – 2021.exe
K7 Detection Name: Trojan ( 005774081 )