Skip to content

Pay2Key encryptor: what a January 2026 build reveals

Kirk
11 min read
malwareransomwareencryptionreverseengineeringpay2keyiran
On this page

In late February, Pay2Key ransomware hit a U.S. healthcare organisation. Halcyon and Beazley Security published a joint report (opens in new tab) detailing the attack chain: compromised admin credentials, a week of dormancy, TeamViewer for access, credential harvesting with Mimikatz and LaZagne, and a self-extracting 7z archive that deployed the encryptor. The entire encryption phase took about three hours.

The report described the crypto as ChaCha20 with Curve25519 key exchange, a 12-byte null nonce, and per-file key generation via SystemFunction036. The report published IOC hashes, but the encryptor binary from the healthcare incident (68a95a0a...) is not on MalwareBazaar, Triage, ThreatFox, or VirusTotal as a downloadable sample.

We located an earlier Pay2Key build from January 9, 2026, packaged as a Mimic-based self-extracting archive. This is not the same binary used in the February healthcare incident. It is an older build from the same RaaS platform, sharing the same toolchain, SFX delivery structure, and NoDefender AV evasion kit documented in the Halcyon report. The February variant may differ in configuration, encryption thresholds, or behaviour. What follows applies to the January build only.

We mapped the encryptor's crypto architecture: key generation, cipher selection, nonce handling, key protection, and the intermittent encryption logic. The encryption is sound. There is no shortcut past Curve25519, no nonce reuse flaw, no weak key generation. Without the operator's private key, encrypted files are not recoverable through cryptographic means.

In this build, Pay2Key's intermittent encryption mode leaves 70 to 87 percent of large files as plaintext. For databases, virtual machine disks, and backup archives, most of the data is still there. Whether the February build uses the same thresholds and block sizes is unknown.


Sample overview

The Pay2Key encryptor ships inside a self-extracting 7z archive. The outer SFX drops 7za.exe, Everything.exe, and a password-protected inner archive containing the encryptor, a secondary binary, and Sysinternals SDelete.

FieldValue
SHA2562ae80e5bff8fc9055ce7dc60e59447cba6e6c3a215eea1b6de7d9cb5ae26f9e8
MD510333c96ae8c877398bb16841b627c94
TypePE32 (GUI) Intel 80386, MSVC++ 2015
Size2,394,112 bytes
CompiledAugust 31, 2024
Crypto libraryOpenSSL 1.1.x (statically linked)
Internal namepayfast
File extensionConfigurable per build
Ransom noteC:\\temp\\Decrypt_files.txt
Session fileC:\\temp\\session.tmp
Contactueli.maurer@onionmail.org

The encryptor builds on Mimic ransomware (opens in new tab), a Conti derivative that uses voidtools Everything for filesystem enumeration. The import table includes 12 Everything32.dll functions: Everything_QueryW, Everything_GetResultFullPathNameW, Everything_GetResultSize, and nine others. The Restart Manager API (RmStartSession, RmRegisterResources, RmGetList, RmShutdown) handles unlocking files held by other processes before encryption.

This build's internal name is payfast. The February 2026 variant from the healthcare incident reportedly uses the name "Cobalt" internally. Different RaaS configurations produce different internal names, ransom note filenames, file extensions, and contact addresses from the same builder.

SFX delivery chain

The self-extracting archive runs a command line:

7za.exe x -y -p2295124761281648206 Everything64.dll

Everything64.dll is not a DLL. It is a 7z archive encrypted with the password 2295124761281648206, containing:

FileSHA256Purpose
ENC_*.exe2ae80e5b...Pay2Key encryptor (analysed below)
DC.exec576f7f5...AutoIt-compiled binary (not a decryptor)
xdel.exee8eaa39e...Sysinternals SDelete (PDB confirms)
Everything.ini2fefb69e...Everything configuration
Everything2.ini89ad2164...Everything configuration

Both .ini hashes match the IOCs in the Halcyon report. DC.exe checks the registry key Software\\AutoIt v3\\AutoIt and exits with code 1, suggesting it requires an AutoIt runtime dependency not present in the package.

Encryption scheme

Key generation

Each file gets a unique 32-byte ChaCha20 key. The key is generated byte-by-byte in a loop at 0x44e950:

xor esi, esi              ; counter = 0
loop:
  call fcn.0044dc40       ; generate one random byte
  mov [ebp+esi-0x98], al  ; store in key buffer
  inc esi
  cmp esi, 0x20           ; 32 bytes
  jl loop

The call chain resolves to BCryptGenRandom(NULL, pbBuffer, cbBuffer, BCRYPT_USE_SYSTEM_PREFERRED_RNG). This is the Windows CNG cryptographic random number generator. The keys are not predictable.

ChaCha20 with null nonce

The encryptor initialises the cipher context at 0x452443:

