Basic
Basic
Platform: spbctf | Category: Reversing | Type: Challenge | Difficulty: Easy | OS: NA | Author: XESXOR | Date: 2026-03-26 | Status: Solved Techniques: base32_decoding, static_analysis, strings_analysis
Summary
Task: a stripped 64-bit ELF accepts input and prints Correct! only for one exact string. Solution: identify the custom routine as a Base32 encoder, decode the embedded target string, and account for the newline kept by fgets.
Basic — spbctf
Description
Flag is the input that makes the app say 'Correct'
The binary asks for input, transforms it, and compares the transformed result against a hardcoded string. The goal is to recover the original input that produces the expected encoded value.
Summary
The important clue is in strings: the binary contains the standard Base32 alphabet and a fixed target string IYYTIR27GE2V6QSBKNCV6T2GL5AU4WIK. Static analysis shows main reads input with fgets(), passes it to a custom encoder, and compares the encoder output with strcmp(). Decoding the target as Base32 yields REDACTED\n, so the intended visible input is REDACTED followed by pressing Enter.
Recon
file: ELF 64-bit LSB executable, x86-64, dynamically linked, strippedchecksec: Partial RELRO, Canary found, NX enabled, No PIEstringsreveals:- Base32 alphabet:
ABCDEFGHIJKLMNOPQRSTUVWXYZ234567 - Hardcoded target:
IYYTIR27GE2V6QSBKNCV6T2GL5AU4WIK - Output strings:
Correct!andNOT correct
- Base32 alphabet:
These strings already suggest a simple encoded-string checker instead of a complicated obfuscated algorithm.
Reversing
main follows a short validation path:
- Read user input with
fgets(). - Compute its length with
strlen(). - Pass the buffer into the routine at
0x4006bd. - Compare the produced string with
strcmp()against the constant at0x400940.
The routine at 0x4006bd is a custom Base32 encoder. Its logic extracts 5-bit chunks from the input and uses the alphabet ABCDEFGHIJKLMNOPQRSTUVWXYZ234567 for lookup. Since the compared value is hardcoded, there is no need to reimplement the whole binary: just decode the constant.
The target string is:
text read-only • copy allowedIYYTIR27GE2V6QSBKNCV6T2GL5AU4WIK
Decoding it as Base32 gives:
text read-only • copy allowedREDACTED\n
The trailing newline matters because fgets() keeps it when the user presses Enter. So the actual terminal input is the visible string REDACTED, and the binary receives REDACTED\n internally.
Solution
Minimal recovery script:
python read-only • copy allowed#!/usr/bin/env python3 import base64 target = "IYYTIR27GE2V6QSBKNCV6T2GL5AU4WIK" decoded = base64.b32decode(target).decode() print(repr(decoded)) print("Visible input:", decoded.rstrip("\n"))
Output:
text read-only • copy allowed'REDACTED\n' Visible input: REDACTED
Verification is straightforward: run the binary, enter REDACTED, and press Enter. Because of fgets(), the newline is included, the encoded value matches the hardcoded Base32 string, and the program prints Correct!.