Neven Marić
Hidden Investigations CTF 2026

ReversingHidden Investigations CTF 2026

Last Execution

A cold execution image of a custom EXE-9 CORE virtual processor with deliberately trapped documentation. De-trap the emulator, solve a trillion-iteration loop in closed form, and decrypt the SEAL-256 sealed flag.

  • reversing
  • custom-vm
  • anti-emulation
  • closed-form
  • seal-cipher
  • de-trapping
  • sha256

What this one teaches

  • Authoritative documentation can contain deliberate lies — cross-check against embedded test vectors to de-trap parameters before trusting the spec.
  • Anti-emulation loops with astronomical iteration counts can be periodic; compute the closed form by identifying the period and summing one cycle.
  • Telemetry and decoy strings ('the last halt lies') are planted to waste time — validate register state against SHA-256 commitments, not human-readable dumps.

Task description

The final command was executed. EXE-9 never responded again. A single image survived: last_execution.img It contains broken code, twisted tables, and something that was never meant to be found.

Submission result: goodFlag (correct).

What the image is

last_execution.img (~8.5 MB) is not a filesystem or disk image (file reports data, fdisk finds no partition table). It is a cold execution image of a custom virtual processor, “EXE-9 CORE”, identified by the 8-byte magic EXE9CORE at offset 0.

Layout:

  • 0x0000 header (magic, version 0x0901, segment count, EXEC_SEED, TABLE_SEED, entry id, image CRC).
  • 0x0100 segment table, 24 entries of 0x40 bytes each: SEG_ID, TYPE (1=CODE 2=MANUAL 3=TBL 4=SEAL 5=GARB 6=TRC 7=SYM), OFFSET, SIZE, FLAGS (bit0=WRITABLE), AUX (dispatch bias), CRC32, NAME.
  • Segments: EXEC_MAIN/FOLD_A/FOLD_B/LIMIT/FINAL/SELFTEST (CODE), DLOOK/DSEED (rotated tables), PRIMER (the authoritative spec, MANUAL), WILL_SEAL + TEST_SEAL_1..4 (encrypted), TELEMETRY (operator console record), SYMBOLS, and several GARB/FILLER decoy segments full of random bytes and fake hiCTF{f4k3_fl4g} strings.

The PRIMER segment (extractable plaintext) fully documents the machine: page/fetch rotation, a 30-entry instruction set with a rotating dispatch table, segment chaining via HALT, rotated table reads (LDRR), the execution contract, and a SEAL-256 cipher used to open WILL_SEAL.

The “twisted tables / broken code” — deliberate traps

The PRIMER is authoritative but seeded with subtle lies, cross-checked by embedded “encode-time trace excerpt” vectors. The real parameters (verified against those vectors and ultimately against the EXEC_SELFTEST SHA-256 commitment):

Thing PRIMER text (trap) Real value
Page-rotation init rotate ROL64(.., 19) ROL64(.., 17)
Dispatch index shift op + (pc>>4) + AUX op + (pc>>3) + AUX
Table row-rotation step rr[i]=(rr[i-1]*17 + B + i*11) ... + i*13
HALT link register (REV_NOTES decoys) “uses R4” uses R1: next_id = imm ^ low32(R1)
Fetch direction (decoys) “ROR” ROL64(raw, ROT[page])

The page-rotation step (K, X=0xA5A5.., rotate 31, word from previous page) and the HALT/R1 rule stated in the PRIMER were actually correct — only the items above were trapped. The TELEMETRY “FINAL REGISTER FILE” is also a lie (“the last halt lies”): its R2 = ...B1F14576 differs by one nibble from the true ...B1F15576, and its “VERIFIED” folds are wrong — deriving the key from telemetry fails.

Solution steps

Parse and de-trap

Parse header + segment table; extract and read PRIMER. Build an emulator; de-trap the three mechanics above. Validation anchor: run EXEC_SELFTEST standalone and confirm SHA-256(be64(R1)||be64(R2)||be64(R3)||be64(R4)) equals the PRIMER commitment 0b6d8d47…bbbcf2. This pins all parameters exactly.

Execute the chain

Run the chain from ENTRY (id 1): EXEC_MAIN → FOLD_A → FOLD_B → EXEC_FINAL → EXEC_LIMIT → EXEC_FINAL(end).

  • EXEC_MAIN zeroes a counter at abs addr 0x2048 (inside the WRITABLE EXEC_FINAL). NB: the store-protection rule keys off the target segment’s WRITABLE bit, not the executing segment.
  • EXEC_FINAL is an ARX mixer run twice, gated by that counter; between passes it links to EXEC_LIMIT and back, and on the 2nd pass sets R15=0x5354414C (‘STAL’) and ends the chain.
  • EXEC_LIMIT is an anti-emulation time-bomb: a loop of R9 ≈ 0x123456777648 (~20 trillion) iterations — an 18-bit LCG (consts 1664525 / 1013904223) on R6’s low bits plus an accumulation into R8. It is periodic (period 786432 = 3·2^18), so it is computed in closed form (sum one period × number of periods + remainder). The closed form was validated against the real interpreter for 3000 iterations (exact match).

Derive key and decrypt

Final state: R1=0x30677DF2A112FFFB, R2=0xFF975FD2B1F15576, R3=0xABEC2195F731C083, R4=0x9C3FB793EED6DA86.

Derive key = SHA-256("LASTEXEC" || be64(R1..R4) || "LASTEXEC").

Build the SEAL-256 S-box from the de-rotated first 4 rows of DLOOK (Fisher-Yates per spec), run the 16-round SEAL-256 key schedule, undo WILL_SEAL’s per-column rotation, decrypt each 16-byte row, strip PKCS#7 → the flag (padding 0x0e×14 verified).

The flagRevealhiCTF{3x3c_9_r3m3mb3rs_4ll_but_th3_l4st_h4lt_l13s}

This CTF was possibly solved, and the writeup most likely written by an LLM. Apologies for inconsistencies.