New HijackLoader Evasion Tactics | ThreatLabz By Muhammed Irfan V A Published: 2025-03-31 · Archived: 2026-04-05 23:44:39 UTC Technical Analysis In the following sections, we examine HijackLoader’s new modules and changes in evasion tactics. The module names added since our last analysis are the following:  ANTIVM ,  MUTEX ,  CUSTOMINJECT ,  CUSTOMINJECTPATH ,  modTask ,  modTask64 ,  PERSDATA , and  SM . First stage HijackLoader’s first stage has undergone two changes. The first change involves the blocklist processes check, where a new process name,  avastsvc.exe , was added to the list. If any of the processes in the table below are running, HijackLoader delays execution by 5 seconds.  SDBM Hash Value Process Name Description 5C7024B2 avgsvc.exe The  avgsvc.exe process is a component of AVG Internet Security. 6CEA4537 avastsvc.exe The  avastsvc.exe process is a component of Avast Antivirus. Table 1: Processes blocklisted by HijackLoader. The second change pertains to the decryption of modules. While most HijackLoader samples still use IDAT headers in a PNG file to store encrypted modules, a few samples are embedding them in the PNG’s pixel structure. Second stage (ti module) As mentioned in our previous blog, HijackLoader uses the Heaven's Gate technique to execute x64 direct syscalls. We have now observed that call stack spoofing has been added to the list of evasion tactics used by HijackLoader. This technique uses a chain of EBP pointers to traverse the stack and conceal the presence of a malicious call in the stack by replacing actual stack frames with fabricated ones. The  ti module only uses call stack spoofing for the following native system APIs: https://www.zscaler.com/blogs/security-research/analyzing-new-hijackloader-evasion-tactics Page 1 of 10 ZwCreateSection ZwMapViewOfSection ZwUnmapViewOfSection ZwProtectVirtualMemory ZwReadVirtualMemoy ZwWriteVirtualMemory ZwWriteFile ZwResumeThread ZwGetContextThread ZwSetContextThread ZwRollbackTransaction   ZwClose   ZwTerminateProcess   HijackLoader API calls HijackLoader collects the API hash, system call number, function name, and function address of all API names that start with Zw in  ntdll.dll . This information is stored as an array of elements, with each element being a structure of size 16, which we will refer to as a  DIRECTSYSCALL_STRUCT , as shown below. struct DIRECTSYSCALL_STRUCT { uint32_t APIHash; // CRC32 hash of the API function name uint32_t ssn; // System service number (SSN) char *APIName; // API function name void *APIFunctionAddress; // API function address }; When HijackLoader calls a Windows API function, the malware first locates the corresponding structure ( DIRECTSYSCALL_STRUCT ) for the specified API. HijackLoader then invokes the Windows API function either by directly calling its address (if not running under WOW64) or by utilizing a combination of call stack spoofing, Heaven's Gate, and direct syscalls (if running under WOW64). Call stack spoofing Call stack spoofing is used to mask the origin of function calls such as API and system calls. The figure below shows a high-level view of how HijackLoader leverages call stack spoofing: https://www.zscaler.com/blogs/security-research/analyzing-new-hijackloader-evasion-tactics Page 2 of 10 Figure 1: Diagram showing how HijackLoader uses call stack spoofing to mask the origin of function calls.  HijackLoader uses the base pointer register (EBP) to navigate the stack by following the chain of EBP pointers. The malware retrieves the return address pointer (EBP+4) from the stack frames. If the return address is not located in the text section of NTDLL or kernelbase, HijackLoader collects both the return address pointer and the return address of the stack frame. The return address pointer is then patched with a random address from the text section of a legitimate system DLL. This activity is repeated until the stack limit is reached or when three adjacent stack frames have the return address in the text section of NTDLL or kernelbase. The process is illustrated in the diagram below: https://www.zscaler.com/blogs/security-research/analyzing-new-hijackloader-evasion-tactics Page 3 of 10 Figure 2: Diagram depicting how HijackLoader traverses the stack to retrieve and patch the return addresses to spoof stack frames. The name of this legitimate system DLL is specified in the HijackLoader  SM module. After this, HijackLoader employs the Heaven’s Gate technique, which allows it to switch from executing 32-bit (x86) code to executing 64- bit (x64) code. Once in 64-bit mode, HijackLoader performs the direct syscall. HijackLoader uses the syscall number ( ssn ) and the necessary parameters for the native system service API to execute the direct syscall. Following the syscall, HijackLoader transitions back to x86 and patches the return address pointers with the actual return addresses. Previously, HijackLoader utilized direct syscalls for process injection and to remap the  .text section of the x64  ntdll.dll in memory with the  .text section of the x64  ntdll.dll from disk. In addition to remapping  ntdll.dll , HijackLoader now also remaps the  .text section of the x64  wow64cpu.dll from disk to memory to remove user-mode hooks. Other than the  ti module, the modules  modCreateProcess ,  modUAC , and  modTask also use call stack spoofing. However, these modules do not use Heaven's Gate or make direct syscalls, but instead invoke Windows API functions directly. https://www.zscaler.com/blogs/security-research/analyzing-new-hijackloader-evasion-tactics Page 4 of 10 The figure below shows the call stack for a call to  CreateProcessW after the return addresses have been patched by the  modCreateProcess module. In the call stack, the return addresses outside of the text section of NTDLL and kernelbase are patched with addresses from the text section of a legitimate system DLL ( shdocvw.dll ) until three adjacent stack frames have the return address in the text section of NTDLL or kernelbase. https://www.zscaler.com/blogs/security-research/analyzing-new-hijackloader-evasion-tactics Page 5 of 10 https://www.zscaler.com/blogs/security-research/analyzing-new-hijackloader-evasion-tactics Page 6 of 10 Figure 3: Example of HijackLoader spoofing the call stack with the fake frames enclosed in a red square. Recent HijackLoader modules The table below lists information about the more recent HijackLoader modules. CRC32 Module Name Description 0x4dad7707 ANTIVM Contains the configurations HijackLoader uses for anti-VM checks (explained in detail in the following section). 0x1999709f MUTEX Contains a mutex name. If a mutex with this name exists, HijackLoader will exit. 0x6703f815 CUSTOMINJECT Contains a legitimate executable file which is used for injecting code into its process memory. The process is created in a custom path specified by the  CUSTOMINJECTPATH module. 0x192a4446 CUSTOMINJECTPATH Contains a file path used to create the legitimate file in the  CUSTOMINJECT module.  0x3115355e modTask Creates a scheduled task for persistence (explained in detail in the next section). 0x9bfaf2d3 modTask64 A 64-bit version of the  modTask module. 0xa2e0ab5d PERSDATA Contains the configuration used by the  modTask module to create scheduled tasks. https://www.zscaler.com/blogs/security-research/analyzing-new-hijackloader-evasion-tactics Page 7 of 10 CRC32 Module Name Description 0xd8222145 SM Contains the name of the system DLL used in call stack spoofing to patch the return addresses.  TinycallProxy module is also copied to this system DLL. 0x455cbbc3 TinycallProxy Acts as a proxy to execute API calls. The call to the  TinycallProxy module will have the address of the API function, number of parameters for the API call, and parameters for the API call as its arguments. 0x5515dcea TinycallProxy64 This module is a 64-bit version of the  TinycallProxy module. Table 2: Description of more recent HijackLoader modules. Virtual machine detection module The virtual machine detection module  ANTIVM contains a configuration used by HijackLoader to identify virtual machines and analysis environments. This configuration is stored in a structure which we will refer to as the  ANTIVM_STRUCT , as shown below. struct ANTIVM_STRUCT { uint32_t antiVMType; uint32_t timeThreshold; uint32_t minPhysicalMemory; uint32_t minProcessorCount; uint32_t antiVMType2; wchar_t username[20]; // Hardcoded to "george" (may change between samples) byte PhysicalMemory; byte ProcessorCount; }; The first member,  antiVMType determines the type of anti-VM check to be performed. These checks employ common anti-VM techniques. The  antiVMType can include multiple values combined using bitwise OR operations. The values supported are listed in the table below. https://www.zscaler.com/blogs/security-research/analyzing-new-hijackloader-evasion-tactics Page 8 of 10 Value Check Performed 0x1 Calculates the average time taken to execute the CPUID instruction using the RDTSC instruction and compares it against the timeThreshold member of the  ANTIVM_STRUCT . If the measured time equals or exceeds the timeThreshold, HijackLoader exits. 0x4 Calls the CPUID instruction with EAX set to 1 and checks if the 31st bit of the ECX register (the hypervisor present bit) is set. If the bit is set, HijackLoader terminates. 0x8 Retrieves the maximum input value for hypervisor CPUID information by calling the CPUID instruction with EAX set to 0x40000000. If this value is greater than or equal to 0x40000000, HijackLoader exits. For instance, on Microsoft hypervisors, this value will be at least 0x40000005. 0x10 Retrieves the total physical memory of the system in gigabytes and compares it to the minPhysicalMemory member of the  ANTIVM_STRUCT . If the total physical memory is less than or equal to minPhysicalMemory, HijackLoader exits. 0x20 Retrieves the number of processors on the system and compares it to the minProcessorCount member of the  ANTIVM_STRUCT . If the processor count is less than or equal to minProcessorCount, HijackLoader exits. 0x40 Encompasses multiple checks, determined by the antiVMType2 member of the  ANTIVM_STRUCT. The supported checks are: 0x1 - Verifies if the computer name consists only of numbers.  0x2 - Verifies if the username matches the username member of the  ANTIVM_STRUCT .  0x4 - Verifies if HijackLoader is executed from the Desktop folder or any of its subfolders.   ANALYST NOTE: These three checks appear to be in development, as HijackLoader does not exit even if the conditions are met.   Additionally, irrespective of the antiVMType2 value, HijackLoader compares the system's total physical memory in gigabytes with the PhysicalMemory member of the  ANTIVM_STRUCT and the number of processors with the ProcessorCount member of the  ANTIVM_STRUCT . If both of these https://www.zscaler.com/blogs/security-research/analyzing-new-hijackloader-evasion-tactics Page 9 of 10 Value Check Performed checks are equal (which may be a specific configuration for a malware sandbox), HijackLoader exits. Table 3: Description of values supported by the HijackLoader virtual machine detection module. Persistence module Before transferring control to the  modTask persistence module, the  ti module copies itself to a new address and the ti module copy is XOR’ed with the performance counter value obtained by calling the QueryPerformanceCounter API. The new address of the XOR’ed ti module and the XOR key are stored for restoration purposes. When control is transferred to the  modTask module, HijackLoader begins by overwriting the entire plaintext  ti module with zeros. HijackLoader then performs call stack spoofing as previously described. Next, the  modTask module copies the  TinycallProxy module into the text section of the system DLL specified in the  SM module and uses this copied  TinycallProxy module to call APIs.  Then, HijackLoader creates a scheduled task for persistence using the configuration in the  PERSDATA configuration module. The configuration is stored in a structure which we will refer to as the  PERSDATA_STRUCT , with the definition shown below. struct PERSDATA_STRUCT { uint32_t triggerTaskOnLogon; // If set, the task will be triggered when the // user logs in, otherwise the task will execute // at regular intervals. uint32_t TaskFlag; // Flag used in ITask::SetFlags method uin32_t MinutesInterval; // Task execution interval in minutes uin32_t wRandMinutesInterval;// Unused by the TASK_TRIGGER structure wchar_t taskName[50]; // Name of the task }; More information about HijackLoader’s modules are available in our previous blog. Source: https://www.zscaler.com/blogs/security-research/analyzing-new-hijackloader-evasion-tactics https://www.zscaler.com/blogs/security-research/analyzing-new-hijackloader-evasion-tactics Page 10 of 10