Description
A heavily bloated binary makes static analysis tedious - there are many irrelevant functions. But it boils down to one integer comparison: find the magic value and enter it as input.
Ghidra quickly identifies the magic constant in main() even through all the bloat.
Setup
Download the binary and make it executable.
Open in Ghidra (or run in the picoCTF web shell), find main(), and read the integer comparison.
wget https://artifacts.picoctf.net/c/172/bbbbloat && chmod +x bbbbloatSolution
Want to try it yourself first?
The guided walkthrough reveals hints one step at a time.
Step 1Identify the magic constant in Ghidra
ObservationThe binary is called bbbbloat and the description warns about heavy bloat, so manual inspection will drown. Ghidra is the reliable route: trace the scanf input forward to the one integer comparison in main() and the magic constant falls out.Open the binary in Ghidra, navigate to the main function, and look for where your scanned input is compared to a constant. The comparison isif (input == 0x86187). In decimal that is 549255.bashwget https://artifacts.picoctf.net/c/172/bbbbloat && chmod +x bbbbloatbash# Open in Ghidra, run auto-analysis, find main(), read the if-check valueExpected output
picoCTF{cu7_7h3_bl047_695...}What didn't work first
Tried: Run 'strings bbbbloat | grep picoCTF' hoping to find the flag or the magic number without opening Ghidra.
strings extracts printable ASCII and will never turn the constant 0x86187 into a usable hint, since it lives as raw bytes rather than a labelled comparison. Ghidra's decompiler traces the data flow from scanf to the cmp instruction and shows the constant in context.
Tried: Grep every function in Ghidra for 'if' statements rather than tracing input flow forward from the scanf call.
The bloat functions hold dozens of branches that never touch user input, so auditing them at random burns time. Start at the scanf call, find the variable it writes to, and follow that variable. Ghidra's find-references on it goes straight to the one comparison that matters.
Learn more
The binary uses
scanfto read an integer from the user and then compares it against a hardcoded constant. All the surrounding function calls are irrelevant bloat that does not affect the outcome. Ghidra's decompiler folds through constant propagation and shows the comparison plainly once you find main().Hex to decimal:
0x86187= 8*65536 + 6*4096 + 1*256 + 8*16 + 7 = 549255. In Ghidra, right-click the hex constant in the decompiler and pick "Convert to Decimal" to avoid doing the arithmetic by hand.Heuristic for spotting bloat in the decompiler: long chains of nested function calls whose return value is discarded; loops with no observable side effect; functions that rebuild data they already have. Skip past those and look at where the input flows:
scanfto a variable to acmp. Trace forward from the input read; ignore everything else.Step 2Enter the magic value to get the flag
ObservationGhidra shows a hardcoded 0x86187 compared straight against user input. Convert that to decimal, 549255, pipe it into the binary, and the comparison passes.Run the binary normally and enter 549255 (0x86187) when prompted. It prints the flag.bashecho '549255' | ./bbbbloatWhat didn't work first
Tried: Enter the hex value 0x86187 directly at the prompt instead of the decimal equivalent 549255.
The binary reads input with a decimal format specifier, so it parses '0x86187' as the number 0 rather than 549255, the comparison fails, and it takes the wrong-answer path. Convert the hex constant from Ghidra into decimal before you type it.
Tried: Run the binary without piping input and type the value interactively, then copy the flag from the terminal - but accidentally enter a space or newline before the digits.
scanf skips leading whitespace, but a stray non-digit character leaves the buffer in a bad state and the read returns 0 or the previous value. Piping the number in with echo feeds exactly the right bytes and one trailing newline, which removes the interactive mistakes entirely.
Learn more
Piping the value directly via
echo 'VALUE' | ./binaryis a quick way to automate providing input without interactive prompts. The binary reads from stdin, and the pipe connects stdout of echo to stdin of the binary.This challenge teaches that code complexity (bloat) is not the same as security. True security requires cryptographic key material or secrets that cannot be recovered from static analysis - not just confusing code structure. A hardcoded comparison value is always recoverable with Ghidra.
Interactive tools
- Strings ExtractorPull printable text from any binary, library, or image. ASCII and UTF-16 detection, configurable minimum length, flag-like highlight, no command line needed.
Flag
Reveal flag
picoCTF{cu7_7h3_bl047_695...}
Ghidra reveals the magic comparison value (549255 / 0x86187). Enter it when prompted and the binary prints the flag.