CONTACT US

The Return of Ghost Emperor’s Demodex

A Comprehensive Look at the Updated Infection Chain of Ghost Emperor’s Demodex Rootkit.

Executive Summary

  • In late 2023, Sygnia’s Incident Response team was engaged by a client whose network was compromised and was leveraged to penetrate one of its business partner’s network.
  • During the investigation, several servers, workstations, and users were found to be compromised by a threat actor who deployed various tools to communicate with a set of C2 servers.
  • One of these tools was identified as a variant of Demodex, a rootkit previously associated with the threat group known as GhostEmperor.
  • GhostEmperor is a sophisticated China-nexus threat group known to target mostly South-East Asian telecommunication and government entities, first disclosed by Kaspersky in a blog published in September 2021.
  • GhostEmperor employs a multi-stage malware to achieve stealth execution and persistence and utilizes several methods to impede analysis process.
  • Usually, once the threat group gains initial access to the victim’s network by using vulnerabilities such as ProxyLogon, a batch file is executed to initiate the infection chain.
  • In this blog we describe a new infection chain deployed by GhostEmperor, which includes several loading schemes and various obfuscation techniques utilized by the threat group.

Introduction

During Sygnia’s analysis of the forensic findings extracted from the victim’s environment, the team found strong resemblance to the multi-stage tool which was described in Kaspersky’s blog from 2021. However, our investigation yielded some alterations in the infection chain and a slightly different C++ DLL variant.

Among these alterations, the variant we analyzed incorporates an EDR evasion technique and uses a reflective loader to execute the Core-Implant. Additionally, we identified the use of different file names and registry keys. The variant we encountered appears to have been compiled in July 2021, suggesting it might be a more recent version than the one originally analyzed by Kaspersky.

This blog post focuses on the key differences we identified and analyzed in the infection chain and the loading scheme operations.

New Infection Chain Flow Graph
Infection Chain: Process Tree Overview
Infection Chain: Process Tree Overview

WMIExec

WMIExec is a command-line tool used for executing commands on remote Windows systems through Windows Management Instrumentation (WMI).
It is part of the Impacket Toolkit, which is an open-source collection of modules written in Python for programmatically constructing and manipulating network protocols, that is commonly used by threat actors and red teams.

During our investigation, we observed that the threat actor used this tool to run a batch file, initiating the infection chain on the victim’s compromised machine. The output logs were saved to a file located at c:\windows\temp using a local SMB path. The following command was executed:

cmd.exe /Q /c c:\windows\vss\1.bat > \127.0.0.1\C$\Windows\Temp[generated_string] 2>&1

Snippet showcasing the WMIExec command being executed on a victim machine with batch script '1.bat'
Snippet showcasing the WMIExec command being executed on a victim machine with batch script ‘1.bat’

Batch File

The batch file starts the infection by installing the malware and obtaining persistency by the following actions:

It starts by dropping a CAB file named “1.cab” to C:\Windows\Web. CAB is a compressed archive format commonly utilized in Windows to bundle multiple files.
The batch file then uses expand.exe – a native Windows tool used for file extraction from compressed Cabinet files (.cab), to extract these four files:

  • prints1m.dll – Service DLL.
  • Service.ps1 – encrypted Powershell.
  • config.REG – registry dump of AES decryption key.
  • AesedMemoryBinX64.REG – registry dump of AES-encrypted shellcode containing the Core-Implant.

Next, the batch file imports the two registry files using the reg.exe import [file] command to set two registry keys with encrypted values, which will be used later to execute the next stage.

Snippet from Registry Explorer showcasing the embedded payload stored in the registry value 'inputlog'.
Snippet from Registry Explorer showcasing the embedded payload stored in the registry value ‘inputlog’.

The threat actor employs several LOLBins such as reg.exe and expand.exe within the batch file to achieve stealthiness as they are legitimate and signed Microsoft built-in tools which do not arouse any suspicion.

The Batch file proceeds and executes an encrypted PowerShell script, passing a decryption key as a parameter. This script contains an encrypted blob, which, once decrypted using the provided key, reveals another PowerShell script that is executed.

