{
	"id": "98c8fc18-ec90-4da5-97ee-790e550b4758",
	"created_at": "2026-04-06T00:16:36.807601Z",
	"updated_at": "2026-04-10T03:20:46.071429Z",
	"deleted_at": null,
	"sha1_hash": "b1b7adc3f79ba034e12591aa1b15a424777f9a59",
	"title": "HijackLoader Updates | ThreatLabz",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 475451,
	"plain_text": "HijackLoader Updates | ThreatLabz\r\nBy Muhammed Irfan V A\r\nPublished: 2024-05-06 · Archived: 2026-04-05 15:26:38 UTC\r\nTechnical Analysis\r\nThe following sections focus on the new changes to HijackLoader.\r\nFirst stage\r\nThe purpose of the loader’s first stage is to decrypt and decompress the HijackLoader modules, including the\r\nsecond stage ( ti64 module for 64-bit processes and ti module for 32-bit processes), and execute the second\r\nstage.\r\nThe first stage resolves the APIs dynamically by walking the process environment block (PEB) and parsing the\r\nPortable Executable (PE) header. The loader uses the SDBM hashing algorithm below to resolve APIs.\r\n def SDBMHash(apiName):\r\n finalHash = 0\r\n for i in apiName:\r\n finalHash = (finalHash*0x1003F) \u0026 0xFFFFFFFF\r\n finalHash = (finalHash + ord(i)) \u0026 0xFFFFFFFF\r\n return finalHash\r\nUsing the SDBM hash algorithm above, the loader resolves the WinHTTP APIs to check for an internet\r\nconnection. This is achieved with the following URL:\r\nhttps://apache.org/logos/res/incubator/default.png\r\nThe loader repeats this process until there is an internet connection. After that, HijackLoader decrypts embedded\r\nshellcode by performing a simple addition operation with a key. It then sets the execute permission using\r\nVirtualProtect for the decrypted shellcode and calls the start address of the shellcode.\r\nBlocklist processes\r\nThe shellcode uses the SDBM hash algorithm again to resolve additional APIs. After that, the shellcode uses the\r\nRtlGetNativeSystemInfo API to check for blocklisted processes running on the system. In previous versions of\r\nHijackLoader, the loader checked for five processes related to antivirus applications. Now, the code only checks\r\nfor two processes.\r\nhttps://www.zscaler.com/blogs/security-research/hijackloader-updates\r\nPage 1 of 9\n\nThe names of current running processes are converted to lowercase letters and the SDBM hashing algorithm is\r\ncompared with the hashes of the two processes. If these values match, execution is delayed using the\r\nNtDelayExecution API. Information for the two blocklisted processes can be found in the table below.\r\nHash Value Process Name Description\r\n5C7024B2 avgsvc.exe The avgsvc.exe file is a software component of AVG Internet Security.\r\nB03D4537 Unknown N/A\r\nTable 1: Processes blocklisted by HijackLoader.\r\nNote that the AVG process was also previously blocklisted by earlier versions of HijackLoader.\r\nSecond stage loading process\r\nThere are two methods that HijackLoader uses to load the second stage, both of which are embedded in the\r\nmalware’s configuration. HijackLoader retrieves a DWORD from the configuration at offset 0x110 and XOR’s the\r\nvalue with a DWORD from the configuration at offset 0x28. Let's refer to the result of this XOR as the value “a”.\r\nThe malware loads a copy of itself into memory using GlobalAlloc and ReadFile . Then it reads a DWORD\r\nfrom the configuration at offset 0xC and adds this value to the address where the malware file was loaded into\r\nmemory, and then reads a DWORD from this address. Let's call this value “b”. \r\nIf “a” and “b” do not match, a PNG file is downloaded and used to load the second stage. \r\nIf “a” and “b” match, an embedded PNG is used to load the second stage.\r\nThe image below shows an example of an embedded PNG when rendered using an image viewer.\r\nhttps://www.zscaler.com/blogs/security-research/hijackloader-updates\r\nPage 2 of 9\n\nFigure 1: An embedded PNG image containing the encrypted modules used by HijackLoader in a PNG viewer.\r\nPNG payload\r\nThe screenshot below displays the decompiled HijackLoader code that checks whether the PNG is embedded\r\nwithin the file or if it needs to be downloaded separately.\r\nhttps://www.zscaler.com/blogs/security-research/hijackloader-updates\r\nPage 3 of 9\n\nFigure 2: The decompiled output of HijackLoader to find if the PNG is embedded or if it should be downloaded.\r\nIf the PNG is embedded, the malware starts searching for the PNG image with the following bytes: 49 44 41 54\r\nC6 A5 79 EA . This contains the IDAT header 49 44 41 54 and magic header C6 A5 79 EA .  \r\nThe logic replicated below in Python shows how the malware finds the IDAT header followed by the magic\r\nheader.\r\ncheckFlag = 0\r\nwith open(malware_file, \"rb\") as input_file:\r\n input_file.seek(0)\r\n file = input_file.read()\r\n offset = 0\r\n \r\nhttps://www.zscaler.com/blogs/security-research/hijackloader-updates\r\nPage 4 of 9\n\ntry:\r\n resultOffsetNextByte = file.index(b'\\x49\\x44\\x41\\x54\\xC6\\xA5\\x79\\xEA', offset + 1)\r\n print(\"Found Corect PNG Image\")\r\n checkFlag = 1\r\n except ValueError:\r\n print('Could not Find PNG with Correct Header')\r\nThe screenshot below shows the IDAT header followed by the magic header C6 A5 79 EA .\r\nFigure 3: The format of the IDAT header.\r\nIf the PNG needs to be downloaded, the URL is decrypted from the configuration using a simple XOR cipher.\r\nFollowing that, the WinHTTP library is utilized to download the PNG from the decrypted URL.\r\nThere are multiple encrypted blobs in the PNG file. Each encrypted blob is stored in the format Blob size:IDAT\r\nheader . Each of the encrypted blobs can be found by searching for the IDAT header. The size of each encrypted\r\nblob is parsed and data of this size following the header is appended to a new memory address. When the total size\r\nis reached, the encrypted data is decrypted using a simple XOR cipher with the key: 32 A3 49 B3 (which is a\r\nDWORD that follows the MAGIC Header ). Then, the decrypted blob is decompressed using the LZNT1 algorithm.\r\nThis decompressed data contains the modules and configurations used to load the second stage. The offset at 0xF4\r\nof the decompressed data contains a DLL name (in this specific case pla.dll ) that is loaded into memory. The\r\nmodules are then parsed to locate the ti module (by name) using the SDBM hashing algorithm. Then, the ti\r\nmodule is copied to the DLL’s BaseOfCode field and is executed.\r\nThe screenshot below shows the decompiled output for the injection of the second stage.\r\nhttps://www.zscaler.com/blogs/security-research/hijackloader-updates\r\nPage 5 of 9\n\nFigure 4: The decompiled output for the injection of the second stage.\r\nSecond stage\r\nThe main purpose of the second stage is to inject the main instrumentation module. To increase stealthiness, the\r\nsecond stage of the loader employs more anti-analysis techniques using multiple modules. The modules have\r\nfeatures that include a UAC bypass, Windows Defender Antivirus exclusion, using Heaven's Gate to execute x64\r\ndirect syscalls, and process hollowing.\r\nModules\r\nThe malware developers have continued to create new modules. The table below shows the HijackLoader modules\r\nadded since our last blog.\r\nHash\r\nValue\r\nModule Name Description\r\n8858AC11 modCreateProcess\r\nBefore transferring control to the  modCreateProcess module,\r\nthe  ti module is copied to a new address and XOR’ed with a\r\nhttps://www.zscaler.com/blogs/security-research/hijackloader-updates\r\nPage 6 of 9\n\nHash\r\nValue\r\nModule Name Description\r\nperformance counter value retrieved by calling the\r\nQueryPerformanceCounter API. The new address of the\r\nXOR’ed  ti module and the XOR key are stored for later use.\r\nWhen control is transferred to the  modCreateProcess module,\r\nHijackLoader begins by overwriting the entire  ti module with\r\nzeros. HijackLoader then performs x86 call stack spoofing. Next,\r\nthe  modCreateProcess module copies the  TinycallProxy module\r\ninto the text section of the system DLL specified by the  SM module\r\nand uses this copied  TinycallProxy module to\r\ncall  CreateProcess . The\r\nparameters  lpCommandLine ,  dwCreationFlags ,  lpStartupInfo ,\r\nand  lpProcessInformation are supplied by the  ti module based\r\non the requirements. After the API call, the return address pointers\r\nare patched with the actual return addresses, and the XOR’ed  ti\r\nmodule is decrypted and restored to its original address. This\r\ntechnique helps obfuscate the origin of the API call.\r\n9757C10F modCreateProcess64 This module is the 64-bit version of modCreateProcess .\r\n3B2859F5 modUAC\r\nHandles the encryption and decryption of the  ti module, performs\r\nx86 call stack spoofing, and utilizes the  TinycallProxy module to\r\ncall APIs, similar to the  modCreateProcess module. If the first\r\nDWORD of the  UACDATA module is two,  modUAC elevates its\r\nprivilege using the  runas operation. Otherwise,  modUAC bypasses\r\nUAC using the CMSTPLUA COM interface.\r\n7366BCF3 modUAC64 This module is the 64-bit version of modUAC .\r\n4F7A1A39 modWriteFile\r\nOnly handles the encryption and decryption of the  ti module,\r\nsimilar to the modCreateProcess module.  modWriteFile does not\r\nperform x86 call stack spoofing or use the  TinycallProxy module\r\nto call APIs.  modWriteFile uses  CreateFile to obtain the file\r\nhandle and  WriteFile to write the content. The\r\nparameters  lpFileName and  dwCreationDisposition\r\nfor  CreateFile , and  lpBuffer and  nNumberOfBytesToWrite\r\nfor  WriteFile , are provided by the  ti module based on the\r\nrequirements.\r\n1C549B37 modWriteFile64 This module is the 64-bit version of modWriteFile .\r\nhttps://www.zscaler.com/blogs/security-research/hijackloader-updates\r\nPage 7 of 9\n\nHash\r\nValue\r\nModule Name Description\r\n1003C017 WDDATA\r\nThis module contains a PowerShell command to add a Windows\r\nDefender Antivirus exclusion.\r\nTable 2: The new modules added to HijackLoader.\r\nti module\r\nThe ti module is the first module called by the first stage. It dynamically resolves APIs by walking the PEB and\r\nparsing PE headers using CRC-32 as a hashing algorithm. It then checks if a mutex, whose name is resolved using\r\nCRC-32 hashing, is present on the system. If the mutex is present, the process terminates; otherwise, it continues\r\nexecution.\r\nNext, the ti module retrieves the environment variable at offset 0x45 from the decompressed data ( %APPDATA% in\r\nour case), expands it, and checks if the current process is running under this directory. If not, it copies itself to this\r\nlocation, executes the copied file, and terminates itself.\r\nNext, the loader uses the Heaven's Gate technique to bypass user mode hooks – this is further explored in the next\r\nsection.\r\nBypass user mode hooks for injection\r\nTo bypass user mode hooks, the loader uses a combination of Heaven's Gate and a direct syscall technique. The\r\nscreenshot below shows HijackLoader employing the Heaven’s Gate technique to execute an x64 direct syscall.\r\nFigure 5: HijackLoader using Heaven’s Gate to execute a x64 direct syscall.\r\nSubsequently, the execution is returned to the 32-bit code. Following this, the next stage is injected. The process\r\ndesignated for injection is stored in the decompressed data at offset 0x90 ( %windir%\\SysWOW64\\cmd.exe in our\r\nspecific case). The cmd.exe is created as a child process, and the main instrumentation module is injected using\r\nhttps://www.zscaler.com/blogs/security-research/hijackloader-updates\r\nPage 8 of 9\n\nprocess hollowing. The main instrumentation module uses the same process mentioned in our previous blog to\r\ndecrypt the final payload and execute it.\r\nExplore more Zscaler blogs\r\nSource: https://www.zscaler.com/blogs/security-research/hijackloader-updates\r\nhttps://www.zscaler.com/blogs/security-research/hijackloader-updates\r\nPage 9 of 9",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://www.zscaler.com/blogs/security-research/hijackloader-updates"
	],
	"report_names": [
		"hijackloader-updates"
	],
	"threat_actors": [],
	"ts_created_at": 1775434596,
	"ts_updated_at": 1775791246,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/b1b7adc3f79ba034e12591aa1b15a424777f9a59.pdf",
		"text": "https://archive.orkl.eu/b1b7adc3f79ba034e12591aa1b15a424777f9a59.txt",
		"img": "https://archive.orkl.eu/b1b7adc3f79ba034e12591aa1b15a424777f9a59.jpg"
	}
}