Challenge Information
- Challenge Name: Gatekeeper
- Points: 100
- Author: Yahaya Meddy
- Description: What's behind the numeric gate? You only get access if you enter the right kind of number. Reverse the program behavior and find what input grants access to the secret flag.
- Connection:
nc green-hill.picoctf.net 54458
Solution Overview
The Gatekeeper challenge required reverse engineering a binary executable to find the correct numeric input that would grant access to a hidden flag. The solution involved analyzing the binary's logic, understanding its input validation, and crafting the correct input format.
Tools Used
file- To identify the binary typestrings- To extract readable strings from the binaryobjdump- To disassemble and analyze the binarync(netcat) - To connect to the remote server- Basic shell commands for testing and analysis
Step-by-Step Solution
1. Initial Analysis
First, I examined the provided binary file:
file gatekeeper
# Output: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked
The binary was a 64-bit Linux executable that was not stripped, making reverse engineering easier.
2. Behavioral Testing
I tested the binary's behavior with different inputs:
./gatekeeper
# Enter a numeric code (must be > 999 ): 56
# Too small.
echo "123456" | ./gatekeeper
# Enter a numeric code (must be > 999 ): Too high.
This revealed that the program accepts numeric input and validates it against certain constraints.
3. String Analysis
I extracted strings from the binary to look for clues:
strings gatekeeper | grep -E "(flag|pico|correct|access|secret)"
# Output: /flag.txt, reveal_flag
This indicated the program reads a flag from /flag.txt and has a reveal_flag function.
4. Assembly Analysis
The key breakthrough came from analyzing the assembly code:
objdump -d gatekeeper | grep -A 10 -B 10 "cmp\|test\|jne\|je"
Key findings from the assembly:
- The program accepts both decimal and hexadecimal numbers
- It checks if the number > 999 (0x3e7 = 999)
- It checks if the number ≤ 9999 (0x270f = 9999)
- Critical discovery: It checks if the input string length is exactly 3 characters
- If all conditions pass, it calls the
reveal_flagfunction
5. Logic Deduction
From the analysis, I deduced the requirements:
- Input must be a valid number (decimal or hexadecimal)
- The numeric value must be > 999 and ≤ 9999
- The input string must be exactly 3 characters long
This meant I needed to use hexadecimal format, since "1000" (4 characters) wouldn't work, but "3e8" (3 characters, hex for 1000) would.
6. Local Testing
I tested the solution locally:
echo "3e8" | ./gatekeeper
# Enter a numeric code (must be > 999 ): Flag file not found.
The "Flag file not found" message instead of "Access Denied" confirmed I had bypassed the security checks.
7. Remote Exploitation
I connected to the remote server:
nc green-hill.picoctf.net 54458
# Enter a numeric code (must be > 999 ): 3e8
# Access granted: }e16ftc_oc_ipfff5ftc_oc_ipe_99ftc_oc_ip9_TGftc_oc_ip_xehftc_oc_ip_tigftc_oc_ipid_3ftc_oc_ip{FTCftc_oc_ipocipftc_oc_ip
8. Flag Extraction
The flag was printed with "ftc_oc_ip" inserted between characters. I extracted and cleaned it:
echo "3e8" | nc green-hill.picoctf.net 54458 | sed 's/.*Access granted: //' | sed 's/ftc_oc_ip//g' | tr -d '\n' | rev
# Output: picoCTF{3_digit_hex_GT_999_e5fff61e}
Key Insights
- String Length Constraint: The 3-character length requirement was the crucial constraint
- Hexadecimal Input: Using hex representation allowed meeting both the value (>999) and length (3 chars) requirements
- Flag Obfuscation: The flag was printed with repeated "ftc_oc_ip" strings inserted between characters
- Reversed Order: The flag characters were in reverse order
Final Answer
Flag: picoCTF{3_digit_hex_GT_999_e5fff61e}
Lessons Learned
- Always check multiple constraints in reverse engineering challenges
- String length can be as important as numeric value
- Assembly analysis can reveal critical logic not visible in behavioral testing
- Flag obfuscation techniques may require additional processing steps