A command line executing the PowerShell script and the decryption argument
A command line executing the PowerShell script and the decryption argument

PowerShell script

The decrypted PowerShell script creates a new service named “WdiSystem” that loads the malicious Service DLL (prints1m.dll). It also creates a service group called “WdiSystemhost” and runs the malicious service within this group. By running the malicious service within the context of the “WdiSystemhost” service group, the threat actor masquerades the malware’s execution as a legitimate Windows system process, as it resembles the authentic and legitimate WdiSystemHost (“Windows Diagnostic System Host” service).

Rogue “WdiSystemhost” service in process list
Rogue “WdiSystemhost” service in process list

To accomplish this technique, the script carries out the following steps:

  • Creates a service by invoking the New-Service PowerShell command with svchost.exe as the binary path of the service.
  • Creates a service group named “WdiSystemhost” by adding a new registry key in HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentCersion\SvcHost:
Registry view of service groups managed by svchost
Registry view of service groups managed by svchost

The lowercase “host” in the name suggests it is a rogue version. The original name is “WdiSystemHost”

  • Wires the malicious service DLL (prints1m.dll) to the service by setting a “ServiceDll” registry key with the DLL’s path as the value, located in HKLM:\SYSTEM\CurrentControlSet\Services\WdiSystem\Parameters.
Registry view of the key that dictates the DLL associated with the malware’s service.
Registry view of the key that dictates the DLL associated with the malware’s service.
  • Runs the service by invoking the Start-Service PowerShell command.
  • Launches the malicious service DLL (prints1m.dll) as a service which is executed within the service group.
The PowerShell script after decryption
The PowerShell script after decryption

Prints1m.dll – Service DLL

This Service DLL dynamically loads all of the necessary functions it requires for operation by navigating through an internal OS structure named Process Environment Block, which contains the already loaded libraries and functions in the process.

The Kernel32 library, loaded by default in every process, is used by the malware to access the LoadLibraryA function, which is responsible for loading DLLs into the process.

Subsequently, an encrypted configuration located at the DLL’s data section (offset 0x4050) is decrypted using a custom decryption scheme, which contains the following parameters:

  • Initial sleep time.
  • Registry paths of the shellcode location (which was established by the batch file).
  • A list of module and function names required for operation (offset 0x45F0).

The service uses this list to create an in-memory Import Address Table, loading the modules it requires using the LoadLibraryA function, and traverses each module’s export table to obtain the necessary functions.

Part of service’s code to dynamically load necessary functions
Part of service’s code to dynamically load necessary functions
Memory view of the decrypted configuration, showing the list of functions
Memory view of the decrypted configuration, showing the list of functions
Memory view of the decrypted configuration, showing the path of the encrypted shellcode
Memory view of the decrypted configuration, showing the path of the encrypted shellcode

After setting up an anti-hooking technique (which will be described in the next section), the service
initiates the next stage by spawning a new thread. It then sleeps for 15 seconds before attempting to decrypt and execute the next stage, which is retrieved from the registry keys set by the batch file. In case of failure, it retries at intervals of 30 to 60 seconds until successful execution is achieved.

snippet of code showing the decryption loop
Snippet of code showing the decryption loop

EDR Evasion and Anti-User-Mode Hooking Technique

Antivirus and EDR solutions typically inject DLLs into the address space of running applications to facilitate user-mode hooking, thus identifying and preventing malicious activity within the processes.
During our investigation we observed that the threat actor added an evasion technique to the Service DLL by setting a specific mitigation policy to the process:

Calling SetMitigationPolicy with ProcessSignaturePolicy as parameter to set the mitigation policy
Calling SetMitigationPolicy with ProcessSignaturePolicy as parameter to set the mitigation policy

Mitigation policies, such as ASLR, DEP and CFG, are security measures implemented by the OS to mitigate attacks and vulnerabilities such as Buffer Overflows and Code Injections. Some of these mitigation policies are enabled in the process by default. In our investigation, the threat actor set up a particular mitigation named “ProcessSignaturePolicy” which forbid loading DLLs that are not signed by Microsoft to the process.
This means that any security solution trying to inject a DLL not signed by Microsoft will fail to do so. This technique helps circumvent analysis tools by limiting user-mode hooking.

