Abstract
Key takeaways
- SectopRat stealer loader chain
- Uses a proprietary virtual machine
- Uses the GPU and D3D11 shaders to decrypt itself
- Targets IT and cryptocurrency software
- Resolves its C2 through EtherHiding (BSC smart contracts)
- Likely related to GPUGate
- Two other tools, probably AI-generated were identified
- One of the operators most likely made an operational-security mistake
We identified a crimeware-style compromise chain whose distinctive feature is that it decrypts itself using D3D11 shaders executed on the GPU. The chain has two stages built around two different loaders, relying on a proprietary virtual machine, GPU-based decryption, and C2 retrieval from smart contracts on the Binance Smart Chain (BSC). It finally executes in memory the SectopRat stealer, previously described by Fortinet.
This compromise chain was also covered in July by Huntress. We provide some additional details here, but we will not cover the malvertising campaign itself.
We detail here the two loaders, which we named VMLoader and GPULoader respectively. They run a SectopRat payload that also relies on BSC smart contracts to obtain its C2.
We also briefly describe an optional FakeGuard payload performing an AitM attack against the banking sector, masquerading as an application for blocking unwanted websites.
We then investigate the chain of smart contracts used to configure the SectopRat samples, which leads to what appears to be an operational-security mistake by the operator, potentially exposing their identity.
Finally, we compare these findings with the GPUGate article published by Arctic Wolf.
Overview
The initial infection happens through the download of a ZIP archive posing as a legitimate installer, such as 197b6c51 (ClaudeDesktop.zip). The archive contains a legitimate jcef_helper.exe (Java Chromium Embeded Framework) binary (renamed, for instance, to DockerDesktop.exe, Chrome.exe, ClaudeDesktop.exe) and a libcef.dll DLL).
The libcef.dll binary (which we call VMLoader) performs a system check — in particular inspecting the installed GPU (blacklisted vendors, required VRAM, etc.) — decrypts a resource holding 15 bytecodes ran by a custom virtual machine, and finally reads a BSC contract to obtain a URL from which a .zip file is downloaded. Every executable contained in that archive is then run.
The downloaded ZIP file usually contains the following files:
sslconf.exe: legitimate, signed executabletempdir.dll: the GPULoader malware, which loads and runs an encrypted companion file- companion file (for example
licence.dat): the encrypted SectopRat payload loaded by GPULoader - (optional)
siteguard.exe: the FakeGuard malware, performing AitM attacks on banking-site browsing - (optional)
vcruntime140.dll: dependency
The GPULoader malware has the distinctive feature of decrypting its companion file by having the decryption carried out by the GPU, and it uses the same proprietary virtual machine. The final payload is a SectopRat malware, which also uses a BSC control channel — different from the one used by libcef.dll. In some cases, a FakeGuard malware is also present.
VMLoader
The malware masquerades as libcef.dll, the Chromium Embedded Framework (CEF) library, used by many desktop applications to render web pages. It exports the 216 CEF API functions and a fake version info, but none of these functions are actually implemented.
The malware first performs a GPU check by enumerating graphics adapters via CreateDXGIFactory, and rejects:
- software adapters (CPU-based software emulation)
- less than 256 MB of dedicated VRAM and less than 1 GB of shared VRAM
- an adapter description name shorter than 12 characters
- vendor IDs
0x1414(Microsoft Basic Render),0x1234(QEMU),0x15AD(VMware) - the inability to create a Direct3D 11 device via
D3D11CreateDevice
If these checks pass, the code proceeds to load an encrypted resource and decrypt it. Two modes exist depending on the loader version:
- Version 1 6b8ecc21:
XORwith a 32-byte key, no derivation - Version 2 6ccd6b67:
AES-256-CTRusing theBCryptAPI
Note: the version-1 loader (XOR) can also load a companion file when the resource is not embedded in the binary.
Once decrypted, the resource holds 15 subprograms compiled for an in-house virtual machine. Each decrypted blob carries a "VMP1" magic number in its header. The opcodes and blocks are similar across all observed versions. The virtual machine is relatively simple and essentially calls an opcode dispatcher for each element read; the operations stay fairly simple (push, pop, add, sub, xor, opr, shl, shr, reads, writes, etc.), with the exception of opcodes 0x61-0x64, which provide FNV-1A-hash-based API resolution for kernel32.dll or ntdll.dll and direct calls to them.
The full VM instruction set has not been completely analyzed; however, most of the instructions were disassembled, and we were able to infer the following behaviors for the 15 modules:
| Module # | Role |
|---|---|
| 1 | Microsoft Defender emulator detection (Mp and VFS_ functions) |
| 2 | RWX memory protection |
| 3 | ntdll.dll remapping |
| 4 | Memory patching, potentially EDR unhooking |
| 5 | Anti-debug by clearing the hardware debug registers DR0-DR7 |
| 6 | Privilege-elevation check (token) |
| 7 | Privilege elevation via runas |
| 8 | Windows Defender exclusion via powershell -NoProfile -Command Add-MpPreference -ExclusionPath 'C:\Users' |
| 9 | Queries the BSC contract and decrypts the URL with the XOR key deadbeefcafebabe13374269 |
| 10 | Downloads the stage-2 archive as update.bin |
| 11 | Self-install: copies the malware and its executable onto the system |
| 12 | Self-install: Run-key persistence |
| 13 | Self-install: scheduled-task persistence via the schtasks.exe command |
| 14 | Extracts the archive and runs the contained .exe files |
| 15 | Downloads and runs the legitimate installer |
Module #15 downloads and runs the legitimate installer based on the current process name. It supports, for example, googlechrome.exe, claudedesktop.exe and exodus.exe. However, it can also handle Сhrоme.exe, where the C and o characters are their Cyrillic homoglyphs. This may be intended to bypass detection rules that would flag malformed chrome.exe executables (unsigned, in a non-standard folder, inside a ZIP archive, etc.).
Self-installation happens in a %APPDATA%\EdgeUpdate-<8hex>\{DockerDesktop.exe, libcef.dll, update.bin} folder, where <8hex> is an 8-hex-character suffix regenerated per build.
The binaries carry a fake VERSIONINFO publisher drawn from the following set:
Bridge Libraries Group (brlib 4.17.966.64)Foundation Libraries Project (foundlib 1.3.205.55)Native Bindings Project (nbind 4.17.162.43)Embedded Helpers Foundation (emhelp 1.18.932.55)OpenSource Toolkit Contributors (rtlib 2.8.116.3)WinFramework Helpers (apsrt 4.8.89.23)Adaptive Runtime LLC (adaptrt 2.18.446.88)
We were able to identify the following mutexes:
Global\DefenderHydrationGateGlobal\OneDriveStandaloneCacheGlobal\MicrosoftEdgeRolloutSyncGlobal\TaskHostSchedulerGateGlobal\WindowsTelemetryDataAcq
And the following Run persistence keys:
DefenderTelemetryServiceMicrosoftEdgeUpdateTaskMachineTaskSchedulerHelperSvcWindowsConfigurationServiceWindowsTempCleanupSvcOneDriveStandaloneUpdater
All of these therefore appear to be generated periodically.
The smart contracts are read from bsc-dataseed.binance.org via an eth_call request for contract 0xc190. The response is XORed with the string deadbeefcafebabe13374269. The value has been updated 6 times:
| Date (UTC) | Decoded value |
|---|---|
| 2026-05-28 11:36 | https[:]//legsotier.us/{zip.php,app.exe,dll.php} |
| 2026-05-28 12:08 | https[:]//neeitoerw.my/{zip.php,app.exe,dll.php} |
| 2026-09-19 17:09 | https[:]//apisue.click/{zip.php,app.exe,dll.php} |
| 2026-10-13 11:01 | https[:]//zippis.xyz/{zip.php,app.exe,dll.php} |
| 2026-10-19 11:11 | https[:]//faceitzip.xyz/{zip.php,app.exe,dll.php} |
| 2026-10-23 09:01 | https[:]//arzipi.xyz/{zip.php,app.exe,dll.php} |
Contract 0xc190 was created on 2026-05-28 11:36:38 by 0x3695. This wallet is funded solely by the 0x8C82 common gas hub.
SteamLoader
VMLoader is not the only malware using this smart contract. In fact we found another malware, 40846f40 which uses the same contract and that does the same thing. However, in this case, this is a quite simple .NET malware with no obfuscation whatsoever, and it is a standalone .exe unsigned file. In fact the smart contract 0xc190 is in clear text, and the functions have quite speaking prefixes, such as "Res" (EtherHiding resolve), "Get" (download), "Dec" (Decoy) or "Stm" (Steam).
The logic is quite simple:
- the malware will store its resources in the
AppData\Roaming\Cache-XXXXfolder, where XXXX is derivated from the machine name - if the malware runs in SYSTEM Integrity Level, it will add a Windows Defender exclusion over the
C:\Usersfolder, install the last.exefound in the folderAppData\Roaming\LocalCache\as a Scheduled Task (nameCacheMaintenanceTask), and run it. It will also create run the process on the user session withNtCreateToken/CreateProcessAsUser - if the malware runs in HIGH Integrity Level, it will create a Mutex (
Global\WinCacheSyncE), create the same task, add the same exclusion, resolve the smart contract C2 address, download the pointed file, and depending of the extension, it will run it. The.dllextension is not supported, the.exeis simply executed, otherwise it is handled as aZIParchive withtar.exein axfolder, then any.exefile is executed (cmd /c for /r \<PATH>" %f in (*.exe) do @start "" /d "%~dpf" "%~f") - if the malware is not elevated, it will run its decoy (download and execute the associated installer depending on its own process name) and, if the Mutex is not set, try to elevate itself. First with the Steam technique, otherwise with a simple
runascommand which will prompt the UAC
The Steam functions is quite interresting, as it will abuse the SteamClientService to trigger an execution of an executable having the same name in the LocalCache folder. It uses an existing, Valve-signed, InstallScript: Wallpaper Engine (appid 431960), which basically comports:
"InstallScript"
{
"Run Process On Uninstall"
{
"Process_name"
{
"process 1" "%INSTALLDIR%\\launcher.exe"
"command 1" "-uninstall"
}
}
"Run Process"
{
"Fix Windows Network Media Throttle"
{
"HasRunKey" "HKLM\Software\Valve\Steam\Apps\431960\disableNetworkThrottle"
"process 1" "%INSTALLDIR%\launcher.exe"
"command 1" "-disablenetworkthrottle"
"NoCleanUp" "1"
}
}
"Firewall"
{
"Wallpaper Engine UI" "%INSTALLDIR%\\bin\\wallpaperui.exe"
}
}
"kvsignatures" { "InstallScript" "7a2dfd7…" }
Then it makes the %INSTALLDIR% pointing in its own folder, and call the SteamService with its SharedMemory IPC using Global\SteamClientService_SharedMemFile. This will trigger Steam to execute the launcher.exe (itself) with SYSTEM privileges. If Steam is not running, it will try to start the process.
However, an interresting check is made before the Steam technique is tried:
The malware aborts this technique if a specific dll/companion file are not found in the LocalCache folder : it checks for a libcef.dll file, what looks like to be a companion .dat file, and a .exe having the same name the SteamLoader has. Thus, this file is either the SteamLoader malware itself or a file with the same name in the LocalCache folder. All of these files will be copied in a temporary folder, then installed and executed. However, the malware does not import/load any libcef.dll.
This does not make a lot of sense:
- the malware is crafted to have the same behaviour the VMLoader has, without any obfuscation, which undermines completely the efforts put into the VMLoader development
- it uses two different folders, the
LocalCacheand theCache-XXXX, but nothing is ever copied in theLocalCachefolder - it installs persistence for an undefined
LocalCache.exe file, but nothing is ever copied in this folder by the malware - the only files to be written in the
Cache-XXXXare the.binfile or.exefile fetched from the C2, however the.exefile is immediately ran with a simpleProcess.Startcall. This executable will be written under theu.exename, different of the malware's name. Thus it cannot be considered by theSteamroutine - the
Steamroutine does not execute if the DLL file and its companion are not found. But it defaults on the malware itself which does not import this DLL - the
Steamroutine expects a file that looks like to be a GPULoader or VMLoader payload. However, the download routine is called only if the process runs in a High IL mode, skipping this routine. Moreoever, the GPULoader payload is downloaded in axsubfolder, thus it cannot be located in this folder. We don't know what is expected there - the GPULoader final payload is fetched in a zip archive, where the executable name might change, thus the whole Steam routine which expects a same executable name would not be correct
- on the HighIL routine, the ScheduledTask routines run before the remote payload is fetched, therefore the folder will be empty
- both the System and HighIL routines do the same thing, as they both create the same scheduled task with the same parameters. However the System does not fetch the remote payload
Consequently, for the Steam routine to be executed it would require another installation step beforehands, which would place other files in the LocalCache and Cache-XXXX folders. Nothing in the data we observed suggest this, and it would be quite illogic, as the stage1's purpose, as its decoy routine suggest, is to download and execute a payload in the most minimal possible way in order to avoid detection.
Therefore it results in a quite simple behaviour : an attempt of gaining HIGH IL privileges with a runas command, then a simple download/execute stream of a ZIP file using the EtherHiding host resolution.
FakeGuard
A binary named "SiteGuard" a7b829a5 is also present in most archives. We named it "FakeGuard" as it is a PyInstaller executable whose purpose is to carry out an AitM attack and code injection. To do so, it will:
- generate a
PC Site Guard Local CACA and install it (PowerShell script) - install a system proxy via PAC (PowerShell script)
- intercept and inject a JavaScript script into certain HTML pages
- install a malicious Chrome MV3 extension
Site Guard · Режим родителя("parent mode") with proxy permission and access tohttps[:]//45.59.122.85/*only, allowing it to force the proxy installation - block access to certain sites
- install Run-key persistence
This server allows executing commands on the infected system through basic cmd /c commands.
The C2 server is hardcoded: 45.59.122.85 but FakeGuard also uses the same EtherHiding mechanism to find these servers, polling the 0xc6a3 contract funded by 0x3695 (same wallet than the VMLoader one).
This contract holds cleartext values:
| Date (UTC) | Value |
|---|---|
| 2026-10-13 14:13 | https[:]//167.88.172.111 |
| 2026-10-13 21:37 | https[:]//153.92.223.113 |
| 2026-10-22 08:55 | https[:]//72.60.20.149 |
| 2026-10-22 14:21 | https[:]//191.96.1.36 |
| 2026-10-23 15:45 | https[:]//72.60.20.149 |
The Python scripts carry Russian docstrings indicating the role of the JavaScript scripts fetched from the server:
- passive sniffing of account balances (tied to the
schwab_sidcookie and theschwab.combank) - cookie theft for session replay
- substitution of beneficiary IBAN/BTC/ETH/etc. during banking operations
Which can be translated as:
Intercept mode: full MITM of selected hosts with rewriting and reporting.
Domains from lab.json ("intercept") get the real site content with /__lab/inject.js injected instead of a block page; control and capture traffic (/__lab/*) goes to our panel. CA — the default SiteGuard (already trusted).
lab.json next to the client's data-dir:
Given the number of comments and their structure, this code may have been generated by an LLM in Russian.
This binary can also run basic remote commands (beaconing on the /api/device/commands endpoint, which can trigger execution via a call to cmd.exe /c). In the version studied, only schwab.com is targeted by the default configuration. However, the binary also fetches a remote configuration, and one of these — served from https[:]//45.59.122.85/routing/ — was recovered. It is much broader:
{"enabled":true,"domains":["akamaiedge.net","ally.com","americanexpress.com","avast.com","avcdn.net","bankofamerica.com","binance.com","bingx.com","bitdefender.com","bitfinex.com","bitget.com","bitmart.com","bitstamp.net","blob.core.windows.net","blockchain.com","broadcom.com","bybit.com","capitalone.com","cex.io","chase.com","checkappexec.microsoft.com","chime.com","citi.com","coinbase.com","core.windows.net","crl.microsoft.com","crypto.com","ctldl.windowsupdate.com","cwfservice.net","data.microsoft.com","definitionupdates.microsoft.com","delivery.mp.microsoft.com","discover.com","download.microsoft.com","download.windowsupdate.com","ecs.office.com","endpoint.security.microsoft.com","eset.com","events.data.microsoft.com","fe3cr.delivery.mp.microsoft.com","fidelity.com","gate.io","gemini.com","github.com","go.microsoft.com","htx.com","intuit.com","kaspersky-labs.com","kaspersky.com","kraken.com","kucoin.com","lbank.info","malwarebytes.com","mb-cosmos.com","mb-internal.com","mexc.com","mp.microsoft.com","mwbsys.com","navyfederal.org","norton.com","okx.com","paypal.com","pnc.com","poloniex.com","robinhood.com","schwab.com","settings-win.data.microsoft.com","siteguard.test","smartscreen-prod.microsoft.com","smartscreen.microsoft.com","sofi.com","symantec.com","symantecliveupdate.com","td.com","truist.com","update.microsoft.com","uphold.com","urs.microsoft.com","usaa.com","usbank.com","virustotal.com","vortex-win.data.microsoft.com","wd.microsoft.com","wdcp.microsoft.com","wdcpalt.microsoft.com","wellsfargo.com","windows.net","windowsupdate.com","wise.com"],"include_subdomains":true,"proxy":"PROXY 127.0.0.1:8877"};
A more recent one has the following values:
{"targets":[{"host":"ally.com"},{"host":"americanexpress.com"},{"host":"bankofamerica.com"},{"host":"binance.com"},{"host":"bingx.com"},{"host":"bitfinex.com"},{"host":"bitget.com"},{"host":"bitmart.com"},{"host":"bitstamp.net"},{"host":"blockchain.com"},{"host":"bybit.com"},{"host":"capitalone.com"},{"host":"cex.io"},{"host":"chase.com"},{"host":"chime.com"},{"host":"citi.com"},{"host":"coinbase.com"},{"host":"crypto.com"},{"host":"discover.com"},{"host":"fidelity.com"},{"host":"gate.io"},{"host":"gemini.com"},{"host":"github.com","quiet":true},{"host":"htx.com"},{"host":"intuit.com"},{"host":"kraken.com"},{"host":"kucoin.com"},{"host":"lbank.info"},{"host":"mexc.com"},{"host":"navyfederal.org"},{"host":"okx.com"},{"host":"paypal.com","watch":true},{"host":"pnc.com"},{"host":"poloniex.com"},{"host":"robinhood.com"},{"host":"schwab.com"},{"host":"sofi.com"},{"host":"td.com"},{"host":"truist.com"},{"host":"uphold.com"},{"host":"usaa.com"},{"host":"usbank.com"},{"host":"wellsfargo.com"},{"host":"wise.com"},{"host":"drive.google.com","quiet":true},{"host":"photos.google.com","quiet":true},{"host":"docs.google.com","quiet":true},{"host":"myaccount.google.com","quiet":true},{"host":"accounts.google.com"},{"host":"clients6.google.com","quiet":true},{"host":"etrade.com"}],"catchall":false,"exclusions":[],"swap":{},"gateCodes":false,"quietHosts":["github.com","drive.google.com","photos.google.com","docs.google.com","myaccount.google.com","clients6.google.com"],"watchHosts":["paypal.com"]}
The domains listed here mix two different functional groups: interception targets (banking and cryptocurrency) and blocking/tampering targets (system and antivirus updates).
The intercept.py docstrings mention 216.126.227.160 as a C2 server. This IP address could not be found in the smart contracts addresses nor in hardcoded values. It does not belong to the other C2s subnets.
Back in October, this website hosted a schwab.com phishing page, also LLM-generated, with an interesting comment:
Unfortunately, the website has been down since then, so we could not test the backend panel link displayed in the comment. In any case, this example shows that the propention of LLMs to put comments everywhere can lead to quite big opsec fails.
GPULoader
The binary masquerades as tempdir.dll, a utility component of IBM SPSS Statistics. It is loaded via sideloading by a legitimate IBM executable (sslconf.exe).
When loaded, it first runs the same checks as VMLoader, namely:
- rejection of vendor IDs
0x1414(Microsoft Basic Render),0x15AD(VMware),0x1234(QEMU); - rejection of software adapters (
DXGI_ADAPTER_FLAG_SOFTWAREflag); - at least 256 MB of dedicated VRAM or 1 GB of shared VRAM;
- a card description longer than 11 characters.
Additional checks are also present:
- a blacklist of
FNV-1ahashes of graphics-card descriptions; - creation of a
D3D11device, then 16 operations executed with a performance measurement viaQueryPerformanceCounter: if the measurement exceeds 30 ms, the check fails.
It then proceeds to read the companion file. The following files were identified:
license.datcwise.datspssaux.datuistate.binappcfg.datclientdat.binmodules.datsslconfig.datsettings.bin
The companion file size is hard-coded in the GPULoader binary, and a check is performed to make sure it is correct.
The malware then performs the decryption:
- it uses the created D3D11 device to create GPU resources (decryption key, nonce, mask, size, input buffer, output buffer) via
CreateBuffer,CreateShaderResourceView,CreateUnorderedAccessView - it creates a compute shader from a
DXBCblob embedded in the DLL viaCreateComputeShader - it maps the resources into the shader via
CopyResource,CSSetShaderResources,CSSetUnorderedAccessViews,CSSetShader,CSSetConstantBuffers - it calls the shader's
Dispatchmethod - it securely wipes the keys and shaders from memory
The shader is a compute shader implementing a standard AES-256-CTR algorithm, with a modification of the MixColumns matrix (3,1,1,3 instead of 3,1,1,2 on the 4th row). A key derivation is performed via an XOR with the mask parameter.
The decrypted payload carries a magic number 0xE85A8827 followed by a header defining several sections. This magic number changes between samples and therefore appears to be generated at build time for each version. There are 10 sections, each carrying a type.
| Type | Size | Content |
|---|---|---|
| A | 0x21D | VM bytecode: AMSI bypass |
| B, D, E, F, G, I | 8 each | 0xC3 followed by 7 bytes, unknown role |
| C | 0xDC | VM bytecode: .NET bootstrap |
| H | 0x432 | VM bytecode: Run persistence |
| P | 0x66E00 | PE32+ .NET |
The code runs the VM bytecodes A and C:
- bytecode A is an AMSI bypass that hooks
AmsiScanBufferby creating aVectoredExceptionHandlerand setting a hardware breakpoint on that function. - bytecode C is a .NET bootstrap that executes the .NET PE in memory. It uses
mscoree.dll.CorBindToRuntimeto instantiate the CLR v4.0.30319. The data is copied into aSAFEARRAY, then anAssembly.Loadis performed, and the EntryPoint is finally called. This is a SectopRat binary.
This is the same VMP1 bytecode as in VMLoader.
Finally, a thread is created to install the malware:
- it copies the 3 files (sslconf, tempdir and the companion file) into the
\AppData\Roaming\Cisco AnyConnect Secure Mobility Client\Profilefolder - it creates a scheduled task via the Task Scheduler COM API (
ITaskService) namedMicrosoftCompatibilityAppraiser - it runs bytecode
H, which installs aTaskSchedulerHelperSvcRun key
The Run keys vary between samples:
TaskSchedulerHelperSvcWindowsConfigurationServiceDeviceCensusBackupWlanExtensibilityProviderUserNotificationListenerAppReadinessTrigger
The tasks also change, but are all located at the root:
MicrosoftCompatibilityAppraiserAppxManifestRecoveryServiceWindowsActivationTechnologyMicrosoftSearchIndexerHelperDiagnosticsHubStandardCollectorWatcherWerSvcRollbackTaskWindowsDefenderTaskExcludeBackgroundTaskInfrastructureHelper
GPULoader standalone
Using ExaLyze, we were able to determine that 10 functions are shared between GPULoader and the binary 925ad6253e84a28e0e2538b7492a991b0224a88f334f586880ade9ef6bbc59f2. These are notably functions used to load .NET payloads.
This is another version of GPULoader that does not load a companion file but embeds it directly.
SectopRat/ArechClient2 payload
The payload is a SectopRat sample similar to the one documented by Fortinet in the article https://www.fortinet.com/blog/threat-research/uncovering-a-sectoprat-variant-embedded-in-legitimate-software . Among other things, it enables:
- Browser data theft: Chromium (Login Data, Web Data, cookies,
app_bound_encrypted_key, payment cards) and Gecko (cookies.sqlite,logins), as well as Battle.net, Steam (ssfn), FileZilla, Discord, Telegram (tdata) and Opera GX. - Wallets and VPNs: about thirty wallet extensions (
Metamask,Coinbase,Binance,Ronin,TronLink),NordVPN,OpenVPNandProton. - Profiling: WMI (
SecurityCenter2,Win32_Processor,VideoController,PhysicalMemory,DiskDrive,Process). - RAT: about 35
Receive*commands, includingInitStealer,ShellJoinCommand,FileManager,ProcessManager,CaptureRequest,FullscreenRequest,DeployBrowserKey,GetBrowserKeys,SendCookieFile,RestartBot,RestartPC,UnInstallandLocalPluginInitModule(theRLibmodule). - Hidden desktop and keylogger:
DesktopSwitch,NewKeyLog,ScreenFloatandBigDataToViewermessages. - Self-deletion:
cmd /C choice /C Y /N /D Y /T 6 & Del "…".
Here again the C2 is obtained through the BSC blockchain, via contract 0xe012d0f34cde9b870e9d9ed566ea5f8fd9b92228, created on 2025-05-30 07:30:23 UTC in wallet 0xb57daeb4aa10f6a79e520218ec3c455f58c5fa12. The values are in the format START<base64 of 32 bytes>FINISH, with an AES IV and a block indicating the C2 address. The decrypted history is as follows:
| Date (UTC) | Block | C2 | set tx |
|---|---|---|---|
| 2025-05-30 07:30 | 50564264 | 107.189.24.67 |
0xbee67ef3254b0a03… |
| 2025-07-13 06:16 | 53852731 | 104.194.133.210 |
0x53af31e2137525cf… |
| 2025-07-26 23:07 | 55431008 | 107.189.26.86 |
0x3971623905995eac… |
| 2025-08-11 07:13 | 57197751 | 107.189.21.86 |
0x28fff2e04f81ebbe… |
| 2025-08-22 06:54 | 58463287 | 45.59.124.17 |
0xe7304eea8a8f358b… |
| 2025-09-05 08:08 | 60081583 | 45.59.125.228 |
0xe9df8a8f11e2eaaf… |
| 2025-09-14 19:35 | 61173108 | 45.59.122.82 |
0xce76487c2b82ed42… |
| 2025-09-24 09:27 | 62276165 | 107.189.17.143 |
0x1d49f1ac60244789… |
| 2025-11-23 21:28 | 69242587 | 45.59.122.134 |
0xe7fec73e598b8318… |
| 2025-12-03 12:03 | 70349146 | 45.59.122.235 |
0x3babd13ca56c89a9… |
| 2025-12-09 08:17 | 71022045 | 107.189.22.118 |
0x30f84d5c829574e0… |
| 2025-12-16 12:33 | 71848720 | 107.189.20.32 |
0x2aa22b8832edfbc9… |
| 2025-12-29 06:20 | 73316071 | 107.189.20.95 |
0x9bdf94a2185ad705… |
| 2026-01-10 18:21 | 74755980 | 107.189.24.255 |
0xd260eed320386091… |
| 2026-01-28 11:37 | 77899791 | 45.59.117.145 |
0xf7c4e0109986438a… |
| 2026-03-13 23:12 | 86438425 | 45.59.114.190 |
0x7991788b0612c371… |
| 2026-04-03 21:32 | 90449755 | 45.59.123.122 |
0xe161379051eb0517… |
| 2026-04-14 12:06 | 92483607 | 45.59.117.67 |
0x0eed829a935a19ed… |
| 2026-04-20 11:21 | 93628000 | 195.110.58.222 |
0x790298a88f5c6a46… |
| 2026-05-12 23:35 | 97944022 | 191.101.80.211 |
0xa8fa97fd38349ae9… |
| 2026-06-12 17:09 | 103835922 | 2.24.131.246 |
0x2af54e35c71bd4f2… |
| 2026-07-25 09:58 | 112030502 | 2.24.128.29 |
0x65906fa052ae592c… |
A second contract 0xfdf3acb71c52889e5bb38e77512a7a18d292fe10 published by this wallet can also be found. It likewise holds values in the format START<base64 of 32 bytes>FINISH (an AES-encrypted block for SectopRat), and these are generally published a few minutes after updates to contract 0xe012d0f34cde9b870e9d9ed566ea5f8fd9b92228.
The oldest samples (compiled in May 2026) additionally include a browser-targeting module that modifies preferences and bundles a malicious extension titled "Google Docs" that logs every URL contacted and every "input"-type field change.
Blockchain pivot
Note: for readability, we have truncated wallet, contract and transaction identifiers here, but they can be viewed by clicking on them.
Each set transaction costs money, and wallet 0xb57d was funded by the gas hub 0x2a0d.
That hub has a very distinctive behavior: it only makes very small BNB transfers (0.015 to 0.027 BNB each) to 67 wallets since May 2025, which together published a total of 163 contracts. All of these contracts have identical bytecode, and 161 of them follow the START<base64 of 32 bytes>FINISH structure. Only one of them can be decrypted by the SectopRat payloads we extracted, which suggests the same holds for the other contracts, and that keys are used for other SectopRat campaigns.
The hub 0x2a0d created two test wallets, each holding a single contract:
- 0x5914 created on 2025-05-07, holding
TestBlabla - 0x21f8 created on 2025-05-07, holding
dsfdsfsdfsdfsdfsdfsdfsdf
Pushing the investigation further, the hub 0xa6ab funds 0x2a0d, and we note that:
- the overall provisioning of the gas hubs used is about 1.6 BNB
- the total cost (publication and updates) comes to roughly 0.2 BNB, which represents about 10% of the allocated amounts
- the funding comes mostly from the anonymous
ChangeNOWandFixedFloatproviders, but also from a wallet 0x39a9
Wallet 0x39a9 is particularly interesting:
- it was created on 2022-05-08, and funded by a Binance Hot Wallet
- in 2023 it made a single transaction moving all held funds to an apparently innocuous third-party wallet
- on 2025-04-04 it received funds from ChangeNOW (anonymous) and transferred them to the SectopRat funnel
- on 2025-05-07 it received funds from ChangeNOW (anonymous) and created a valid SectopRat contract
Therefore:
- it was initially funded by the Binance platform
- it issued standard transactions between 2022 and 2023 and was then unused until 2025
- it directly funds the SectopRat funnel
- it created a SectopRat test contract
Note: for the uninitiated, a BSC wallet is provisioned via Hot Wallets. These act as cryptocurrency brokers and deliver funds to a wallet. Some perform KYC (Know Your Customer) and require the person to be identified (ID document, etc.). Others do not, and allow anonymous transactions. ChangeNOW, for instance, applies no KYC policy.
This wallet is particularly interesting because Binance enforces a KYC policy and therefore holds the identity of the person who performed the funding transactions for wallet 0x39a9.
It is therefore possible that this is a personal wallet belonging to the person providing SectopRat instances via EtherHiding, who may have forgotten they had credited it non-anonymously two years earlier, and used it for testing while developing the code.
Note: it is also possible that wallet 0x39a9 was stolen or handed over and then reused by the author. However, the fact that it was not used after the first test does not really fit that scenario, nor does the fact that the currency used to originally create the account and during the initial SectopRat deployment is identical.
The observed deposits (about $1,140) are as follows:
| Amount (USD at the then-current rate) | Date | Platform used | Wallet |
|---|---|---|---|
| 55.55 | 2022-05-08 | Binance | 0x39a9 |
| 109.91 | 2025-04-04 | ChangeNOW | 0x39a9 |
| 28.51 | 2025-05-07 | ChangeNOW | 0x39a9 |
| 251.50 | 2025-04-05 | ChangeNOW | 0xa6AB |
| 500.97 | 2025-05-07 | FixedFloat | 0xa6AB |
| 31.79 | 2026-04-22 | FixedFloat | 0x2a0d |
| 54.49 | 2026-07-13 | FixedFloat | 0x2a0d |
| 107.14 | 2026-08-12 | FixedFloat | 0x2a0d |
Detection
Despite the attacker's efforts, detection is fairly straightforward. First, it is possible to monitor the Ethereum smart contracts created by the identified wallets, then decode the various identified values when they are in cleartext.
Beyond the IOCs, it is also possible to identify:
- a
tempdir.dll / sslconf.exe / companionfile triplet in aCisco AnyConnect Secure Mobility Clientfolder - an
%APPDATA%\EdgeUpdate-folder with a suffix - a
%LOCALAPPDATA%\SiteGuard\folder jcef_helper.exerenamed and outside its JetBrains location- resolution of / traffic to
bsc-dataseed*.binance.orgfrom a host with no crypto context - the local CA
PC Site Guard Local CA - installation of a local proxy on port
8877 - Cyrillic homoglyphs in standard executable names such as
Chrome.exe
Campaign
This VMLoader/GPULoader campaign has been running since April 2026, although the C2s of the SectopRat payloads have been present since May 2025. The identified ZIP archives target installations of the following software:
- Claude Desktop
- Google Chrome
- Exodus
- Docker Desktop
Attribution and links to other campaigns/groups
Crimeware operations like this one usually split across several distinct actors — stealer developer, loader/dropper developer, MaaS broker, operators, money-laundering — which do not necessarily overlap, so we cannot strongly tie every brick together.
That said, several observations point to a single self-contained operation rather than a kit resold to many customers:
- we did not find any other VMLoader/SteamLoader/GPULoader configuration contract
- the FakeGuard C2 hub is pinned in a smart contract deployed by the same wallet that manages the VMLoader/SteamLoader contracts
- across all FakeGuard samples, none uses a different contract
- every payload we recovered resolves to a single SectopRat C2 channel
We therefore assess that, for now, these loaders are not sold to third parties beyond the actor described here.
Given the workflow and commands, it is clear that the SteamLoader and VMLoader were built by the same entity: it uses the same contract, the same workflow, commands and strings to download, extract and execute the payload it downloads. However, if it is not shipped with any other files (which we believe), the SteamLoader is clearly poorly made. The FakeGuard malware and C2 being very probably vibecoded, we believe that the SteamLoader malware was too. And as it was used operationnaly besides the program being quite illogical, we think that the VMLoader and GPULoader might also have been vibecoded too. However we do not have any proof to attest it.
Now, if we focus on these TTPs, they appear to be very similar to the elements described by Arctic Wolf in their GPUGate article :
- download of a ZIP archive from a "zip.php" URL and execution of the contained executables, which include a sideload
- GPU-based decryption of the payload
- addition of Windows Defender exclusions for a folder
- execution gating based on the system's graphics specifics, in particular the length of the card name
- C2 servers located in highly similar network ranges (
107.189/16,45.59/16,104.194/16) - propagation via malvertising targeting IT-related software
When looking at the other SectopRat smart contracts, we found that 135 newer contracts were emitted since the creation of the one linked to this campaign. The one used by the payload was created on the first activity month (May 2025) and lots of SectopRat related samples to the same contract can be found on VirusTotal since then. For instance, one of them was delivered with the 6832faa4f ZIP archive. It embeds the payload in a XOR-encrypted file.
Conclusion
GPULoader and VMLoader are the product of a deliberate engineering effort. Rather than piling on packers, their author reached for mechanisms that are genuinely hard for defenders to replay at scale: a decryption routine that only runs correctly on a real GPU, a custom stack-based virtual machine that hides the sensitive logic (anti-analysis, EDR unhooking, persistence, C2 retrieval) behind an opcode dispatcher, and hardware fingerprinting that filters out emulators, software renderers and under-specified sandboxes before any malicious behavior is exposed. The GPU step is the centerpiece: a sandbox without a non-blacklisted GPU/emulator would never see the payload decryption, and the modified AES MixColumns matrix means even a correct key fails against a stock AES implementation.
For now, we assess that the VMLoader/GPULoader/FakeGuard toolset is developed and maintained by a single threat actor, very likely the same one behind the GPUGate toolset described by Arctic Wolf in 2025. Whether these campaigns are operated by that actor directly or by one or more customers, and whether the same operator is behind both GPUGate and this campaign remains unclear.
The SectopRat analysis was not expected as we first wanted to focus only on the loaders because of their technical aspect. By analyzing the Etherhiding C2 chain, we quickly focused on this mechanism, and identified the old 0x39a9 wallet which seemed to be an operational secrurity mistake by one of the SectopRat operators, as it was once topped up from a KYC-enforcing Binance hot wallet years before being repurposed for SectopRat.
Finally, the fact that a test C2 IP address was retrieved in the FakeGuard docstrings highlights the fact that generating malware with LLMs can lead to such leaks. We do not know how many tools were crafted using such techniques: both the FakeGuard and its C2 counterpart are very probably generated as such, and we think that the SteamLoader is also AI-generated. However we do not know wether the VMLoader and GPULoader are, but it would not be suprising at all if they were.
IOCs
Sha256
REMARK THIS SECTION IS NOT EXHAUSTIVE, ONLY A SUBSET IS PROVIDED
VMLoader phishing ZIP
- e44f3dfc256c31747b2987c577a562ec934646b2a7836c719855842c9d4dc3f7
- 3b7846908b421681ad1c3a04203f869a3bdb5226300ae0924be549b55cd9ca96
- 8d1a8317c635854145960b608756b048ed787ecc91daff5e1ec4117563ddc2d2
- 03d7e03ffd380044a13228eeee22c11f8bd2d20f1880105a3a87bf721fdcb595
- 197b6c515cbb9696f3ba1b8a40857189e9de8fc9fa7787fa3e154c9fcf3ea31c
VMLoader stage 2 ZIP
- 5bd4654b855f853691ff4d21ab0e22b596ce909d8ae779cb685c810b6b3f0275
- 6c2b73e3974c81280c0d0ad31db612401ed8137c0f35dc6d67c2bc61e6614c67
- 80e4fa61a03c5aa06fa1fc5cdb19b47a77efdc52d476d26a4b4d1c1e2cae4a7b
- bce2def5c8f11e4458df143cad0dcff9b817b89ffed3a0aae812ad6da23eced5
- 7d71219b61cbfa5a251df9a185e4abb7aaeb15e76b23529e5d2ebfd2a30c0f73
GPULoader Companion files
- 6dfecc6121ebf2d31bcf0f227574c905229a42cee9b05cd811f94a8e91f5734c
- 4cf82033e30ba3cbab82433ff5e5985be0ad3ed4406e0c5ca8766b8b3728fcca
- c1f474069c0bb9d81f60c8f83da0915158501d54db54f7a9b18c1a62067bc923
- 1a8f050df20359e675f80e140cf48f5be1f0659c8a98450c43d255254fb53b97
- 62f7c0fdf2fbfd0e517a39c313bfe0245139617ef226b4fc01a0eb6054880fd3
VMLoader DLL
- 2fef321364fa8c07c6251dc774492cbeff573309d185e06fa94eb292855081b7
- 4deac9ef9de40e94531ec71c687934da3522433b9a5119bfe6fde88dcb9114cd
- ce2cb9efa1c6ea2fbd9c6629cc50815b12000f3a59a0531471c8eb01ffc34531
- 223fcbc48067c2da1f837185c731fe8c45098d778dea5270f8042928a69b4b0b
- ba6377b19a33e9a7b1d3b885eac56375b7173ce68d35b35807da0ecf4cbaadab
- de5f20f57516e8c96824459ce1ec809b9f8eb6c9ffb59638d5902f09dc383b1a
- 1026d8c05e9262255b227b0486e62f531f5d5604775d004c7a3e8fccc5ea6f44
- 6b8ecc210ac8a9a22c357bc798e39d4effa3f164b70eb672568738b90b3458f7
GPULoader DLL
- 925ad6253e84a28e0e2538b7492a991b0224a88f334f586880ade9ef6bbc59f2
- 2001d1c820b71a6565eaa9bdeb764b4ebeea7e868d053a244ecf73ef04173cff
- a2c9b74048dff925ff3f57ed62557fc0af4d9fea30917ee0e8ff8700b06b6822
- 68eb0c36856632bee2fd59993cd2e0293563ef918f5133e6108e6ef11f794c99
- 28b4ab2f7e280d13a5a06025b7a047101deb51b2e405619e7d5d59bb37a73ed7
- 1cf6e50a13b54b8e4ccaaea63f62e549ab11fd42e99626229375823632782724
- e9ff5a2e8abb7ea683d86ce48f5b738f51859f779ad48f1f12287d90ef4bdba3
- f0ac40ffda3fc557c0603c7d747b18d3e50e6ba8e0194214e05ece5d59b38712
Paths
%LOCALAPPDATA%\SiteGuard\browser-extension%LOCALAPPDATA%\SiteGuard\%APPDATA%\EdgeUpdate-<8hex>\%APPDATA%\Cisco AnyConnect Secure Mobility Client\Profile\
Mutex
Global\DefenderHydrationGateGlobal\OneDriveStandaloneCacheGlobal\MicrosoftEdgeRolloutSyncGlobal\TaskHostSchedulerGateGlobal\WindowsTelemetryDataAcq
Commands
Note: in the commands below, <MALWAREPATH> is replaced by the path of the malicious code:
powershell -NoProfile -Command Add-MpPreference -ExclusionPath 'C:\Users'schtasks /create /tn "MicrosoftEdgeUpdate" /tr "<MALWAREPATH>" /sc onlogon /rl highest /fcmd /c cd /d "\u" && tar.exe -xf "<MALWAREPATH>\update.bin"cmd /c for /r "\u" %f in (*.exe) do @start "" /d "%~dpf" "%~f"cmd /C choice /C Y /N /D Y /T 6 & Del <MALWAREPATH>
Run keys
DefenderTelemetryServiceMicrosoftEdgeUpdateTaskMachineTaskSchedulerHelperSvcWindowsConfigurationServiceWindowsTempCleanupSvcOneDriveStandaloneUpdaterTaskSchedulerHelperSvcWindowsConfigurationServiceDeviceCensusBackupWlanExtensibilityProviderUserNotificationListenerAppReadinessTrigger
Scheduled tasks
- Task
MicrosoftEdgeUpdaterunning a program in a folder prefixed withEdgeUpdate-.
The following tasks have legitimate-looking names, but unlike the malicious ones, legitimate tasks are never located at the root:
MicrosoftCompatibilityAppraiserAppxManifestRecoveryServiceWindowsActivationTechnologyMicrosoftSearchIndexerHelperDiagnosticsHubStandardCollectorWatcherWerSvcRollbackTaskWindowsDefenderTaskExcludeBackgroundTaskInfrastructureHelper
C2
VMLoader
neeitoerw[.]mylegsotier[.]usneeitoerw[.]myapisue[.]clickzippis[.]xyzfaceitzip[.]xyzarzipi[.]xyz
FakeGuard
45.59.122.85216.126.227.160(mentioned)167.88.172.111153.92.223.11372.60.20.149191.96.1.36
SectopRat
2.24.131.2462.24.128.2945.59.114.19045.59.117.6745.59.117.14545.59.122.8245.59.123.12245.59.122.13445.59.122.23545.59.124.1745.59.125.228104.194.133.210107.189.17.143107.189.24.67107.189.26.86107.189.21.86107.189.22.118107.189.20.32107.189.20.95107.189.24.255195.110.58.222191.101.80.211