c1a201cf95536c5c9a63f69793515c296e7db0b289328786e8b1cb7a03714b80pay2key: c1a201cf — Nov 2025 MSVC 14.16 sibling, standard-section unpacked build
Executive Summary
Second confirmed Pay2Key sibling. Compiled 25 Nov 2025 — roughly seven months newer than the first observed sample (eef5cb41). Standard MSVC sections (no UPX), 885 KB, four icons in .rsrc, identical behavioral bootstrap: Sleep → Rstrtmgr → NtSetInformationProcess → priority elevation → mutex → dual worker threads. No C2 strings recovered statically. Static-only (CAPE skipped — no Windows guest).
What It Is
| Field | Value |
|---|---|
| SHA-256 | c1a201cf95536c5c9a63f69793515c296e7db0b289328786e8b1cb7a03714b80 |
| Size | 884 736 bytes (885 KB) |
| Type | PE32 executable (GUI) Intel 80386, 5 sections ^[file.txt] |
| Linker | MSVC 14.16 (VS 2017) ^[exiftool.json] |
| Compiled | Tue Nov 25 18:43:33 2025 UTC ^[exiftool.json] |
| Entry point | 0x5B142 (deep in .text) ^[pefile.txt] |
| Base | 0x400000 ^[pefile.txt] |
| Signed | No ^[rabin2-info.txt] |
| Exports | None ^[rabin2-info.txt] |
Sections are standard MSVC: .text (entropy 6.66), .rdata, .data, .rsrc, .reloc. No UPX0/UPX1 present, overlay: false per radare2. The OpenCTI upstream tag upx-dec appears to be a false positive or refers to a pre-unpacked state no longer visible in the binary we hold. ^[triage.json] ^[rabin2-info.txt]
Resources: four RT_ICON entries (sizes 0xF3E, 0x25A8, 0x10A8, 0x468), RT_GROUP_ICON, RT_RCDATA, RT_MANIFEST. No VS_VERSIONINFO strings recovered. ^[pefile.txt]
How It Works
The bootstrap follows the Pay2Key template documented at pay2key. Entry (entry0 → main → fcn.0042bb50) performs the following sequence:
Sleep(500),SetErrorMode(1),SetUnhandledExceptionFilter. ^[r2:fcn.0042bb50]- Opens/creates
PAY2KEY_LOG.txtvia an internal string-builder (fcn.0040ce00). ^[r2:fcn.0042bb50] - Dynamically loads
Rstrtmgr.dlland resolvesNtSetInformationProcess+NtQueryInformationProcessfromntdllviaGetProcAddress. ^[r2:fcn.0042bb50] - Initializes two critical sections, parses command line, checks console state. ^[r2:fcn.0042bb50]
- Calls
fcn.0041d780andfcn.004249c0— likely config-parsing and GUI setup helpers. - Elevates process priority to
HIGH_PRIORITY_CLASS(0x80) viaSetPriorityClass. ^[r2:fcn.0042bb50] - Invokes
NtSetInformationProcesswith info-class0x21(33). The Pay2Key template uses this for self-protection / break-on-termination semantics. ^[r2:fcn.0042bb50] - Creates a mutex via
CreateMutexA(name computed at runtime — not recovered statically). - Spawns first worker thread (
fcn.00422b40) and waits up to 5000 ms. ^[r2:fcn.0042bb50] - Computes a time delta via
GetSystemTimeAsFileTime, then sleeps again. - Spawns second worker thread (
fcn.00423b70). ^[r2:fcn.0042bb50] - Calls
SetCurrentDirectoryW(0x4cce48)and enters the file-processing loop: opens target files withCreateFileW(access mask0x10e0000), modifies ACLs viaSetSecurityInfo, then closes. ^[r2:fcn.0042bb50]
A block of boolean toggles at 0x4c8ba0–0x4c8bac steers execution branches — likely feature flags for encryption, network spread, or self-erasure. ^[r2:fcn.0042bb50]
Decompiled Behavior
Radare2 decompilation of fcn.0042bb50 (the main orchestrator called from main) reveals the full static bootstrap. The function is ~500 instructions and contains no obfuscation — plain C++ with MSVC CRT exception-handling frames. Key call graph:
fcn.0042bb50→fcn.0040ce00(string builder) →str.PAY2KEY_LOG.txtfcn.0042bb50→sym.imp.KERNEL32.DLL_LoadLibraryW→str.Rstrtmgr.dllfcn.0042bb50→sym.imp.KERNEL32.DLL_GetProcAddress→str.NtSetInformationProcess/str.NtQueryInformationProcessfcn.0042bb50→sym.imp.KERNEL32.DLL_CreateThread→fcn.00422b40(worker 1)fcn.0042bb50→sym.imp.KERNEL32.DLL_CreateThread→fcn.00423b70(worker 2)fcn.0042bb50→sym.imp.KERNEL32.DLL_SetPriorityClass→HIGH_PRIORITY_CLASSfcn.0042bb50→sym.imp.KERNEL32.DLL_SetCurrentDirectoryWfcn.0042bb50→sym.imp.KERNEL32.DLL_CreateFileW→sym.imp.ADVAPI32.dll_SetSecurityInfo
The two thread entry points are not fully resolved in this decompile slice; in the sibling eef5cb41 they implement ChaCha20 file encryption and LAN discovery/ICMP sweep respectively. ^[r2:fcn.0042bb50]
C2 Infrastructure
No hardcoded C2 strings, IPs, domains, or URLs recovered statically. All network indicators are likely runtime-decrypted or configured via the RT_RCDATA blob. ^[strings.txt]
Interesting Tidbits
- OpenCTI
upx-dectag is a false positive for our copy. No UPX sections, no overlay, standard MSVC linker fingerprints. The upstream source may have tagged an intermediate unpacked stage. ^[triage.json] ^[pefile.txt] ^[rabin2-info.txt] binwalkflags SHA256 constants and CRC32 polynomial table at offsets 0xAC480 and 0xB8068 — these are standard MSVC runtime artefacts, not custom crypto. ^[binwalk.txt]- Dinkumware C++ STL copyright string confirms MSVC toolchain. ^[binwalk.txt]
- RT_RCDATA resource exists but was not extracted during triage; likely holds encrypted ransom-note template or config. ^[pefile.txt]
- No exports, minimal IAT footprint — only ~150 imports across 12 DLLs, with no direct
Crypt*APIs imported (crypto is likely inline or in a worker thread not reached by static decompile).
How To Mess With It (Homelab Replication)
Not recommended for replication — this is active ransomware. For research, unpack the RT_RCDATA blob and trace fcn.00422b40 and fcn.00423b70 under a debugger to recover the ChaCha20 key schedule and the file-extension target list.
Deployable Signatures
YARA
rule pay2key_sibling_c1a201cf {
meta:
description = "Pay2Key ransomware sibling — static bootstrap fingerprint"
author = "PacketPursuit"
sha256 = "c1a201cf95536c5c9a63f69793515c296e7db0b289328786e8b1cb7a03714b80"
strings:
$log = "PAY2KEY_LOG.txt" ascii wide
$ver = "2.1" ascii wide
$rstrtmgr = "Rstrtmgr.dll" ascii wide
$ntset = "NtSetInformationProcess" ascii wide
$ntquery = "NtQueryInformationProcess" ascii wide
$samples = "Samples" ascii wide
condition:
uint16(0) == 0x5A4D and
$log and ($ver at 0 or $rstrtmgr) and
3 of ($ntset, $ntquery, $samples)
}
IOC list
| Type | Value |
|---|---|
| SHA-256 | c1a201cf95536c5c9a63f69793515c296e7db0b289328786e8b1cb7a03714b80 |
| Filename (log) | PAY2KEY_LOG.txt |
| Version string | 2.1 |
| Registry persistence (inferred from sibling) | HKCU\Software\Microsoft\Windows\CurrentVersion\Run\Microsoft Edge Update |
| Mutex | Runtime-generated (not recovered statically) |
Behavioral fingerprint
PE32 GUI with MSVC 14.16 runtime, standard sections, deep entry point (>0x5B000). On launch: Sleep(500 ms), dynamically loads Rstrtmgr.dll, resolves NtSetInformationProcess and NtQueryInformationProcess from ntdll, sets HIGH_PRIORITY_CLASS, creates a mutex, then spawns two worker threads separated by a time-delta sleep. Subsequently opens target files with broad access rights (0x10e0000) and modifies ACLs via SetSecurityInfo. No exports, no visible crypto imports.
Detection Signatures
| ATT&CK ID | Technique | Evidence |
|---|---|---|
| T1486 | Data Encrypted for Impact | Pay2Key family, ChaCha20 (inferred from sibling eef5cb41) |
| T1547.001 | Registry Run Keys | Masquerades as Microsoft Edge Update (sibling observation) |
| T1490 | Inhibit System Recovery | bcdedit, wbadmin, vssadmin (sibling observation) |
| T1070.004 | File Deletion | fsutil setZeroData self-erasure (sibling observation) |
| T1055 | Process Injection | Worker-thread model with NtSetInformationProcess |
| T1106 | Native API | NtQueryInformationProcess, NtSetInformationProcess |
References
- Entity page: pay2key
- Sibling analysis:
/intel/analyses/eef5cb41b2c7fe11ce2a0b05de8c6ed583286a0bbc8c632aa073772dcad3efc6.html - OpenCTI artifact:
602201be-3087-425c-a6bb-dd6409781a66
Provenance
Static analysis only. No CAPE detonation (no Windows guest). capa failed (missing signature path). floss failed (mangled CLI invocation). Radare2 analysis level 2, decompilation of entry0 and fcn.0042bb50. Supporting tools: pefile, binwalk, strings, exiftool, rabin2. Provenance markers: ^[r2:fcn.0042bb50], ^[strings.txt], ^[triage.json], ^[pefile.txt], ^[rabin2-info.txt], ^[binwalk.txt], ^[exiftool.json].