Service’s mitigation policies
Service’s mitigation policies

The fact that many antivirus vendors employ DLLs with a legitimate Microsoft signature, and that some security solutions inject their DLLs prior to the invocation of SetProcessMitigationPolicy, limits the effectiveness of this method.

Shellcode and Reflective loader

The Service DLL reads two encrypted registry keys that were set by the batch file:
“AKey” – an AES decryption key
“inputlog” – an AES-encrypted shellcode containing the core-implant.

Snippet from Sandbox execution of the threat actor's malicious service showing the read activity performed by the service of the two registry keys.
Snippet from Sandbox execution of the threat actor’s malicious service showing the read activity performed by the service of the two registry keys

The service employs the AES algorithm to decrypt the encrypted shellcode retrieved from the “inputlog” registry key. It sets the decryption key from the “AKey” value and uses a null byte array as the Initialization Vector (IV). The shellcode consists of a Position-Independent shellcode functioning as a reflective loader, alongside a corrupted Portable Executable (PE) file, positioned at offset 0x4000. Certain headers within the PE file have been deliberately stripped to enhance resistance to analysis and detection. Specifically, the “MZ” and “PE” headers have been nullified, and the DOS Stub has been removed.

Jump\trampoline at the Start of the shellcode.
Jump\trampoline at the Start of the shellcode
Corrupted PE file located at offset 0x4000
Corrupted PE file located at offset 0x4000

The shellcode loads the core-implant DLL using a reflective loader which performs the following steps:

  • Allocates memory for the core-implant DLL.
  • Parses the custom PE headers of the core-implant.
  • Moves each section to its proper location in the allocated memory.
Code snippet parsing DLL sections and relocating them to the appropriate memory locations
Code snippet parsing DLL sections and relocating them to the appropriate memory locations
  • Performs relocation of the code and data sections to match the new base address.
  • Resolves the import table.
  • Sets proper memory protections.
Code snippet applying correct protections for each section
Code snippet applying correct protections for each section
  • Executes the now-ready Core-Implant by calling its Entry Point.

Core-Implant

The Core-Implant handles two main tasks – managing Command and Control (C2) communication and installing the Demodex kernel rootkit. To load Demodex, the threat actor had to bypass the Driver Signature Enforcement (DSE) security feature, which blocks unsigned drivers.

To do that, the threat actor leveraged “Cheat Engine”, an open-source tool used for video game cheating, and utilized its signed driver, dbk64.sys, to manipulate memory and execute code in kernel space. the threat actor used this driver to map and execute a shellcode in kernel space which patches the IOCTL Dispatcher of the dbk64.sys driver. This modification adds functionality to the driver that enables it to load the Demodex driver.

An analysis of the Core-Implant’s metadata shows that the threat actor modified the compilation and export-table timestamp of the Core-Implant to 12 Feb 2016. However, the timestamp of the debug section is set to 02 July 2021, which might indicate that this is the actual time this implant was created.

Core-Implant’s timestamps retrieved from PE Studio
Core-Implant’s timestamps retrieved from PE Studio

Appendix – IOC

DescriptionHash
Service DLL – prints1m.dllMD5: 4bb191c6d3a234743ace703d7d518f8f
SHA1: 43f1c44fa14f9ce2c0ba9451de2f7d3dd1a208de
PowerShell script – service.ps1MD5: 95e3312de43c1da4cc3be8fa47ab9fa4
SHA1: a59cca28205eeb94c331010060f86ad2f3d41882
Cheat Engine driver – dbk64.sysMD5: d8ebfd26bed0155e7c4ec2ca429c871d
SHA1:  bab2ae2788dee2c41065850b2877202e57369f37
C2 Domainimap.dateupdata[.]com
C2 IP193.239.86.168
subsctibe decor
Want to get in touch?