Description
This binary is putting together some important piece of information... Can you uncover that information? Examine this file. Do you understand its inner workings?
Setup
Download the binary and review it in Ghidra or objdump.
Pay special attention to the std::basic_string constructor calls and the subsequent comparisons before characters are appended.
wget https://artifacts.picoctf.net/c_titan/187/bin && \
chmod +x bin && \
objdump -D bin | lessSolution
- Step 1Map each DAT entryIn Ghidra, rename the DAT_ addresses (char_0, char_a, etc.) to their literal characters. This makes the later logic much easier to read.
Learn more
Ghidra is a free, open-source reverse engineering framework developed by the NSA. Its decompiler translates machine code back into pseudo-C, making binary analysis accessible without reading raw assembly. Ghidra can analyze binaries for x86, ARM, MIPS, PowerPC, and dozens of other architectures.
When Ghidra encounters global variables without debug symbols, it names them with their memory addresses:
DAT_00401234. Renaming variables to meaningful names is a core reverse engineering workflow. As you identify what each address holds (a character, a string, a counter), renaming it propagates throughout the decompiled view, transforming unreadable code into something approaching the original source.C++
std::basic_string(the backing type forstd::string) appears frequently in decompiled C++ output. The constructor calls are verbose in decompiled code because string construction involves memory allocation, length tracking, and null termination. Recognizing this pattern and focusing on what values are being appended - rather than the construction mechanics - is key to efficiently reading C++ reverse engineering output.This annotation workflow is the same technique used by professional malware analysts who reverse-engineer obfuscated code. Starting with the first few identifiable symbols (strings, API calls, magic constants), analysts build outward, renaming and retyping until the full picture becomes clear. Tools like IDA Pro and Binary Ninja offer similar renaming and retyping capabilities.
- Step 2Evaluate the conditionsWalk through the comparisons: '5' < 'B' succeeds so 'e' is appended, '6' != 'A' adds '9', the difference check fails, and the trailing lines append d a 2 c 0 e }.
Learn more
The binary builds the flag string conditionally by evaluating comparisons between character literals and appending different characters based on whether each comparison succeeds or fails. This is a classic obfuscation technique: instead of storing
"picoCTF{...}"as a plain string (visible withstrings), the binary assembles it at runtime through a series of conditional branches.Character comparisons in C use ASCII values.
'5'is 0x35 (53) and'B'is 0x42 (66), so'5' < 'B'is true. This numeric comparison approach means the outcome of each branch is predictable from the ASCII table - no runtime input is needed, making this static analysis sufficient to recover the flag without running the binary.This technique of hiding strings by building them character-by-character at runtime is widely used in malware to evade signature-based detection. Antivirus tools that scan for known bad strings won't find them if the strings are never stored completely in the binary. More advanced obfuscators XOR encode strings and decrypt them only when needed, requiring dynamic analysis to observe the decrypted values.
- Step 3ConcatenateCombine the hard-coded prefix picoCTF{...}.
Learn more
The flag prefix
picoCTF{wELF_d0N3_mate_contains a pun: ELF (Executable and Linkable Format) is the binary format used by Linux executables, shared libraries, and core dumps. "Well done, mate" becomes "wELF d0N3 mate" - a nod to the fact that you've successfully reversed an ELF binary.ELF files have a well-defined structure: an ELF header, program headers (segments for runtime loading), section headers (sections for linking), and the actual data. The
readelfcommand-line tool and tools likepwntools'ELF()class provide programmatic access to ELF internals - essential for binary exploitation and patching.The suffix
e9da2c0eis a hash-like value unique to your downloaded binary, as the flag note mentions. This per-instance randomization is a common CTF technique to prevent flag sharing between players - each download has a different suffix, so the answer you'd get may differ from others. It reinforces the importance of working through the analysis yourself rather than copying answers.Assembling the flag from static analysis demonstrates that you can recover secrets from a binary without ever running it. This is the essence of static reversing - useful when the binary is for a different architecture, requires unavailable hardware, or is suspected malware that you don't want to execute.
Flag
picoCTF{...}
Note that this flag will be different for you based on your downloaded binary.