{
	"id": "9a060860-8a17-477b-8d97-afe1c10926ff",
	"created_at": "2026-04-06T00:15:15.943192Z",
	"updated_at": "2026-04-10T03:19:56.88544Z",
	"deleted_at": null,
	"sha1_hash": "7d3e92ec36036ce214bed30d4753cfa0a426bad7",
	"title": "GuLoader Snowballs via MalSpam Campaigns",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 439821,
	"plain_text": "GuLoader Snowballs via MalSpam Campaigns\r\nPublished: 2021-02-17 · Archived: 2026-04-02 12:45:48 UTC\r\nGuLoader is one of the well-known downloader malware of 2020, as its prevalence was very high during the\r\nfirst half of the year. Its common payloads were FormBook, Agent Tesla, LokiBot, Remcos RAT, just to name a\r\nfew, which were delivered by abusing storage services like OneDrive, Google Drive etc. Our 1st encounter with\r\nthe GuLoader binary was in March 2020 when it was delivering FormBook in a spam campaign. Later, Check\r\nPoint revealed their findings about the similarities between GuLoader and CloudEye, a protector for binaries. \r\nRecently, we got our hands on the latest GuLoader binary which was submitted to bazzar[.]abuse[.]ch by\r\nJAMESWT (@JAMESWT_MHT). It came as an email attachment as depicted in Figure 1. The email seemed\r\ninteresting because the sender’s name was Amit Saini claiming to be from Coca-Cola, Bangalore, India.\r\nhttps://labs.k7computing.com/?p=21725Lokesh\r\nPage 1 of 7\n\nFigure 1: Email with Attachment (courtesy of @JAMESWT_MHT) \r\nThe infection vector hasn’t changed yet but we at K7 Labs still keep track of GuLoader because of the efforts\r\ntaken by them to keep improving their code for detecting the Virtual/Debug environment. Although some of the\r\ntricks are old, they still get the job done.  In this blog, we’ll see the improvements that have been made to the code\r\nover time.\r\nAnti-Analysis \u0026 Anti-VM/Debug Techniques \r\nGuLoader in March 2020\r\n1. Debugger Anti-Attach technique – using ntdll.ZwSetInformationThread() with parameter 0x11\r\n2. Patching ntdll.DbgBreakPoint() and ntdll.DbgUiRemoteBreakin()\r\nhttps://labs.k7computing.com/?p=21725Lokesh\r\nPage 2 of 7\n\n3. Patching User mode hooks – patching the 1st\r\n 5 bytes of unconditional jump (0xe9 ????????) set by some\r\nAV \u0026 sandboxes\r\nGuLoader after July 2020\r\nIn addition to previous techniques mentioned above, there were some more tricks found in the binary which was\r\nreceived after the end of June and they are\r\n1. ZwQueryVirtualMemory() – to detect execution with in virtual machine\r\n2. Check breakpoints\r\n3. Enumerating the active windows using EnumWindows() API\r\n4. Checking for qemu-ga.exe and qga.exe under Program Files.\r\nWhile all these were documented tricks there are 2 tricks in particular which were quite interesting to us.\r\nRDTSC and CPUID instruction combination as depicted in Figure 2.\r\nIt uses RDTSC instruction to get the elapsed time in EAX:EDX and performs OR operation between EAX \u0026\r\nEDX and saves it in ESI. Then it calls CPUID instruction with EAX=1 and checks if the 31st bit (0x1f) is set (by\r\ndefault it is 0 \u0026 if run under virtual machine it will be set) and then exits execution by displaying a popup\r\nmessage stating “The program cannot be run under virtual Environment or debugging software!”.\r\nAgain it calls RDTSC instruction and performs the OR operation between EDX and EAX and subtract the new\r\nresult with the previous result stored in ESI. In normal execution, the difference between 2 RDTSC instructions\r\nwill never be 0, but the code checks if the difference is less than or equal to 0 which results in an endless loop.\r\nFigure 2: RDTSC and CPUID Instructions\r\nApart from the infinite loop mentioned above, it also uses one more loop which executes for 0x186a0\r\ntimes (that is 100000 times). The value 0x186a0 is stored in ECX and performs addition between EDI\r\n(EDI=0 initially) and the result received after the difference between two RTDSC instructions (mentioned\r\nabove). This loop is executed till ECX becomes 0 and if the value in EDI after the loop ends is greater than\r\n0x68e7780 it again returns to the start of the check where it again sets ECX to 0x186a0.\r\nhttps://labs.k7computing.com/?p=21725Lokesh\r\nPage 3 of 7\n\nFigure 3: RDTSC loop\r\nRetrieves the name of the active window and creates a hash with it and matches it with the predefined hash\r\nstored in the code as depicted in Figure 4.\r\nFigure 4: Hash Comparison of the  Active Window\r\nGuLoader 2021\r\nThe GuLoader sample which was analyzed recently had almost every check mentioned above except for the active\r\nwindow hash comparison. Instead they have a different hash comparison technique.\r\nUsing MsiEnumProductsA() and MsiGetProductInfo() function\r\nFirst it calls MsiEnumProductsA() function with iPoductIndex as 0 and increments it by 1 for subsequent calls. It\r\nreturns a product code which is a 38 character GUID with a null terminating character making it 39 character long.\r\nhttps://labs.k7computing.com/?p=21725Lokesh\r\nPage 4 of 7\n\nThis GUID is given as input to MsiGetProductInfo() function to retrieve the product name installed and this loop\r\nis executed for 0xff times as depicted in Figure 5.\r\nFigure 5: MsiEnumProductsA() and MsiGetProductInfo() loop\r\nThe result received after a call to MsiGetProductInfo() is the name of the product in strings which needs to be\r\nconverted to a hash for comparison. This eliminates performance overhead since comparing each character\r\nsequentially takes time. The hashing function used here is djb2 as depicted in Figure 6 which is quite simple and\r\nlightweight.\r\nFigure 6: Hashing Logic\r\nThe hashes used in the code (like 0x7c8aa9fd, 0x9b8ffb51) are unknown to us at this point in time but anyone can\r\nguess that it must be mostly related to check if AV, sandboxes or debuggers are installed.\r\nhttps://labs.k7computing.com/?p=21725Lokesh\r\nPage 5 of 7\n\nUse of NtQueryInformationProcess() with processInformationClass parameter as 0x07 (process debug\r\nport) as depicted in Figure 7. This API usage is well documented and is an old trick to detect if the process\r\nis being debugged.\r\nFigure 7: NtQueryInformationProcess() function\r\nCode implementation changes – to make the process of reversing/debugging a little harder they have\r\nimplemented spaghetti code which is a code having a lot of jumps and calls.\r\nOnce all these Anti-VM and Anti-Debugging checks are over it proceeds to download the encrypted binary from\r\nthe domain stated and copies it to a buffer space and decrypts it as depicted in Figure 8.\r\nFigure 8: Downloading after Decrypting the Binary\r\nThe domain is still live and seems to be bogus because the domain name mentioned in the contact section of the\r\npage is repair-electronics[.]com whereas the domain name active is repair-electrons[.]com and the “created by\r\nMohamad Chedid” line under copyright symbol has a HTML  href tag, which is blank and doesn’t redirect\r\nanywhere. When viewing the source of the page there is a commented line saying “Free HTML5 template\r\ndeveloped by FREEHTML5.CO” as depicted in Figure 9.\r\nhttps://labs.k7computing.com/?p=21725Lokesh\r\nPage 6 of 7\n\nFigure 9: Bogus Domain Name\r\nThreat actors are always evolving by modifying their tools with improved techniques and tricks to evade detection\r\nand make the analysis harder. Here at K7 Labs we actively monitor such malware and have proactive detection for\r\nall the files. So stay safe from these kinds of attacks in this pandemic situation by using a reputed AV product such\r\nas K7 products.\r\nIndicators Of Compromise (IOCs)\r\nMD5: 1C8B24FCF8143C9035EE722EC8714EB0\r\nFile Name: EXTERNAL RFP – PAN India Epoxy PU – 2021.exe\r\nK7 Detection Name: Trojan ( 005774081 )\r\nURL\r\nhxxps[:]//www[.]repair-electrons[.]com\r\nSource: https://labs.k7computing.com/?p=21725Lokesh\r\nhttps://labs.k7computing.com/?p=21725Lokesh\r\nPage 7 of 7",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://labs.k7computing.com/?p=21725Lokesh"
	],
	"report_names": [
		"?p=21725Lokesh"
	],
	"threat_actors": [],
	"ts_created_at": 1775434515,
	"ts_updated_at": 1775791196,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/7d3e92ec36036ce214bed30d4753cfa0a426bad7.pdf",
		"text": "https://archive.orkl.eu/7d3e92ec36036ce214bed30d4753cfa0a426bad7.txt",
		"img": "https://archive.orkl.eu/7d3e92ec36036ce214bed30d4753cfa0a426bad7.jpg"
	}
}