A walkthrough of a sample i found in VT - a 32-bit Windows ransomware that calls itself “Payload,” rents itself out as a service, and still moves like it’s 2021.
The sample that shouldn’t exist #
When a 32-bit PE compiled in February 2026 lands on the bench, you double-check the timestamp. Then you check it again. Nobody ships 32-bit ransomware anymore — except, apparently, the affiliates behind a RaaS brand called Payload.
SHA256: 1ca67af90400ee6cbbd42175293274a0f5dc05315096cb2e214e4bfe12ffb71f
Size: 394,752 bytes
Type: PE32 console, Intel i386, MSVC
ClamAV: Win.Ransomware.Babuk-10032520-1
That ClamAV signature is the first breadcrumb. The Babuk source code leaked in 2021 and has been spawning derivatives ever since — Rorschach, RTM Locker, Rook, the LockBit-Green cross-pollination. Payload is the latest descendant, and the operator is clearly fine with the codebase being five years old as long as it still encrypts.
So let’s see how it works.
Walking past the front door #
The import table tells almost no story. Three libraries: kernel32, advapi32, shell32. That’s it. No WinHttp, no Crypt32, no Ntdll — none of the surface area a static analyst would normally use to fingerprint behavior.
That’s because 23+ APIs are resolved at runtime by walking PE export tables. The resolver uses an offset-by-one trick that confused me for an hour: each mov [global_slot], eax instruction stores the result of the previous GetProcAddress call, not the current one. Once you accept that, the NT API table falls out:
[0x45f6b4] = NtCreateFile
[0x45f6bc] = NtClose
[0x45f6c4] = NtSetInformationFile
[0x45f6c8] = NtQueryDirectoryFile
Those four slots are the entire victim-file pipeline. Remember them — they come back later.
Blinding the watchers #
Before Payload touches a single file, it patches ETW (sub_4092D2). The Event Tracing for Windows providers that EDR vendors hook through — EtwEventWrite, EtwEventWriteFull, EtwEventWriteTransfer, EtwRegister — get neutered in memory:
Four functions, two instructions each. The Windows Threat Intelligence provider, AMSI scan callbacks, anything routing telemetry through ntdll ETW — they all return cleanly with zero events emitted. The watcher is still standing there. It’s just not seeing anything.
The pre-encryption housekeeping #
The orchestrator sub_40A855 reads like a checklist:
- Empty the Recycle Bin (
SHEmptyRecycleBinA) — no recovery from there. - Set lowest shutdown priority — if the user panics and reboots, Payload dies last.
- Delete shadow copies —
cmd.exe /c vssadmin.exe delete shadows /all /quiet. Notably, this is launched from a 32-bit process, so Payload first callsWow64DisableWow64FsRedirection(runtime-resolved, of course) to avoid being silently rerouted into SysWOW64 wherevssadmin.exedoesn’t exist. - Stop services — Veeam, BackupExec, Acronis, QuickBooks, the entire backup-vendor rolodex. Uses
EnumDependentServicesAto walk the dependency tree first, so dependents stop cleanly. - Kill processes — 31 entries:
sql.exe,outlook.exe,excel.exe,thunderbird.exe,steam.exe, the usual suspects. The goal is releasing file locks on documents and databases.
Nothing exotic here. This is Babuk’s playbook, transcribed line for line.
The enumeration mystery #
Here’s where I lost an hour. I expected FindFirstFileW / FindNextFileW — the canonical Win32 directory walker, the one every ransomware writeup mentions. Payload doesn’t import either of them.
The answer was in slot [0x45f6c8]: NtQueryDirectoryFile. Payload skips Win32 entirely and talks to the NT layer.
The enumerator lives in sub_4099c0 and runs as a thread proc launched from sub_40a22c at 0x40a6e0:
For every file the enumerator finds, it doesn’t encrypt it directly. It posts the file onto an I/O Completion Port:
That’s the Babuk signature pattern — and it’s why this thing runs fast.
IOCP, briefly #
An I/O Completion Port is a kernel-side queue. The enumerator is the producer: it walks directories and drops work items. A fixed pool of worker threads are the consumers: they block on GetQueuedCompletionStatus, grab the next file, encrypt it, loop. The kernel does the scheduling. You get parallel encryption without the cost of spawning a thread per file.
For ransomware it’s perfect. For defenders trying to interrupt encryption mid-flight, it’s nightmarish — pausing the enumerator doesn’t stop the queue, and killing one worker just leaves files for the others.
The worker loop lives in sub_40a1a2:
The crypto #
Two primitives, both standard Babuk:
ChaCha20 (sub_401992) — confirmed by the sigma constant and quarter-round rotations:
A CLI flag selects between scalar, SSE2, and AVX2 implementations. Whoever wrote this cared about throughput.
Curve25519 (sub_40a22c) — ECDH key agreement against an embedded operator pubkey:
Base64: aH9Tbdc+qPcQkPwhclaNYFadhF04GzuGsuRxDbKMRkU=
Hex: 687f536dd73ea8f71090fc2172568d60569d845d381b3b86b2e4710db28c4645
Without the operator’s Curve25519 private key, you can’t decrypt it. That’s the design — and the math is solid. Breaking Curve25519 directly is ~2^128 work, which is “heat death of the universe” territory.
The ransom note #
The note is RC4-encrypted in .rdata. Key (32-byte ASCII):
Decrypts to:
**Welcome to Payload!**
The next 72 hours will determine certain factors in the life of your company: the publication of the file tree, which we have done safely and unnoticed by all of you, and the publication of your company's full name on our luxurious blog. NONE of this will happen if you contact us within this time frame and our negotiations are favorable.
We are giving you 240 hours to: [1] familiarize terms, [2] begin negotiations, [3] conclude them.
http://payloadrz5yw227brtbvdqpnlhq3rdcdekdnn3rgucbcdeawq2v6vuyd.onion (Tor blog)
http://payloadynyvabjacbun4uwhmxc7yvdzorycslzmnleguxjn7glahsvqd.onion (negotiation portal)
User: hEg62n6K / Password: iuThQRYm5D6HRSF4
Your ID to verify: 1Q6NsTqfT023CTcDSFCt4oyCNKOyochF
Two .onion URLs with payload hostname prefixes, per-victim credentials baked into the binary, a unique victim ID. This is a build from an affiliate panel. There are many like it. This one belongs to someone.
Operator tells #
A few details that screamed “affiliate kit” rather than “auto-detonating worm”:
- CLI flags everywhere.
--background, algorithm selector, mutex on/off, note on/off, auto-delete on/off, target mode (Lock Path/Lock all drives/Lock all drives (no-shares)). - Operator-facing log strings in clear text:
[Mode] Lock all drives,[CPU] AVX2 found,[Mutex] locker running..,[Encryption] END. These are written to the operator’s console, not embedded in any victim-facing output. - A warning aimed at the operator, not the victim:
Filters WILL BE ignored — ATTENTION!. That’s the builder telling its user they’re about to re-encrypt already-encrypted files.
Someone is sitting at a keyboard running this. It’s not fire-and-forget.
Takeaways #
- Babuk is not dead. Five years post-leak, the codebase is still actively maintained by a brand calling itself Payload. The pattern of forking the leak, re-skinning the note, and renting it out as a service is now the dominant mid-tier RaaS model.
- Win32 isn’t the only file API. If your EDR only hooks
FindFirstFileW/CreateFileW/MoveFileW, Payload walks past you usingNtQueryDirectoryFile+NtCreateFile+NtSetInformationFile. The NT layer is where the action is. NtSetInformationFile(FileRenameInformation)is the in-place rename primitive. NoMoveFile, no copy-and-delete. If your detection logic looks for filesystem rename events, you’ll see them — but if it looks for the API call in a userland hook, you won’t, because there’s no Win32 wrapper here.- IOCP-based encryption is hard to interrupt. Killing one worker is meaningless; the queue keeps feeding the others. Defenders need to break the producer (the enumerator thread) or revoke the handles, not chase consumers.
- ETW patching is the new normal. Four
movinstructions and your EDR’s primary telemetry channel goes silent. Userland ETW is no longer trustworthy as a defense surface.
IOC #
File
SHA256: 1ca67af90400ee6cbbd42175293274a0f5dc05315096cb2e214e4bfe12ffb71f
Imphash: 51da4b9aa541a6fc636a97d44ee265b4
URLs
payloadrz5yw227brtbvdqpnlhq3rdcdekdnn3rgucbcdeawq2v6vuyd.onion
payloadynyvabjacbun4uwhmxc7yvdzorycslzmnleguxjn7glahsvqd.onion