Open Secret
Static ELF using raw syscalls only, so there are no libc calls for ltrace to catch
NNS{7h3_p47h_w4s_h1dd3n_bu7_s7r4c3_s4w_7h3_0p3n} 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: x86-64 statically-linked ELF (raw syscalls only, no libc calls to trace), not stripped.
sym.run() decodes a 17-byte path string at 0x403000 using an LCG seeded at 2:
state = state * 0x19660d + 0x3c6ef35f (mod 2^32)
ks = (state >> 16) & 0xFF
path[i] ^= ks
Decoded path = “/.config/nns/key”. The program then searches envp for a “HOME=” entry, concatenates HOME + path, and openat()s it — printing “no license” if the open fails.
If the open succeeds, a second loop continues iterating the same LCG state (it is not reseeded) for 49 more steps, decoding the flag blob at 0x403020 in the same way. Since the LCG state is fully deterministic and doesn’t depend on the actual file being opened (only on the open succeeding), we can just continue the same LCG in Python past the 17 path-decoding iterations and decode the 49-byte flag blob directly, without ever creating the license file.
Flag: NNS{7h3_p47h_w4s_h1dd3n_bu7_s7r4c3_s4w_7h3_0p3n}