| [FIXED] Observer's Paradox |
@KasperskyLabsEngineer Hey, can you take a look at @CrackNotMe other Crackme: "/\ Hydra \/ (MCM 7) /\" (ID: 69cfbdb6110488a320542667), I failed to crack it but I suspect you can finish it. Thanks! |
2026-05-20 21:58 |
| /\ Hydra \/ (MCM 7) /\ |
Hey, amazing work. I don't know why this is only rated 4.3 difficulty, this is at least a 5 to 5.5. I will likely continue this crack tomorrow, if I don't comment on this crackme again then I failed.
This is how far I've got.
Parent to disguised-child anti-attach defeated. The binary re-execs as taskhostw / sihost / SearchProtocolHost / WmiPrvSE / dllhost; gating descendants pre-EntryPoint so the anti-attach PEB.Ldr walk fires once and never again gets you in.
The custom XOR wrap on output_function at 0x5E000 uses key 54 28 6D 44 with period 4. The first instruction is re-encrypted at runtime, so any 5-byte software trampoline gets clobbered into bd ?? ?? ?? ?? (the encrypted form of an e9 jmp rel32) and the function executes with a corrupted prologue. The only safe instrumentation surface is the call site at 0x3094B; everything inside the function has to be observed via hardware breakpoints or by reading memory passively.
All four message ciphertexts are a vanilla SplitMix64 stream cipher (multipliers 0xbf58476d1ce4e5b9 and 0x94d049bb133111eb), each branch storing two movdqu xmm,[rip+disp] chunks plus inline mov imm32 tail bytes plus a hardcoded 64-bit seed. The tell was the assembly pattern: nine consecutive movabs into r8..r13/r14/r15/rsi loading seed+0, seed+1, ..., seed+8 to feed a 9-bytes-per-iter unrolled keystream loop. Decrypted plaintexts:
0x5FB6B seed 0xE343A90C748D5E57 -> "\n[-] ACCESS DENIED.\n"
0x5EDFA seed 0x715F5226D0AA1344 -> "\n[+] NICE! But you're in a VM.\n"
0x5EF4D seed 0x3BE4914D10727526 -> " Flag: MCM7{Nice_Try_But_Bare_Metal_Only}\n"
0x5F308 seed 0x7A85C5D9197AAD7E -> " Run on bare metal for the real flag.\n"
The honeypot trio only fires when the input hash check passes AND [rip+0x50D8] is non-zero (VM detected). The real-metal branch at 0x5FB38 concatenates "\n" + check_buf + "\n" and prints raw, so the actual flag IS the 64-byte check_buf produced by Stage 6, not a stored string anywhere in the binary.
Crypto pipeline:
Stage 2 decrypts a 32-byte heap blob (runtime pointer pair at [rip+0x5C63] and [rip+0x5C88]) by XOR with a key_table-derived stream using consts r8=0x748EEAA66AF7BDA9 and r9=0x29DF323D607C35B with bitshift mixing. The asm uses the (a|b)-(a&b) identity for XOR as anti-RE noise.
Stage 3 is FNV-1a of the first 4 plaintext bytes XOR 0x504F4C59 ("POLY").
Stage 4 is the call to 0x1FDB0, the actual tiny custom VM: 10 dispatcher states (0x7E93 / 0x1948 / 0x2A45 / 0x5C68 / 0x8E7A / 0xA1BC / 0xB4D6 / 0xC3DE / 0xD5F2 / 0xE714), an 8192-instruction budget, an RDTSC tamper-detect that XORs the result with 0xDEADBEEF / 0x1337C0DE if execution takes longer than half a second, and a per-op opclass byte at va 0x63DA8. r8d=0 at the call site disables the in-flight bytecode-rewrite trace channel, so the VM is deterministic in this call.
Stage 5 mixes with golden ratio / pi / e (0x9E3779B9, 0x31415926, 0x27182818) to produce r11d.
Stage 6 picks one of four 64-byte tables at va 0x61CA0 indexed by r11 & 3, then SIMD-XORs against heap_buf and rotated r11 bytes to produce check_buf.
Stage 7 is FNV-1a of check_buf compared against 0x8EDA89A9. Match = bare-metal success and check_buf gets printed verbatim.
The key_table builder at 0x22BC0 is decoded too: 1 MiB scratch filled by HMAC-SHA256-DRBG at 0x21490 (standard SHA-256 IV 0x6A09E667..., ipad/opad blocks), then mixed with RC4-KSA plus an MS-LCG (0x41C64E6D / 0x3039) Fisher-Yates shuffle at 0x22490, then 512 rounds of polynomial multiplication mod the Fermat prime F4=65537 against the 2 KiB constant table at va 0x61DA0, using the Granlund-Montgomery 0xFFFF0001 magic-multiplier reduction trick. Output is the 0x200-byte key_table. |
2026-05-14 23:37 |