Flag Pointer Register

PE32+ — the decoder always runs, the result pointer just never reaches RDX. Replay the 8-byte-key XOR instead

2026.09.30 NNS CTF 2026 97 pts Reversing
FLAG NNS{r4x_h4d_7h3_fl4g_bu7_rdx_p01n73d_70_7h3_wr0ng_buff3r}

This challenge is part of a set written up together in ctf/writeup.txt. Shared context for that set:

All 6 “beginner” tier Reverse Engineering challenges were solved via pure static analysis (radare2 / objdump / Python), no interactive debugging required. Each binary encodes/XOR-obfuscates the flag with a small pseudo-random-number-generator (LCG) keystream, seeded and iterated with constants recovered from the disassembly. Recovering the flag is simply a matter of re-implementing the same PRNG in Python and applying it to the encoded bytes pulled straight out of the binary. Binary: PE32+ (Windows) console EXE.

entry0 reads 8 bytes from stdin, calls a decoder function fcn.140001000 which XORs a 57-byte blob at .data (0x140003000) against an 8-byte key at .rdata (0x140002000), one key byte per position mod 8. It then always writes the same hard-coded “Access denied: RDX points to the wrong output buffer.” string to WriteFile — the decoded flag pointer (returned by the decoder) is simply discarded/never wired into RDX, which is exactly the bug described in the challenge text (the correct pointer for WriteFile’s lpBuffer argument never makes it into the right register).

Since the XOR-decode routine runs unconditionally, we don’t need to actually patch the register — we can just replicate the 8-byte-key XOR over the 57-byte blob in Python.

Flag: NNS{r4x_h4d_7h3_fl4g_bu7_rdx_p01n73d_70_7h3_wr0ng_buff3r}