All blog posts
Security ResearchValleyRAT

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•
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.

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. Zscaler’s 2024 analysis credits QiAnXin with first identifying it and tying it to the group known as Silver Fox. Check Point’s study of the ValleyRAT builder 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, India from CloudSEK, Japan from ESET, and 2026 campaigns from Kaspersky and Forcepoint.

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.

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.

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.

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:

|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. 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.

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.

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).

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.

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.

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.

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.

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 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 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

About the author

Kirk | ADAMnetworks

Security Researcher

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

Author profile

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.