| Needlebox |
1. Phrase
phrase:
2. Proof Token
0x7edd5b3a9689e2b4
3. Seal
s0: 0x8b3d40cfc0200449
s1: 0xed5b26a9a6466229
(Seal is the pair of modified state variables after the 64-round second phase. s2 =0x48fe830cfc1c3864 remains as the initial constant throughout.)
If the seal is expected as a single value, it's the XOR: 0x63e6662669666660.
4. Attack Summary
Static analysis + emulation hybrid approach:
Binary triage: PE32+ x64 console, MinGW GCC, stripped. Identified custom hash via golden ratio constant 0x9e3779b97f4a7c15 (xxHash family) and unique multipliers at 0xbf58476d1ce4e5b9, 0x94d049bb133111eb.
Phase 1 (phrase decoder): Located encoded 9-byte block at 0x140189040. Traced the loop: 9 iterations of mix(i ^ state ^ (seed<<8)) where seed=0x5100, extracting a key byte via (state >> ((i&7)*8)) ^ (seed*37 + i*13), XOR'd with each encoded byte to recover plaintext.
Phase 2 (seal/proof): 64 rounds of context-decoded substitution — each round XORs lookup_table[i&0x3f] with a state-derived byte before feeding into the mix chain. This implements the hint "round constants are context-decoded."
Emulation: Used Unicorn Engine to execute the algorithm directly, capturing decoded phrase from the stack output buffer and state variables from the frame. CRT/import calls were hooked to return immediately.
Key insight: "The visible alphabet lies" - the 64-byte lookup table at 0x140189000 appears random but each entry is XOR'd with context during rounds. "Proof token is not just final state" — it's the intermediate state after Phase 1, before the 64-round seal computation. |
2026-05-09 23:02 |
| aola |
The binary uses sscanf(input, "%s.%63s", ...) to split your input at a dot. The part after the dot is compared against the decoded password.
Decryption (function at 0x140001770)
13 encrypted bytes at 0x140004010:
f3 c3 da da c3 cf 87 e1 c3 87 f3 cb d3
Each byte XOR'd with 0xAA:
Yippie-Ki-Yay |
2026-05-09 21:53 |