Referred to as the 'Final Boss' of the competition, this challenge merged reverse engineering with network protocols. Initial execution yielded nothing until a quick strace revealed the binary was silently attempting to connect to 127.0.0.1 on port 13337. The challenge expected a server to talk to.
Opening the stripped binary in Ghidra revealed a wall of obfuscation. Strategic mprotect calls and XOR routines signaled self-modifying code. The binary dynamically decrypted its own logic at runtime using a static key (0xDE) combined with a randomized stabilization key.
Using pwngdb, I bypassed the fog of war by placing a breakpoint immediately after the mprotect call to dump the freshly decrypted memory. Reversing the exposed logic revealed a complex network handshake requiring a magic DWORD (0x0DF7B6FA). Even after establishing execution flow, the binary heavily mangled the payload, XORing the incoming buffer with a session ID and routing it through MD5 hash validations.
Since the validator processed the payload in 4-byte chunks, I realized the resulting MD5 hashes could be trivially brute-forced on a modern CPU. By cracking the hashes, mapping the multi-round custom ciphers via GDB watchpoints, and executing a synchronized server script to handle the handshake and payload delivery, the final flag was exposed.
Key Takeaways
- Hardware breakpoints and watchpoints in
gdbare essential for dissecting self-modifying code dynamically after memory decryption. - Cryptographic checks operating on tiny structures (e.g., 32-bit integers) are susceptible to rapid brute-force attacks, regardless of the hashing algorithm used.