xorps xmm0, xmm0                    ; xmm0 = all zeros
movups [ebp-0xdc], xmm0             ; zero 16 bytes
movups [ebp-0xcc], xmm0             ; zero 16 bytes
movq   [ebp-0xbc], xmm0             ; zero 8 bytes

The IV/nonce field within this structure is 12 bytes of zero. Every file encrypted by this binary uses a null nonce.

This is not a vulnerability. ChaCha20 is a stream cipher where the keystream depends on both the key and the nonce. Reusing a nonce with the same key allows XOR recovery of both plaintexts. But Pay2Key generates a unique 32-byte key per file. A null nonce with a unique key produces a unique keystream. The encryption is equivalent to using a random nonce with a random key: both produce an unrepeatable output.

The null nonce would be a fatal flaw only if the same key were reused across multiple files. That does not happen here.

Curve25519 key protection

Per-file ChaCha20 keys are protected with Curve25519 (X25519) ECDH key exchange. The OpenSSL NID 0x40a (1034) for EVP_PKEY_X25519 appears in the key setup function at 0x452514. The scheme:

  1. The operator's static Curve25519 public key is embedded in the binary's encrypted RCDATA resource (253.7 KB blob at 0x006000a4).
  2. At runtime, a per-victim ephemeral Curve25519 keypair is generated.
  3. For each file, the 32-byte ChaCha20 key is encrypted using the ECDH shared secret derived from the operator's public key and the victim's ephemeral private key.
  4. The encrypted key record is appended to C:\\temp\\session.tmp.

The decryptor (operator-side) reads session.tmp, uses the operator's Curve25519 private key with the victim's ephemeral public key to rederive the shared secret, and recovers each file's ChaCha20 key.

session.tmp stays on disk

session.tmp is written to C:\\temp via WriteFile at 0x4528c4 during encryption. Each file's encrypted key record is appended as it is processed. There is no network exfiltration of this file in the analysed build.

The ransom note instructs the victim to provide their "personal ID" via email. This ID likely encodes the ephemeral public key, though we did not verify the exact encoding. The operator needs this ID plus their own private key to decrypt session.tmp entries. If session.tmp is deleted or corrupted before the operator receives it, recovery is impossible for both parties.

For incident responders: preserve C:\\temp\\session.tmp immediately. It is the only file that links encrypted data back to recoverable keys. If law enforcement later seizes the operator's infrastructure and obtains the private key, session.tmp is what makes decryption possible.

Intermittent encryption and data recovery

Mode selection

A byte at offset 0x49 in the encryption context determines the mode:

ValueModeBehaviour
0x31 ('1')FullEntire file encrypted
0x32 ('2')IntermittentPartial encryption with skip gaps
0x33 ('3')Intermittent (alt)Smaller blocks for files under 10 MB

The file size threshold is stored at offset 0x4a and shifted left by 20 bits (1 MB granularity). The Halcyon report states files under 2 MB are fully encrypted and files 2 MB or larger are intermittent.

Block sizes

The intermittent function at 0x450700 sets the encryption block size based on file size:

cmp byte [esi+0x49], 0x33        ; mode 3?
cmp dword [esi+0x10], 0xa00000   ; file >= 10 MB?

mov dword [ebp-0x70], 0x80000    ; block = 512 KB (small files, mode 3)
mov dword [ebp-0x70], 0x100000   ; block = 1 MB (large files or other modes)

The code structure indicates the first and last blocks of each file are encrypted. This would destroy file headers and footers, causing format-level recovery tools to fail on standard entry points.

Skip pattern

The distance between encrypted blocks is not fixed. It is computed from the per-file ChaCha20 key bytes using four floating-point constants:

AddressValueRole
0x5e9d880.00001Odd-byte multiplier
0x5e9d900.0001Even-byte multiplier
0x5e9da00.6Distribution divider
0x5e9db01.4Accumulator scaler

The algorithm iterates over the 32 key bytes, multiplying each by the alternating constants and accumulating the result. The accumulated value, scaled by 1.4 and divided by 0.6, determines the skip offset between encrypted blocks. Because the key bytes differ per file, the skip pattern varies per file. But the encrypted-to-plaintext ratio is roughly consistent.

Plaintext recovery estimates (modeled)

File sizeBlockEncrypted (approx.)Plaintext recoverable
2 MB512 KB75%25%
5 MB512 KB30%70%
10 MB1 MB30%70%
50 MB1 MB18%82%
100 MB1 MB15%85%
500 MB1 MB13%87%
1 GB+1 MB12.5%87.5%

These estimates are based on the block sizes and segment calculation in the binary. They have not been verified against actual encrypted files. For files over 10 MB, the model suggests roughly 85% of the content is untouched.

Partial recovery targets

