← Back to Writeups
CUSTOMEasyReversing

Basic

XESXOR9/10/20262 min read
#reversing#custom#easy#base32_decoding#static_analysis#strings_analysis

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, stripped
  • checksec: Partial RELRO, Canary found, NX enabled, No PIE
  • strings reveals:
    • Base32 alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZ234567
    • Hardcoded target: IYYTIR27GE2V6QSBKNCV6T2GL5AU4WIK
    • Output strings: Correct! and NOT correct

These strings already suggest a simple encoded-string checker instead of a complicated obfuscated algorithm.

Reversing

main follows a short validation path:

  1. Read user input with fgets().
  2. Compute its length with strlen().
  3. Pass the buffer into the routine at 0x4006bd.
  4. Compare the produced string with strcmp() against the constant at 0x400940. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

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
IYYTIR27GE2V6QSBKNCV6T2GL5AU4WIK

Decoding it as Base32 gives:

text
REDACTED\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
#!/usr/bin/env python3
import base64

target = "IYYTIR27GE2V6QSBKNCV6T2GL5AU4WIK"
decoded = base64.b32decode(target).decode()

print(repr(decoded))
print("Visible input:", decoded.rstrip("\n"))

Output:

text
'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!. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