---
title: "ValleyRAT sideloads through a signed Microsoft profiler"
description: "Tax-themed ISOs sideload ValleyRAT through a signed Visual Studio tool. Five months of builds share one transport key and a fallback text file."
url: https://adamnet.works/blog/valleyrat-signed-profiler-and-19-byte-text-file/
index: https://adamnet.works/llms.txt
---

[All Security Research](https://adamnet.works/blog/security-research.md)

Security Research · ValleyRAT · DLL Sideloading · Remote Access Trojans

# ValleyRAT hides behind a Microsoft profiler and a 19-byte text file

Tax-themed ISOs sideload ValleyRAT through a signed Visual Studio tool. Five months of builds share one transport key and a text file that hands out new servers.

Kirk | ADAMnetworks • October 22, 2026

![An exploded metal file case with glowing orange circuit layers between its panels, a code panel on the left, and smaller sealed cases and a world map in the background.](https://adamnet.works/uploads/valleyrat-hero.webp)

## Key takeaways

- On 14 October 2026, an ISO named `New Tax Filing Regulations.iso` on Alibaba Cloud storage started a ValleyRAT infection through a Microsoft-signed Visual Studio profiler. The profiler loads a replacement `VSPMsg.dll` that decrypts the remote access trojan (RAT) into Explorer.
- The RAT’s server pushed an installer that writes a second copy of the signed profiler, a loader padded to 102 MiB, and a file named `config.log` that holds a second RAT. A logon task or a Run key restarts the bundle.
- We recovered 50 client configurations labelled January to October 2026. Since June, the builds share one 32-byte key, and the client uses that key to derive every session key. The same client recurs under XTEA, RC4, XOR and LZ4 wrappers.
- Every configuration since June names a fallback URL. After 20 failed connections, the client downloads a text file and moves to the `host:port` written in it. Every fallback file that answered in October pointed to `8.218.118.101:5252`.
- Since July, every initial client we recovered sends its first C2 connection to a bare IP address with no DNS lookup. Defenders can hunt for the signed profiler outside Visual Studio folders, `config.log` files under `C:\ProgramData\EdgeUpdate`, and the indicators below.

## Background

ValleyRAT is a Windows RAT that [Proofpoint named in 2023](https://www.proofpoint.com/us/blog/threat-insight/chinese-malware-appears-earnest-across-cybercrime-threat-landscape). [Zscaler’s 2024 analysis](https://www.zscaler.com/blogs/security-research/technical-analysis-latest-variant-valleyrat) credits QiAnXin with first identifying it and tying it to the group known as Silver Fox. [Check Point’s study of the ValleyRAT builder](https://research.checkpoint.com/2025/cracking-valleyrat-from-builder-secrets-to-kernel-rootkits/) describes a first-stage “Online Module” and a main “Login Module” that handles registration, profiling and plugins. The same report notes that the builder leaked publicly, so anyone can produce ValleyRAT clients. Tax-themed lures run through reporting on Taiwan from [Fortinet](https://www.fortinet.com/blog/threat-research/winos-spreads-via-impersonation-of-official-email-to-target-users-in-taiwan), India from [CloudSEK](https://www.cloudsek.com/blog/silver-fox-targeting-india-using-tax-themed-phishing-lures), Japan from [ESET](https://www.welivesecurity.com/en/business-security/cunning-predator-how-silver-fox-preys-japanese-firms-tax-season/), and 2026 campaigns from [Kaspersky](https://securelist.com/silver-fox-tax-notification-campaign/119575/) and [Forcepoint](https://www.forcepoint.com/blog/x-labs/valleyrat-overwolf-sideload-tax-scam).

Because the builder is public, this post groups samples by the bytes they share. It follows one October ISO from the lure to the second RAT, using static analysis and decrypted sandbox traffic. It then works backward through 50 recovered configurations, labelled January to October 2026, using three links: identical login modules, one transport key, and a chain of fallback text files.

Figure 1 shows the October chain.

![Flow diagram of the October chain. A tax ISO holds a signed VSPerf EXE and VSPMsg.dll. The DLL decrypts RAT 1 into explorer.exe. RAT 1 connects to 8.210.231.207:9090 and receives an installer. The installer writes a random-named copy of the EXE, a 102 MiB VSPMsg.dll and config.log to C:\ProgramData\EdgeUpdate, registers a logon task or Run key, and adds Defender exclusions. The second DLL injects config.log into explorer.exe, where RAT 2 connects to 8.210.231.207:6666. Both RATs fall back to shougong9[.]com/hm.txt.](https://adamnet.works/uploads/valleyrat-figure-1-attack-flow.svg)

_Figure 1: The October infection chain, from the tax ISO to the second RAT._

## Initial access: tax lures in Alibaba Cloud buckets

The October ISO was served from the Alibaba Cloud Object Storage Service (OSS) bucket `notice8` in the Singapore region. The object was uploaded at 03:45:37 UTC on 14 October 2026, and a sandbox received the file at 07:15 UTC the same day. The 786,432-byte disc image holds two files: `New Tax Filing Regulations.exe` and `VSPMsg.dll`. Windows mounts an ISO as a drive when it is opened, so the victim sees one document-named program and a DLL beside it.

The same lure set ran through a second bucket. `material-checklist`, in the Kuala Lumpur region, served `ITR_0ca1-2.img` on 16 September 2026, and then four new tax ISOs on 15 October 2026:

| Object | Size (bytes) | Sideloaded DLL name |
| - | - | - |
| `Filing Regulations.iso` | 595,968 | `wmicodegen.dll` |
| `Fiscal Penalty List.iso` | 454,656 | `winhttp.dll` |
| `Tax-Investigation.iso` | 792,576 | `VSPMsg.dll` |
| `Tax-Penalty-List.iso` | 806,912 | `VSPMsg.dll` |

All four ISOs decode to the same 357,376-byte login module as the `notice8` ISO. The configuration is also identical, down to the remark field, which reads “mailbox” in Chinese. Only the wrapper changes. The bucket listing showed the four ISOs uploaded at 00:20:41 UTC. The copies we downloaded nine minutes later carried a Last-Modified time of 00:26:11 UTC and different MD5 hashes, with the same names and sizes.

In August, two other buckets served “Statement of Account” disc images. `xcxc-prod` (Kuala Lumpur) and `in0810` (Dubai) carried images such as `StatementofAccoun_0812.img`. Each decoded to a client for `47.75.119.86:5353` or `47.238.108.53:5353`. Other lure names in the same builds include `LHDNTAX` (Malaysia’s Inland Revenue Board), bank statements, account reconciliations, procurement contracts and a meeting agenda. The containers include ISO, IMG, ZIP, encrypted 7z, RAR and double-extension `.exe.iso` files.

## Technical analysis

### Stage 1: a signed Microsoft profiler loads the replacement DLL

`New Tax Filing Regulations.exe` is the Visual Studio “VSPerf Performance Control Tool”, version 17.0.36015.10, signed by Microsoft Corporation and timestamped 15 April 2025. Its Authenticode digest and certificate chain verify offline. Zscaler documented ValleyRAT sideloading through WINWORD, CloudSEK through Thunder, and Forcepoint through Overwolf. We found no prior report of VSPerf in that role.

The profiler has a mandatory import of `VSPMsg.dll` by bare name, calling the exports `SetErrorMessageModule` and `GetErrorMessageModule`. Windows searches the application’s own folder first, so it loads the DLL from the mounted ISO. Initialization of an imported DLL runs before the program’s own entry point, so the malicious code executes before the profiler does anything.

![Import table listing for New Tax Filing Regulations.exe showing VSPMsg.dll with the imports SetErrorMessageModule and GetErrorMessageModule.](https://adamnet.works/uploads/valleyrat-figure-2-signed-host-imports.webp)

_Figure 2: The signed profiler imports two functions from `VSPMsg.dll`, which the attacker replaces._

The malicious DLL carries a version resource claiming to be a Qualcomm Atheros wireless driver. It loads the genuine `VSPMsg.dll` from System32 and forwards both exports to it, so the profiler’s calls still resolve.

### Stage 2: the loader decodes the RAT into Explorer

The loader hides its strings with single-byte XOR `0x9c` and resolves Windows APIs from an 81-entry table of numeric IDs. Its payload sits in nine chunks that join into 316,084 encoded bytes. A custom routine at `0x180003240` turns every four input bytes into three. It XORs each byte with a lane key (`7f 76 27 4e`), subtracts `0x21`, and packs the four 6-bit results.

![Ghidra decompiler view of function 0x180003240 showing per-lane XOR constants, a 0x21 subtraction, and shifts packing four values into three bytes.](https://adamnet.works/uploads/valleyrat-figure-3-four-to-three-decoder.webp)

_Figure 3: The four-to-three byte decoder at `0x180003240` in the ISO’s `VSPMsg.dll`._

The decoded container holds a label (`New Tax Filing Regulations`), a cipher selector and feature flags. Selector 2 picks a modified XTEA cipher with 32 rounds and delta `0x9700b148` in place of the standard `0x9e3779b9`. After decryption, the loader XORs the buffer with the repeating key `e3 ea bb d2` and decompresses it with LZ4 into 359,121 bytes. That result is a reflective loader stub, followed at offset `0x6d1` by the RAT itself, a 357,376-byte DLL. Re-encrypting the recovered plaintext reproduces every original ciphertext block.

One flag enables anti-VM checks. They look for VMware Tools and VirtualBox Guest Additions registry keys, the `\\.\vmci`, `\\.\HGFS` and `\\.\VBoxMiniRdrDN` devices, VM driver files, and VM tool processes.

The loader injects into an existing `explorer.exe`:

1. It creates a shared section, maps a writable view locally and copies the payload into it.
2. It maps the same section into Explorer as executable.
3. It creates a suspended thread in Explorer whose start address is `ntdll!NtTestAlert`.
4. It queues an asynchronous procedure call (APC) pointing at the payload, then resumes the thread.

When the thread resumes, `NtTestAlert` drains the APC queue and runs the reflective loader. The victim then sees a message box titled “File Error”: “The file is corrupted and cannot be opened. Please download the file again.”

### Stage 3: the login module calls home

The RAT stores its configuration as a reversed UTF-16 string of `key:value` fields. Reversed, the October configuration reads as follows, with its two Chinese values replaced by English placeholders:

```text
|p1:8.210.231.207|o1:9090|t1:1|p2:|o2:|t2:1|p3:|o3:|t3:1|dd:1|cl:1|fz:<default>|bb:1.0|bz:<mailbox>|jp:1|bh:0|ll:0|dl:0|sh:0|kl:0|bd:0|ur:hxxps://shougong9[.]com/hm.txt|ps:3f7ac1852d9e46b071f308ad5ce92467b81a934fd2607ec538a9158b4cd702f6|
```

`p1` and `o1` are the primary server and port, and `t1:1` selects TCP. `fz` and `bz` are the group and remark, written in Chinese in the sample. `ur` is the fallback URL, and `ps` holds a 32-byte key in hex.

The handshake uses that key. Client and server each send a 16-byte random nonce inside a 52-byte record encrypted with AES-128-CBC under a fixed key, `4e87c23a91f56d20b37e44da089c5bf1`. Both sides then compute HMAC-SHA256 over the two nonces with the 32-byte key, and the first 16 bytes of the result become the AES session key. Every later record carries a length, an IV and AES-CBC ciphertext. The client sends a heartbeat every three seconds.

The configuration parser never reads `ps`. The same 32 bytes are embedded twice more in the code: as an XOR-masked array for TCP and as eight immediate DWORDs for the UDP transport. Both copies feed `BCryptCreateHash` as the HMAC secret. The `ps` text matches the key the code uses, and it is the same in every build from June onward.

When the server stops answering, the client works through a recovery sequence:

- After 10 failed connections, it uses the Windows Firewall COM interface to delete up to 256 block rules that match its server’s address or port.
- After more than 20 failures, it downloads the `ur` URL with the user agent `MSIE 6.0`. It reads up to 1,023 bytes, takes the first line as `host:port`, replaces its primary and secondary servers with it, and forces TCP.
- If the new server also fails, it restores the original servers and keeps cycling.

The operator can also push a new server address that the client writes to `HKCU\Software\Microsoft\Hello`.

The login record profiles the host. Beyond hostname, OS, hardware, integrity level and security products, it checks:

- Whether WeChat, WeCom, DingTalk, Feishu, QQ, Telegram, LINE and WhatsApp are present, including WhatsApp Web storage in Chromium and Firefox profiles.
- 14 cryptocurrency wallet extension IDs across Chrome, Edge, Brave, Vivaldi and Opera, and two Firefox wallet add-ons, including MetaMask.
- Browser history for `.bank.in`, the domain the [Reserve Bank of India reserved for Indian banks](https://www.rbi.org.in/scripts/NotificationUser.aspx?Id=12837&Mode=0). A hit adds the Chinese label “India bank” to the record.
- History for eight cross-border payment services: WorldFirst, PingPong, XTransfer, PayPal, Antom, Stripe, Airwallex and Payoneer.

The dispatcher implements 25 commands. They include screenshots, file delivery and execution, download-and-run, process search, plugin loading, configuration changes, logoff, reboot, power off, and clearing the Application, Security and System event logs.

![Ghidra decompiler view of the RAT command dispatcher at 0x1800120a0, with case 0xc passing Application, Security and System to ClearEventLogW.](https://adamnet.works/uploads/valleyrat-figure-4-dispatcher-event-logs.webp)

_Figure 4: Command `0x0c` in the RAT dispatcher clears three Windows event logs._

A keylogger starts before the C2 loop. It reads the keyboard through DirectInput, polls the clipboard every 1.5 seconds, and writes window titles, timestamps, keys and clipboard text to `%ProgramData%\Microsoft\DeviceSync\DisplaySessionContainers.log`.

### Stage 4: the server pushes an installer

We decrypted four sandbox packet captures with the keys recovered above. They hold 49 completed handshakes and 2,254 application records. The server sends plugins in three steps:

1. It offers a module descriptor.
2. The client answers that it lacks the module.
3. The server sends the descriptor and body.

All 92 deliveries in the captures contain one of two bodies, 46 copies each. Both are the same installer, whose name is `wmi` followed by the Chinese for “scheduled task”: once as a plain 1,028,096-byte DLL and once with a 1,745-byte reflective wrapper in front.

The client’s own status messages record what happened to each copy. The plain DLL reports “loading”, then “released” after its `Main` export returns. The wrapped copy reports “in-memory DLL load failed”. The RAT’s manual mapper requires an `MZ` header, and the wrapped copy starts with a jump instruction (`E9 43 04 00 00`).

![Ghidra decompiler view of the manual PE mapper at 0x180017d60 testing the first two bytes against 0x5a4d before parsing PE headers.](https://adamnet.works/uploads/valleyrat-figure-5-plugin-mapper-mz-check.webp)

_Figure 5: The RAT’s plugin mapper rejects any buffer that does not begin with `MZ` (`0x5a4d`)._

### Stage 5: the installer rebuilds the sideload on disk

Despite its name, the installer makes no WMI calls. Its worker first checks whether the process token belongs to the Administrators group. It exits early if a kernel driver named `k32.sys` is loaded (see “A driver track since July” below). It then creates `C:\ProgramData\EdgeUpdate\<random 8>\` with hidden and system attributes and writes three files:

1. `<random 8>.exe`, a byte-for-byte copy of the signed VSPerf profiler, certificate included.
2. `VSPMsg.dll`, a new loader.
3. `config.log`, 369,361 bytes of executable code.

![Ghidra decompiler view of the installer creating C:\ProgramData\EdgeUpdate, setting attributes to 6, and writing the embedded EXE (0x5bc48 bytes), the padded VSPMsg.dll, and config.log (0x5a2d1 bytes).](https://adamnet.works/uploads/valleyrat-figure-6-installer-writes.webp)

_Figure 6: The installer writes the signed EXE, the padded loader, and `config.log` into a hidden EdgeUpdate folder._

The new `VSPMsg.dll` starts as a 123,904-byte template. The installer overwrites 16 bytes of the DOS header and the PE timestamp with values from a generator seeded by the clock and process ID. It then appends copies of one 64 KiB block until the file reaches 106,954,752 bytes (102 MiB). Every install produces a different file hash.

Persistence depends on the earlier group check:

- Without administrator rights, the installer sets the `HKCU\Software\Microsoft\Windows\CurrentVersion\Run` value `MicrosoftUpdate` to the EXE path.
- With administrator rights, it registers a scheduled task named `\MicrosoftEdgeUpdate\Update`, with the author “Microsoft Corporation”, a logon trigger and the highest run level. The task runs the EXE from the bundle folder.

![Ghidra decompiler view of the task scheduler helper calling Create with type 9 and the ILogonTrigger GUID, then Create with type 0 and the IExecAction GUID.](https://adamnet.works/uploads/valleyrat-figure-7-logon-task.webp)

_Figure 7: The installer builds a logon trigger and an executable action for the `\MicrosoftEdgeUpdate\Update` task._

The administrator branch also runs five hidden PowerShell commands. They add Microsoft Defender exclusions for the `C:\ProgramData\EdgeUpdate` path and for the processes `explorer.exe`, `Thunder.exe`, `RuntimeBroker.exe` and `VSPMsg.dll`. All five commands appear in all four sandbox runs.

### Stage 6: config.log carries a second RAT

The second `VSPMsg.dll` exports the same two functions, and both return zero. On load, it calls `GetModuleFileNameW` to find the folder of the program that loaded it and opens `config.log` in that folder. It reads the whole file in one call and rejects short reads. It then injects the bytes unchanged into Explorer with the same section, `NtTestAlert` and APC sequence as the first loader.

`config.log` uses the same reflective loader as stage 2, with two size bytes changed, and carries a second login module. Of 876 functions, 806 match the first RAT after address normalization, and all 25 commands remain. The configuration changes the port from 9090 to 6666 and the remark from “mailbox” to `ws`. The key and fallback URL are unchanged.

The keylogger switch flips. The first RAT logs keys unless `HKCU\key` value `open` is `0`. The second logs only when that value is `1`, and it writes to `%LocalAppData%\DisplaySessionContainers.log`.

![Ghidra decompiler view of function 0x18000ce90 in the second RAT, comparing a registry value against the string 1 before keyboard capture starts.](https://adamnet.works/uploads/valleyrat-figure-8-keylogger-opt-in.webp)

_Figure 8: The second RAT starts keyboard capture only when the registry value equals `1`._

The two builds can be told apart on the wire. The second RAT’s status record grows from 932 to 1,188 bytes because a label field expanded. Every status record the captures show on port 9090 is 932 bytes, and every one on port 6666 is 1,188 bytes.

## One client, many wrappers

The October ISOs are one example of a pattern that runs through the whole set. The operator changes the outside of the file far more often than the client inside:

- The login module labelled 16 August 2026 ships inside six different DLL builds, protected with RC4, standard XTEA and repeating XOR.
- Three “Statement of Account” images from 10 to 15 August use standard XTEA, RC4 and repeating XOR. Two decode to byte-identical login modules, and the third differs by one byte in its date label.
- A login labelled 21 August 2026 arrives in a numeric ZIP and in an encrypted 7z, through two different decoding chains.
- 76 `config.log` downloads captured from July samples reduce to three payloads. Two are XOR-masked with the ASCII key `MalDev`, and one is plain.

Changing the command server takes even less. On 4 August 2026, one build moved from `156.234.80.154:5252` to `47.75.119.86:5353`. Exactly 18 bytes differ between the two files, all inside the configuration block. With that block masked, the two files hash the same. The three July 21 builds are also identical outside their configurations.

The dropped `config.log` does not always match the client that installed it. One numeric ZIP from August starts a client for `47.243.155.133:5353`, and its `config.log` hands the host to `47.75.119.86:5353`. Other builds drop an older client under a newer loader, or send the second stage to a different server, as the October chain does with ports 9090 and 6666.

The loading side follows the same pattern. July and August plugins named `Plg*.tmp` install a browser host EXE, a `webview_support.dll` and `config.log` into the same `C:\ProgramData\EdgeUpdate\<random 8>\` layout. They register the same `\MicrosoftEdgeUpdate\Update` task, and the non-administrator branch writes a Run value named in Chinese for the Thunder (Xunlei) download service. The August plugin mutates the same 16 DOS-header bytes and timestamp as the October loader writer, and the July and August plugins share a byte-identical random-name routine.

## The key and the fallback link builds from April to October

Two configuration fields connect the builds across months.

The `ps` key first appears in builds labelled 15 June 2026. Those June clients are 196,608-byte login modules that encrypt their configuration with AES-128 before reversing it. They use domain names on port 443: `a.qqmusic1[.]com`, `c.360ctct[.]com`, `b.360ctct[.]com` and `360nn3[.]icu`. The June code stores the same 32 bytes in the same two places as October and feeds them to `BCryptCreateHash` in the same way. The encoded key arrays in June and October are byte-identical. Every build after June that we recovered carries the same `ps` value.

The fallback URL tells the rest of the story:

| Labels | Fallback URL | C2 style |
| - | - | - |
| 17 April 2026 | `appfenxiang[.]com/add.txt` | `c.qqmusic1[.]com:4343` |
| 25 April 2026, June 2026 | `appfenxiang[.]com/hm.txt` | Domains on ports 433 and 443 |
| July 2026 | `appfenxiang[.]com/hm3601.txt` to `hm3605.txt`, `hm007.txt` | Bare IPs on 5252 |
| 4 August to October 2026 | `shougong9[.]com/hm.txt` | Bare IPs on 5252, 5353, 6666, 6868, 9090 and 443 |

In July, each server got its own numbered fallback file. `47.75.103.130` used `hm3601.txt`, `47.243.36.18` used `hm3602.txt`, `47.86.111.44` used `hm3603.txt`, and `47.75.119.86` used `hm3605.txt`. From August, every build uses `hxxps://shougong9[.]com/hm.txt`. That domain was registered on 22 July 2026.

![Four stacked boxes for April, June, July and August to October 2026 builds, each listing its fallback URL, C2 style and key status. Arrows from the June, July and August to October boxes point to a box for 8.218.118.101:5252, the address the fallback files returned on 14 and 15 October 2026.](https://adamnet.works/uploads/valleyrat-figure-9-fallback-convergence.svg)

_Figure 9: Fallback URLs by build period, and the server they all named in October 2026._

On 3 October 2026, a URLScan capture saved the full body of `appfenxiang[.]com/hm3605.txt`: 19 bytes, `8.218.118.101:5252` and a newline. On 13 October, a sandbox run of `Open_to_view_0a7a.iso` fetched `shougong9[.]com/hm.txt` and connected to `8.218.118.101:5252` one second later. That build’s primary server was `202.146.222.95:443`. Our collection log for 14 and 15 October records `shougong9[.]com/hm.txt`, `appfenxiang[.]com/hm.txt` and `hm3601.txt` to `hm3605.txt` all returning `8.218.118.101:5252`. `hm3604.txt` answered the same way, although no client we recovered names it. Since September, `shougong9[.]com` and `appfenxiang[.]com` have resolved to the same address, `47.76.110.255`.

One text server reaches back to builds that are months old. The June domain `360ctct[.]com` lapsed on 20 September 2026, and the July clients each point at their own numbered file. After 20 failed connections, all of them end up on `8.218.118.101:5252`.

The May link is a single file. A sandbox run of a May wrapper, submitted on 16 May 2026, fetched `hxxps://jackhm[.]oss-cn-hongkong[.]aliyuncs[.]com/a86.dat` and saved it as `C:\Users\Public\Downloads\a.png`. We rebuilt the TLS session from the capture, and all 24 records pass AES-GCM authentication. The response body is byte-identical to the saved `a.png`. At offset 1,471 it holds a 324,608-byte login module labelled 25 April 2026, with the fallback `hxxps://appfenxiang[.]com/hm.txt`, which the June builds use exactly. The server’s Last-Modified header is 25 April 2026, the same date as the label.

The `appfenxiang[.]com` line runs back one more step. A client labelled 7 April 2026 was hidden by least-significant-bit steganography in a file named `QQmusic.mp3`, inside a 30 MB Nuitka-compiled program. That client shares a byte-identical 79-byte string-reversal routine with the 17 April build, which introduced the `appfenxiang[.]com/add.txt` fallback, and its configuration parser is an earlier, smaller version of the same code.

## A driver track since July

Two July plugins, `Plg7D88.tmp` and `Plg45BE.tmp`, carry the login modules for `47.243.36.18` and `47.75.103.130` and a 28,384-byte kernel driver named `k32.sys`. The plugin first writes the 322,257-byte RAT shellcode into `HKLM\SOFTWARE` as a REG_BINARY value named `IpDates`, the registry name [Check Point documented](https://research.checkpoint.com/2025/cracking-valleyrat-from-builder-secrets-to-kernel-rootkits/) for operator shellcode. It then adds Defender exclusions for `C:\Windows\System32\drivers` and `services.exe`, writes the driver, and creates and starts the kernel service `k32_service`.

The driver carries a code-signing certificate issued to Shenzhen Liantian Technology Co., Ltd, valid from 26 April 2012 to 26 April 2013. Its code:

- Reads `IpDates` and queues a kernel APC into `winlogon.exe` to run the shellcode.
- Writes `DisableAntiSpyware`, `DisableAntiVirus` and `TamperProtection` policy values for Microsoft Defender, and changes the `Start` values of the `WdBoot`, `WdFilter`, `WdNisSvc` and `WinDefend` services.
- Targets the process, thread, image-load, registry and minifilter callbacks that `WdFilter.sys` registers.
- Registers its own minifilter and registry callback to hide its file and service key.

The October code knows about this driver. The installer exits before writing anything if `k32.sys` is loaded, and the RAT reports the driver’s presence to its server.

## Infrastructure

Most command servers sit in Alibaba Cloud address space (AS45102). The rest are on Sun Network Hong Kong (`202.146.222.95`), Zillion Network (`207.56.119.83`) and Yancy Limited (`156.234.80.154`). Payload delivery runs through Alibaba OSS buckets in Hong Kong, Singapore, Kuala Lumpur and Dubai.

| Date (2026) | Event |
| - | - |
| 25 April | `a86.dat` placed in the `jackhm` bucket (Last-Modified) |
| 15 June | Earliest sample with the `ps` key (12:02:41 UTC submission) |
| 22 July | `shougong9[.]com` registered |
| 4 August | First build with the `shougong9[.]com/hm.txt` fallback; 18-byte server change |
| 10 to 27 August | Statement of Account images in `in0810` and `xcxc-prod` |
| 17 September | `shougong9[.]com` moves to `47.76.110.255`, where `appfenxiang[.]com` already resolved from 5 September |
| 3 October | `hm3605.txt` body saved: `8.218.118.101:5252` |
| 5 October | `cicfo[.]com`, a C2 domain in an August `config.log`, passes to registrar expiry parking |
| 14 October | `New Tax Filing Regulations.iso` uploaded to `notice8` |
| 15 October | Four tax ISOs in `material-checklist` replaced within six minutes of listing |

`cicfo[.]com:6666` appears in a dropped `config.log` with the shared key and fallback. Historical DNS put the apex domain on `202.146.222.95` and its `m` and `www` names on `207.56.119.83`. Both addresses are C2 servers in other recovered configurations.

The `material-checklist` bucket also held `file.zip`, uploaded on 23 September 2026. It is a ManageEngine Endpoint Central (UEMS) agent bundle, version 11.5.2624.08.W, set to install silently and enroll with `hxxps://116[.]213[.]43[.]154:8383`, server name `NTT-TG-02669-5`. The bundle’s deployment CA certificate was created at 09:18:54 UTC that day and matches the certificate chain the server presents on ports 8383 and 8443.

## Detection opportunities

These behaviors hold across builds:

- `VSPerf` or `VSPerfCmdUI`-versioned executables running outside a Visual Studio install path, especially from a mounted ISO or `C:\ProgramData\EdgeUpdate\`. The file is signed by Microsoft, so alert on its location and on the DLL loaded beside it.
- An unsigned `VSPMsg.dll`, `winhttp.dll` or `wmicodegen.dll` loaded from the same folder as the executable that imports it.
- A `VSPMsg.dll` of 106,954,752 bytes, or any DLL padded with one repeated 64 KiB block.
- A file named `config.log` that begins with the bytes `E9 43 04 00 00`, or any `config.log` read by a process that then opens Explorer.
- An `explorer.exe` thread whose start address is `ntdll!NtTestAlert`, created suspended by another process.
- The scheduled task `\MicrosoftEdgeUpdate\Update` with the author “Microsoft Corporation”, or an HKCU Run value `MicrosoftUpdate` that points into `C:\ProgramData\EdgeUpdate\`.
- PowerShell `Add-MpPreference -ExclusionProcess 'VSPMsg.dll'`, a DLL name in a process exclusion.
- HTTP requests with the user agent `MSIE 6.0` for a `.txt` file, followed by a TCP connection to the `host:port` in the response.
- Deletion of Windows Firewall block rules by a process that then connects outbound.
- The kernel service `k32_service` or a REG_BINARY value `IpDates` under `HKLM\SOFTWARE`.

These indicators change with each build: file hashes of wrappers and ISOs, the dropped `VSPMsg.dll` and `webview_support.dll` hashes (mutated per install), and command-server addresses.

## Indicators of compromise (IOCs)

### Network indicators

| Indicator | Type | Context |
| - | - | - |
| `8[.]210[.]231[.]207:9090` | C2 | October ISO, first RAT |
| `8[.]210[.]231[.]207:6666` | C2 | October `config.log`, second RAT; ITR image |
| `8[.]210[.]231[.]207:6868` | C2 | September build |
| `8[.]218[.]118[.]101:5252` | C2 | Server named in every fallback file, October 2026 |
| `202[.]146[.]222[.]95:443` | C2 | August and October builds |
| `207[.]56[.]119[.]83:6666` | C2 | August builds |
| `cicfo[.]com:6666` | C2 | August `config.log` |
| `156[.]234[.]80[.]154:5252` | C2 | 4 August build |
| `47[.]75[.]119[.]86:5353`, `:5252` | C2 | July and August builds |
| `47[.]238[.]108[.]53:5353` | C2 | Statement of Account image, August |
| `47[.]243[.]155[.]133:5353` | C2 | August numeric ZIP and encrypted 7z |
| `8[.]215[.]17[.]221:5252` | C2 | August and September builds |
| `47[.]243[.]231[.]74:5252` | C2 | October build |
| `47[.]243[.]36[.]18:5252` | C2 | July builds |
| `47[.]75[.]103[.]130:5252` | C2 | July builds |
| `47[.]86[.]111[.]44:5252` | C2 | July builds |
| `206[.]238[.]196[.]96:5252` | C2 | July build |
| `a[.]qqmusic1[.]com`, `c[.]360ctct[.]com`, `b[.]360ctct[.]com`, `360nn3[.]icu` | C2 domains | June builds, port 443 |
| `hxxps://shougong9[.]com/hm.txt` | Fallback URL | Builds from 4 August 2026 |
| `hxxps://appfenxiang[.]com/hm.txt` | Fallback URL | April and June builds |
| `hxxps://appfenxiang[.]com/hm3601.txt` to `hm3605.txt`, `hm007.txt` | Fallback URLs | July builds |
| `47[.]76[.]110[.]255` | Fallback host | Hosts `shougong9[.]com` and `appfenxiang[.]com` |
| `notice8[.]oss-ap-southeast-1[.]aliyuncs[.]com` | Delivery | October tax ISO |
| `material-checklist[.]oss-ap-southeast-5[.]aliyuncs[.]com` | Delivery | ITR image and October tax ISOs |
| `xcxc-prod[.]oss-ap-southeast-5[.]aliyuncs[.]com` | Delivery | Statement of Account images |
| `in0810[.]oss-me-east-1[.]aliyuncs[.]com` | Delivery | Statement of Account image |
| `hxxps://jackhm[.]oss-cn-hongkong[.]aliyuncs[.]com/a86.dat` | Delivery | May 2026 login module |
| `116[.]213[.]43[.]154:8383` | Management server | ManageEngine agent bundle in `material-checklist` |

### File hashes (SHA-256)

| Indicator | Type | Context |
| - | - | - |
| `832034bf8ace35b74d62eb0b114134778a128cfb1b8af1f2ec67310f01ff4175` | ISO | `New Tax Filing Regulations.iso` |
| `8f3319b85bcec0ba8cf8fe298df998b32085f197d2546e97590ba37ae747252e` | ISO | `Filing Regulations.iso` |
| `d3dcd281a7ac696dff3ef8c06d643e9e406c62768a17d446adaf6069bac53a2b` | ISO | `Fiscal Penalty List.iso` |
| `7c673432fc3be09911f2df29946ffa1a31f4974a3176706e6f343f5fc8325139` | ISO | `Tax-Investigation.iso` |
| `07e4f2cd42c756cb231db4b7999a501f900fd5487dc1228bac7869a3e44ecac5` | ISO | `Tax-Penalty-List.iso` |
| `0ad4491d3d1d6706344137755b192e24fe0ab4673b472f0f97ba3581cf09a9a8` | IMG | `ITR_0ca1-2.img` |
| `1b89fbcd8fdf994ca32c48889ba617919ee16443692b1cfc7a2b8f3f5518a2c9` | ISO | `Open_to_view_0a7a.iso` |
| `a150614db8802e3700db945c42f7e9c2fb03cfdcbea7854b0b072a2e35a11b77` | EXE | Signed VSPerf profiler; legitimate Microsoft file, malicious in this context |
| `008c571e964f6ca718f5ae483c71ca5c19d9251821156e3f8910af395c6c10f8` | DLL | `VSPMsg.dll` from the October ISO |
| `bb0381fde9b3ba403b83d86396f8ba4055391602fee381e12f8800bf09fc7559` | DLL | First RAT login module (memory only) |
| `d5ff20329ab91310145ea46e3c6e4499ad85170c57b3d2233d258585e0cecd0f` | DLL | Installer pushed by the C2 |
| `783f2f5bbe5d9c8278d09332d97245b950199550a86f2536f2b8b35f580bb610` | DLL | Second `VSPMsg.dll` template (dropped copies differ per install) |
| `c728b54b4d4db18f2b0fa3426f12bd9006b9f8d7d58cc5c87726a360da2cc6bc` | Payload | October `config.log` |
| `99d414576e95e9fb7c07bd3a1065c4a54476f1f05076e46c750bb6459fed02fd` | DLL | Second RAT login module (memory only) |
| `23c8cf3e6a62ada2c5d5e52781410b44a1e383625430069da95cbc1720010818` | Payload | August `config.log` for `47.75.119.86:5353` |
| `dcedb43256f4bc7aef6fc8f4fa4c82cd3e51ef996f0f75fa1c4493b8368c7ecb` | Payload | `a86.dat` / `a.png`, May 2026 |
| `b3a2e3df2eb6ec08460dc7a1bc2967c4270b3fc9b45f474285d894c66f5838cb` | DLL | `Plg7D88.tmp` driver installer plugin |
| `8b898b0d1ab4fbf2f7e2c1c50078309dcbcd150ac86e3a49772f6e2924a65336` | DLL | `Plg45BE.tmp` driver installer plugin |
| `b8de157d2ccc5208643470c97e319030581121c51e4d48876cc25b8fbd0adb5a` | Driver | `k32.sys` |
| `52e061b0a78b472b6b9e636c89df289e8424ec80c17d8288ac9d52f3b37f8e2f` | DLL | `Plg44A5.tmp` webview plugin, July |
| `461ce96f338fbe193a47805285e361ff0798fbc849c84ff6cf5ec56ff4fdb9bc` | DLL | `Plg776D.tmp` webview plugin, August |
| `955672334641d7409c4cd3966f7a169dc8a5fe03334032ed6799f95ba7045de3` | ZIP | `file.zip` ManageEngine agent bundle from `material-checklist` |

### Host artifacts

| Indicator | Type | Context |
| - | - | - |
| `C:\ProgramData\EdgeUpdate\<8 random a-z0-9>\` | Directory | Hidden and system attributes; holds the EXE, `VSPMsg.dll` and `config.log` |
| `C:\ProgramData\EdgeUpdate\<8>\<8>.exe` | File | Copy of the signed VSPerf profiler |
| `C:\ProgramData\EdgeUpdate\<8>\VSPMsg.dll` | File | 106,954,752 bytes |
| `C:\ProgramData\EdgeUpdate\<8>\config.log` | File | Executable payload, begins `E9 43 04 00 00` |
| `C:\ProgramData\EdgeUpdate\<8>\webview_support.dll` | File | July and August plugin bundle |
| `\MicrosoftEdgeUpdate\Update` | Scheduled task | Logon trigger, highest run level, author “Microsoft Corporation” |
| `HKCU\Software\Microsoft\Windows\CurrentVersion\Run\MicrosoftUpdate` | Registry | Non-administrator persistence, October |
| `HKCU\Software\Microsoft\Hello\Hello` | Registry | C2 override pushed by the server |
| `HKCU\key\open` | Registry | Keylogger switch |
| `HKLM\SOFTWARE\IpDates` | Registry | RAT shellcode staged for `k32.sys` |
| `C:\Windows\System32\drivers\k32.sys`, service `k32_service` | Driver | Kernel driver from the July plugins |
| `%ProgramData%\Microsoft\DeviceSync\DisplaySessionContainers.log` | File | Keystroke and clipboard log, first RAT |
| `%LocalAppData%\DisplaySessionContainers.log` | File | Keystroke and clipboard log, second RAT |
| `Global\6xiYoNBnFmYi` | Mutex | First loader |
| Defender exclusions for `C:\ProgramData\EdgeUpdate` and the processes `explorer.exe`, `Thunder.exe`, `RuntimeBroker.exe`, `VSPMsg.dll` | Defender settings | Installer, administrator branch |
| `3f7ac1852d9e46b071f308ad5ce92467b81a934fd2607ec538a9158b4cd702f6` | Transport key | Shared HMAC key in June to October builds |

## MITRE ATT\&CK mapping

| Tactic | Technique | Evidence |
| - | - | - |
| Execution | T1204.002 User Execution: Malicious File | Victim opens the program in the tax ISO |
| Defense Evasion | T1553.005 Subvert Trust Controls: Mark-of-the-Web Bypass | Payload delivered inside ISO and IMG containers |
| Defense Evasion, Persistence | T1574.001 Hijack Execution Flow: DLL | Signed VSPerf loads `VSPMsg.dll` from its own folder |
| Defense Evasion | T1027.001 Obfuscated Files or Information: Binary Padding | Loader padded to 102 MiB |
| Defense Evasion | T1140 Deobfuscate/Decode Files or Information | Four-to-three decoder, modified XTEA, XOR and LZ4 |
| Defense Evasion | T1497.001 Virtualization/Sandbox Evasion: System Checks | VMware and VirtualBox checks |
| Defense Evasion | T1055.004 Process Injection: Asynchronous Procedure Call | Section, `NtTestAlert` thread and APC into Explorer |
| Defense Evasion | T1620 Reflective Code Loading | Reflective stub and manual mapper for plugins |
| Defense Evasion | T1036.005 Masquerading: Match Legitimate Name or Location | `EdgeUpdate`, `MicrosoftUpdate`, `\MicrosoftEdgeUpdate\Update` |
| Defense Evasion | T1564.001 Hide Artifacts: Hidden Files and Directories | Hidden and system attributes on the bundle |
| Defense Evasion | T1562.001 Impair Defenses: Disable or Modify Tools | Defender exclusions; `k32.sys` Defender policy and callback changes |
| Defense Evasion | T1562.004 Impair Defenses: Disable or Modify System Firewall | Deletes firewall block rules that match the C2 |
| Defense Evasion | T1070.001 Indicator Removal: Clear Windows Event Logs | Command `0x0c` |
| Persistence | T1053.005 Scheduled Task/Job: Scheduled Task | `\MicrosoftEdgeUpdate\Update` logon task |
| Persistence | T1547.001 Boot or Logon Autostart Execution: Registry Run Keys | `MicrosoftUpdate` Run value |
| Persistence | T1543.003 Create or Modify System Process: Windows Service | `k32_service` |
| Execution | T1059.001 Command and Scripting Interpreter: PowerShell | `Add-MpPreference` commands |
| Discovery | T1217 Browser Information Discovery | `.bank.in` and payment-service history checks, wallet extensions |
| Discovery | T1518.001 Software Discovery: Security Software Discovery | Security product process list |
| Collection | T1056.001 Input Capture: Keylogging | DirectInput keylogger |
| Collection | T1115 Clipboard Data | Clipboard polling every 1.5 seconds |
| Collection | T1113 Screen Capture | Commands `0x04`, `0x05`, `0x0b` |
| Command and Control | T1095 Non-Application Layer Protocol | Custom TCP and UDP record protocol |
| Command and Control | T1573.001 Encrypted Channel: Symmetric Cryptography | AES-CBC with HMAC-derived session keys |
| Command and Control | T1008 Fallback Channels | `hm.txt` files supply a new `host:port` |
| Command and Control | T1105 Ingress Tool Transfer | Server-pushed installer and plugins |

## Bare IP connections fail under DTTS

Every initial client we recovered since July sends its primary C2 connection to a bare IP address. One dropped `config.log` from August names `cicfo[.]com`, a domain that has since expired. The client opens a TCP connection to `8.210.231.207:9090` or `47.75.119.86:5353` without making a DNS request first. Only the fallback path uses a domain name, through `shougong9[.]com`, registered on 22 July 2026.

ADAMnetworks’ [adam:ONE](https://adamnet.works/how-it-works.md) applies Don’t Talk To Strangers (DTTS), which denies IP connections by default unless the destination was first requested through DNS and allowed by policy. The RAT’s first connection to its server has no DNS request behind it, so DTTS denies it. The fallback domain `shougong9[.]com` and June domains such as `360nn3[.]icu` are unknown domains, which adam:ONE denies by default. With both paths closed, the first RAT never receives the installer and none of the later stages run: no EdgeUpdate bundle, no `config.log`, no second RAT.

![Kirk Bio Picture](https://adamnet.works/uploads/pasted-image-1791906333143.webp)

About the author

## Kirk | ADAMnetworks

Security Researcher

Kirk is a security researcher known for reverse engineering of ransomware, malware and web threats.

[Author profile](https://www.linkedin.com/in/matt-kirkland/)

## Related reading

Security Research

### [KeyStealth: Device code phishing to rogue Entra devices and BEC](https://adamnet.works/blog/keystealth-device-code-phishing-to-rogue-entra-devices-and-bec.md)

October 22, 2026

Security Research

### [A ClickFix loader rewritten to get past a rival's page cleaner](https://adamnet.works/blog/a-clickfix-loader-rewritten-to-get-past-a-rival-s-page-cleaner.md)

October 13, 2026

Case Study

### [Rapid Incident Response and Business Recovery by ADAMnetworks](https://adamnet.works/case-studies/rapid-incident-response-and-business-recovery-by-adamnetworks.md)

November 3, 2026

## See it on your own network

Zero Trust Connectivity reduces attack surface 7000:1 by denying egress by default. Talk to us about what that looks like in your environment.

[Request a Demo](https://adamnet.works/contact.md) [How adam:ONE® Works](https://adamnet.works/how-it-works.md)
