Description
What's behind the numeric gate? You only get access if you enter the right kind of number. Download gatekeeper, reverse the numeric checks, and enter the value that passes.
Setup
chmod +x gatekeeper./gatekeeperSolution
Want to try it yourself first?
The guided walkthrough reveals hints one step at a time.
Step 1Run the binary
ObservationThere is a compiled binary and no source. Run it first: its prompts and error messages say what input it wants, before you commit to a disassembler.Execute gatekeeper and read the prompt. It asks for a number, and internally applies two separate checks to it: a length check on the string you typed and a value check on the number that string parses to.bash./gatekeeperWhat didn't work first
Tried: Running strings on the binary hoping to find the flag or the expected numeric value in plaintext.
strings prints readable text from the binary, and the flag is not in there: it is read from a server-side file at runtime. The threshold may show up as a constant, but without understanding the base conversion you still cannot craft the input.
Tried: Entering a normal 4-digit decimal number like 1000 to satisfy the 'greater than 999' check.
There is also a length check of exactly 3 characters, and 1000 in decimal is four. It fails the length gate and errors out before the numeric comparison runs at all. You need three characters that decode above 999.
Learn more
When approaching an unknown binary, always start by running it with normal input to understand its interface. The program's prompts, error messages, and exit codes give you immediate information about what it expects. In this case the binary asks for a number, which suggests it performs integer comparisons internally.
If the binary doesn't reveal enough from runtime behaviour, the next steps are static analysis (disassembling with
objdumpor Ghidra, or reading the source withstrings/cat) and dynamic analysis (running understraceto see system calls, orltraceto see library calls). For this challenge the vulnerability class (integer type confusion) is inferable from the prompt alone and confirmed quickly.Step 2Send a 3-digit hex number greater than 999 decimal
ObservationThe binary wants at most 3 characters and a value above 999, which no decimal integer satisfies at once. So the conversion must read hex, where three characters reach 1000 easily.The binary reads the input as a string, checks the string length must be 3, and separately converts it to a long integer that must be greater than 999. Run the binary and feed it a 3-character hex value like3e8(hex for 1000). The program accepts hex via strtol.bashecho '3e8' | ./gatekeeperWhat didn't work first
Tried: Sending '0x3e8' (with the 0x prefix) instead of bare '3e8' to make the hex value explicit.
The binary reads exactly three characters. '0x3e8' is five, so it truncates to '0x3', which parses as 3 in base 16, nowhere near the threshold. The prefix is unnecessary anyway, since the base is hardcoded to 16.
Tried: Trying strtol with base 0 and sending a string like '0x' prefix to auto-detect hex.
The disassembly shows the base argument fixed at 16, not 0. Auto-detection would need base 0, which the binary does not use. With 16 hardcoded, '3e8' parses correctly on its own, and a prefix would only consume part of your three characters.
Learn more
In Ghidra, the main function reads input with scanf using a
%3sformat (limiting to 3 characters). It then converts the string with a base-16 parse (e.g.strtol(input, NULL, 16)), so a bare 3-character hex string like3e8(no0xprefix needed) becomes 0x3e8 = 1000 decimal. The conversion must be base 16: with base 0,strtolwould treat3e8as decimal and stop at thee, yielding just 3. The binary checks two conditions: string length must be 3, AND the numeric value must be greater than 999.Hex digit strings like
3e8(3 characters) decode to 1000 decimal, satisfying both constraints simultaneously. The largest three-digit hex value,fff, is 4095, so any three hex characters from3e8upward pass the gate.Step 3Decode the reversed and obfuscated flag output
ObservationThe output scatters repeated picoCTF_ substrings through what looks like a scrambled flag. reveal_flag prints the flag backwards with that string spliced in at intervals, so strip it out, then reverse.The reveal_flag function prints the flag content in reverse order, with 'picoCTF_' (inserted forward by the function) interspersed every 4 characters. Strip the 'picoCTF_' occurrences from the raw output, then reverse the remaining string to get the real flag.bash# Copy the output from the binary, strip out the 'picoCTF_' interspersed textbash# Then reverse what remains to read the flagbashecho '<output>' | sed -e 's/picoCTF_//g' | revbash# Or: paste the output into Python and process itpythonpython3 -c "output = '<paste output here>'; print(output.replace('picoCTF_', '')[::-1])"Expected output
picoCTF{3_digit_hex_GT_999_...}What didn't work first
Tried: Reversing the raw binary output directly without first stripping the interspersed 'picoCTF_' substrings.
reveal_flag splices picoCTF_ in forward every four characters while printing the flag backwards, so reversing the raw output leaves those fragments scattered through it. Remove every occurrence first, then reverse.
Tried: Using strings on the binary output file or piping the binary's stdout directly to grep for the flag format.
The flag is never printed in its final form; it is interleaved and reversed as it goes. Grepping for the opening brace finds nothing, because that shape only exists after both transformations. Post-process the output rather than searching it.
Learn more
The
reveal_flagfunction in this binary opens the flag file and prints it backwards, inserting the string "picoCTF_" (forward) every 4 characters as additional obfuscation. To recover the real flag: strip the repeatedpicoCTF_interleaving and reverse the remaining characters.This two-layer obfuscation (reversal + interleaving) is a common CTF technique to prevent straightforward string extraction with
strings. The hint in the challenge description explicitly tells you to reverse the string and clean out extra text.
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.
- Hex ViewerView text or raw hex bytes as a xxd-style hex dump with byte offset, hex columns, and ASCII sidebar. Highlights printable characters and null bytes.
- Base64 & Base32 DecoderDecode Base64 and Base32 strings with auto-detection. Multi-layer mode unwraps nested encodings automatically.
Flag
Reveal flag
picoCTF{3_digit_hex_GT_999_...}
Send a 3-character hex value greater than 999 decimal (e.g. '3e8' = 1000). The flag output is reversed and obfuscated with interspersed 'picoCTF_' text - strip that and reverse to get the real flag.