Keypoints
- Sample employs indirect syscalls by resolving System Service Numbers (SSNs) and locating syscall instructions in ntdll, then calling syscalls via a global address to evade user-mode hooks.
- The SSN is computed by parsing the process PEB, enumerating ntdll exports (Zw* APIs), hashing API names, sorting by RVA, and using the index as the SSN.
- Syscall instruction addresses are found by scanning function bodies in ntdll for the 0x0F05 opcode (syscall) and a randomized-offset variant is used to spoof ETW tracing.
- Strings and payloads are obfuscated: XMM-register based string deobfuscation and encrypted data sections that decode to base64 then XOR with an embedded key to recover payloads.
- Decrypted payloads include a second stager and an UPX-packed XMRig miner; the miner is injected into a suspended svchost.exe via ZwAllocateVirtualMemory/ZwWriteVirtualMemory/ZwSetThreadContext and resumed.
- Persistence is achieved via a Run registry key, creating a Windows service, and a memory-resident injected conhost that preserves and restores the main stager from memory if deleted.
- Common Zw/Nt APIs used by the loader include ZwCreateFile, ZwWriteFile, ZwAllocateVirtualMemory, ZwWriteVirtualMemory, ZwCreateUserProcess, ZwSetThreadContext, and ZwResumeThread.
MITRE Techniques
- [T1106] Native API – The sample invokes kernel routines via direct syscalls to bypass user-mode hooks; it is described as ‘it was using Indirect Syscall.’
- [T1027] Obfuscated Files or Information – The loader obfuscates constants and strings to evade pattern detection; ‘this malware tries to evade pattern based signatures by obfuscating the constants.’
- [T1140] Deobfuscate/Decode Files or Information – Encrypted payloads and strings are decrypted at runtime (base64 + XOR) to recover payloads and configuration; ‘both the payloads are in an encrypted form which are decrypted similar to how the strings were decrypted’.
- [T1055] Process Injection – The miner is injected into a suspended svchost.exe (and a second stager into conhost.exe) using virtual memory allocation, write, context change, and resume; ‘the decrypted Coin Miner payload is injected using ZwWriteVirtualMemory… ZwSetThreadContext… ZwResumeThread’.
- [T1547.001] Boot or Logon Autostart Execution: Registry Run Keys/Startup Folder – The malware copies itself to %appdata% and ‘adds a registry entry pointing to the self-copied executable’.
- [T1543.003] Create or Modify System Process: Windows Service – If elevated, it creates a service for persistence using sc.exe; example: ‘sc.exe create “EHKHFYFV” binpath= “C:ProgramDatadiofjoocyskyzeuxyrjalpyd.exe” start= “auto”’.
- [T1036] Masquerading – The sample uses fake binary properties and an invalid WinRAR certificate to appear legitimate; ‘the sample we obtained even had an invalid WinRAR certificate, with fake binary properties.’
Indicators of Compromise
- [File Hashes] Malware binaries – 64B2AC072D69299CA063190DE16D3230 (Stager), C52DB71D016305B83F064D7199C2C57B (Coin Miner)
- [File Names / Drivers] Dropped components and drivers – Winring0.sys (dropped to %TEMP%), ProgramDatadiofjoocyskyzeuxyrjalpyd.exe (example service binary name)
- [Paths] Persistence and staging locations – %appdata% (self-copy for persistence), Temp folder (Winring0.sys), and system root used for process creation
- [Service Name] Persistence service – EHKHFYFV (created via sc.exe command)
This stager implements indirect syscalls by wrapping native calls in a chain of MOV/CALL sequences: one routine computes the System Service Number (SSN) for a target Zw/Nt API, another finds a syscall instruction address in ntdll, and a third calls the resolved syscall address stored in a global variable. To obtain SSNs the loader parses the process PEB to locate ntdll in the InMemoryOrderModuleList, enumerates exports for names beginning with “Zw”, hashes 2-byte segments of each API name with a constant and ROR24, stores (Hash, RVA) pairs, sorts by RVA, and uses the index of a hash match as the SSN. For syscall addresses it scans each function body (starting at the function RVA + dllbase) for the 0x0F05 opcode within a 0x40-byte window; it then uses the found offset as the assumed location across other APIs or alternatively computes a randomized address (via counter + hardcoded offset) to confuse ETW tracing.
Parameters for direct syscalls are passed either as hardcoded immediate values or pushed on the stack when dynamic values are required; before returning from the wrapper the malware manipulates the return address (pop/push) so that the caller flow continues with intended state and old parameters do not interfere. Strings and payloads are stored obfuscated in .data and decoded at runtime using XMM registers (add with repeated constants then AND masks). Payload decryption yields base64 which is XOR-decoded with a key (itself encrypted in data), revealing two payloads: a second-stage stager and an UPX-packed XMRig miner.
After decryption the miner is launched via process injection: the stager creates a suspended svchost.exe (ZwCreateUserProcess), allocates memory at 0x140000000 in the target (ZwAllocateVirtualMemory), writes the decrypted PE (ZwWriteVirtualMemory), updates the target PEB ImageBase to the new address, sets the thread entry to the injected PE via ZwSetThreadContext, and resumes execution with ZwResumeThread. Persistence is achieved by copying to %appdata% and adding a Run registry key, creating a Windows service when elevated, and injecting a second stager into conhost.exe that keeps the main stager resident in memory and restores it if the disk copy is removed.