Dynamic analysis: build 2, run 1, blind recovery with build 1’s decryptor (protocol fixed 2026-10-13, before detonation)
Goal: check whether build 1’s decryptor, unchanged, recovers files that this build encrypted. It uses only responder data, under the run-6 protocol of case 2026-10-11_101bd45ab673_akira-ransomware.
Frozen before the detonation
| Item | SHA-256 |
|—|—|
| build 1 06-decryptor/akira_decrypt.py (tool under test) | 870c6db94f5bf94a52be630905131c24138555afd3bcef2a7bdc59ee6b81a8fe |
| build 1 06-decryptor/akira_fast.py | 07352777bff09eb30f14a8c826c503e9247948d1385b7dcc8cd02288f4606927 |
| b2run1-blind/b2_blind_recover.py (driver; differs from build 1’s run-6 driver only in the TOOL path and two labels) | fc5d69fde484355854594832a495192bd51d96caf08ba0251bed1655dcd5f72b |
| b2run1-blind/collect_clock_and_times.ps1 (byte-identical to run 6’s; writes pre_run6.txt / post_run6.txt on the VM) | 15fbf5794497b64ac954ba86bc012776971105a6a37a21137d2c4dd45eee7ff4 |
| b2run1-blind/state_probe.ps1 | f91ee0d2f6a716057e426030fa6ba615cc4781cb2a9a373b51b6548a67ebbde3 |
Rules
Identical to build 1’s run 6:
- pass 1: mtime −8/+1 ms, gap 3,800–8,000;
- pass 2, automatic on a miss:
--anchor iv2, 2.5:0.1, gap 8,001–30,000; - known bytes: fixed per file type;
- outcomes: MATCH, KEYS FOUND OUTPUT DIFFERS, NOT FOUND, OUT OF SCOPE.
No tuning after encryption.
Procedure
- VM: revert. The analyst copies the two scripts to the Desktop and places test files in
samples\data. - Before encryption: a state probe, then
collect_clock_and_times.ps1 -Tag pre. A Ghidra copy of the pre-listing is imported before encryption and not read. - Launch:
init "<exe>", "--encryption_path=C:\Users\deadtrace\Desktop\samples\data -localonly", "C:\Users\deadtrace\Desktop". - Gates:
FUN_140078890: force return (rax=0; rip=[rsp]; rsp+=8);FUN_14007ac00: check thatr8is the single root.
- Run: delete all breakpoints, then run to exit. No hooks and no seed reads.
- After the run, same boot:
-Tag post. The analyst copies the.akirafiles andpre_run6.txttob2run1-blind/. - Recovery:
python -I 04-dynamic/b2run1-blind/b2_blind_recover.py --run-dir 04-dynamic/b2run1-blind --pre pre_run6.txt --post post_run6.txt.
Results (2026-10-13): build 1’s decryptor, unchanged, recovered 6 of 7 in-scope build-2 files hash-exact
Log: artifacts/b2run1-blind-recovery-2026-10-13.txt. It shows the driver fc5d69fd… and the decryptor 870c6db9…, both as frozen. Machine-readable results: b2run1-blind/results.json.
Responder data:
- every
.akirafile matched the VM’s post-run SHA-256. The analyst moved them with a Python HTTP server on the VM, and the hash check covers that transfer; - QPC offset
134363561561486661, from 7 clean pairs (spread 111 ticks).
Detonation:
- image base
0x7FF709530000; - the WMI executor
+0x78890was forced to return, called from+0x791AA; - the root queue
+0x7AC00showed one root,...\samples\data; - then no breakpoints;
- operator log: 2 threads, 36,814 ms.
AnyDesk.exe(8.4 MB) was not encrypted: an.exeexclusion, as in build 1.
| File | Size | Known bytes | Pass | Search | key2 / iv2 gap | Outcome |
|---|---|---|---|---|---|---|
20358696.jpg |
24,287 | JFIF 11 B | 1 | 15 s | 4,900 | MATCH |
photo_2026-09-23_15-02-25.jpg |
172,871 | JFIF 11 B | 1 | 26 s | 5,380 | MATCH |
photo_2026-09-24_12-44-15.jpg |
214,866 | JFIF 11 B | 1 | 30 s | 3,896 | MATCH |
QC-STC-…_v1.0.docx |
42,333 | ZIP header 28 B | 1 | 26 s | 4,225 | MATCH |
Screenshot 2026-09-10 152951.png |
26,953 | PNG 16 B | 1 | 28 s | 4,306 | MATCH |
Screenshot 2026-09-29 125745.png |
47,803 | PNG 16 B | 1 | 22 s | 4,013 | MATCH |
Detection Lab Automated BAS-to-Splunk Detection Engineering Loop.pdf |
595,456 | %PDF-1. 7 B |
1 | 22 s (KCipher-2), 155 s in total | 4,086 | KEYS FOUND, OUTPUT DIFFERS (ChaCha stage 2 found nothing, as with build 1’s run-6 PDF) |
rule.yml |
981 | none | – | – | – | OUT OF SCOPE |
Timing, relative to the note and using the live offset:
- key2 sat 3.6–14.5 ms after the note;
- mtime − key2 was 1.34–2.31 ms;
- mtime − iv2 was 0.91–1.91 ms. This falls within build 1’s observed range (0.55–1.86 ms) except the photo at 1.91, and it is well inside the pass-2 window.
- Pass 2 never ran.
Verdict:
- Statically: build 2 shares build 1’s key generation.
- Dynamically: build 1’s decryptor recovers build-2 files blind with no change. That includes the mode/chunk layout, the ciphers and the timing behaviour, which the static comparison left open.
- The same limitation applies: files with ChaCha8 chunks come back only partly decrypted. Here that meant the PDF over 262,140 bytes.
Pre-listing integrity: the host pre_run6.txt (3,289 B, SHA-256 22d1f54b…) agrees with the Ghidra /b2run1 copy imported before detonation. Both are 3,289 bytes, and all 13 per-file SHA-256 values are identical.
Addendum (2026-10-14): the PDF, recovered after the run
This addendum does not change the blind result above (6 of 7), because the frozen driver did not include these tests.
- Cause: the same as build 1’s run-6 PDF. The seeds were in the default window. The zeros/text check looks only at byte 65,535, which here is the tail of object 24’s compressed stream.
- Targeted rerun (
06-decryptor/stage2-investigation/, logartifacts/stage2-pdf-xref-oracle-b2run1-window-2026-10-14.txt):- the plaintext classic xref tables give 968 exact
N G objheaders inside the ChaCha chunks; - each candidate costs one ChaCha8 block, and the 24 M-pair window took 89 s;
- exactly 1 pair matched, and all 968 headers decrypt with it;
- the rebuilt file’s SHA-256 equals the sealed hash (
adb6bafb…). Seeds:1219626222000, 1219626650700, 1219627041700, 1219627450300.
- the plaintext classic xref tables give 968 exact
- Now in build 1’s decryptor as a stage-2 fallback for PDFs (default
recover). The unchanged command line recovers this file hash-exact in 4 min 52 s using the xref test (build 1 caseartifacts/stage2-integrated-recover-2026-10-14.txt). The deflate test alone also finds the same seeds (artifacts/stage2-deflate-test-crosscheck-2026-10-14.txt). - With the fallback: 7 of 7 in-scope build-2 files are recoverable.