SQL databases, VHDX virtual disks, backup archives, and large document stores are the most recoverable targets. These formats store data in structured pages or blocks. With 85% of the content intact:

  • SQL Server / PostgreSQL: Data pages in the middle of .mdf / .ndf files are likely intact. Table data can be carved from raw pages even without the header.
  • Hyper-V VHDX: The VHDX metadata and BAT (Block Allocation Table) in the header will be encrypted, but the bulk of the virtual disk data in the middle is plaintext. Tools that can parse raw NTFS from a known offset can recover files from inside the VM.
  • Backup archives: Depending on the format, individual backup segments in the middle of the file may be intact and extractable.

The encrypted blocks are randomly distributed based on the key, so automated carving requires identifying the block boundaries. A recovery tool would need to scan for the transition between high-entropy (encrypted) and structured (plaintext) data at 1 MB intervals.

Conti/Mimic heritage

Pay2Key's encryptor is built on Mimic ransomware, which itself derives from the leaked Conti builder (opens in new tab). The lineage is visible in the service and process kill lists. The encryptor terminates 60+ services and 40+ processes before encryption, including:

Services: AcronisAgent, BackupExecJobEngine, CAARCUpdateSvc, DefWatch, MSSQLFDLauncher, Veeam*, ccEvtMgr, ccSetMgr, SQLWriter, sophos, MVArmor, PDVFSService

Processes: sqlservr, sqlagent, msaccess, mysqld, oracle, python, node, java, Raccine, Sysmon, xServer, QBDBMgr, Creative Cloud

The Everything.exe integration for file enumeration, the Restart Manager API for file unlocking, and the SDDL-based ACL manipulation all originate from the Mimic codebase. Pay2Key adds Curve25519 key exchange (replacing Conti's RSA), the intermittent encryption mode with key-dependent skip distances, and the session.tmp key escrow mechanism.

Assessment

The crypto primitives are well chosen. BCryptGenRandom produces unpredictable keys, ChaCha20 is implemented via OpenSSL's CRYPTOGAMS assembly, and Curve25519 key exchange is computationally infeasible to break. The null nonce is irrelevant with unique per-file keys. We found no implementation flaw in the code paths we analysed that would enable victim-side decryption.

The practical recovery paths:

  1. Intermittent mode gaps. Files over 10 MB retain roughly 85% of their content as plaintext. Structured formats like SQL databases and VHDX disks can yield significant data through raw carving.
  2. Memory forensics. If a memory dump is captured while encryption is still running, per-file ChaCha20 keys may be recoverable from the process heap. The Halcyon report noted approximately one hour for the active encryption phase in the February incident.
  3. Preserve session.tmp. If law enforcement seizes the operator's Curve25519 private key, C:\\temp\\session.tmp is required for decryption. Without it, even the operator cannot recover files.

IOC summary

Host

IndicatorTypeContext
C:\\temp\\session.tmpFile pathEncrypted per-file key store
C:\\temp\\Decrypt_files.txtFile pathRansom note
ueli.maurer@onionmail.orgEmailRansom contact
payfastInternal nameBinary self-identification
HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\AllowMultipleTSSessionsRegistryTerminal Server persistence
HKLM\\system\\CurrentControlSet\\Control\\Terminal Server\\fSingleSessionPerUserRegistryTerminal Server persistence

Behavioural

IndicatorDescription
Everything32.dll importsFilesystem enumeration via Everything API
BCryptGenRandomPer-file key generation (BCRYPT_USE_SYSTEM_PREFERRED_RNG)
RmStartSession / RmGetListRestart Manager file unlocking
Fake Avast WSC registrationNoDefender toolkit (separate components, not in encryptor)
FileSHA256
SFX loader5e1ba287113770184fb51f0faed1a851d5066fa263a67a463da17601de82cb5a
Encryptor (ENC_*.exe)2ae80e5bff8fc9055ce7dc60e59447cba6e6c3a215eea1b6de7d9cb5ae26f9e8
Everything64.dll (encrypted payload)c45b87fff769379ebb9f4708438e208ee134692a2392a987205bfe900cceacb1
DC.exec576f7f55c4c0304b290b15e70a638b037df15c69577cd6263329c73416e490e
xdel.exe (SDelete)e8eaa39e2adfd49ab69d7bb8504ccb82a902c8b48fbc256472f36f41775e594c
Everything.ini2fefb69e4b2310be5e09d329e8cf1bebd1f9e18884c8c2a38af8d7ea46bd5e01
Everything2.ini89ad2164717bd5f5f93fbb4cebf0efeb473097408fddfc7fc7b924d790514dc5

NoDefender toolkit (July 2025 campaign, reused in February 2026)

FileSHA256
powrprof.dll1c70d4280835f18654422cec1b209eec856f90344b8f02afca82716555346a55
powrprof.exea8bfa1389c49836264cfa31fc4410b88897a78d9c2152729d28eca8c12171b9e
wsc_proxy.exebd4635d582413f84ac83adbb4b449b18bac4fc87ca000d0c7be84ad0f9caf68e

See also: Payload ransomware group: mutex MakeAmericaGreatAgain.

Share this article