← Back to Writeups
CUSTOMMediumReversing

Adooha

XESXOR9/2/20263 min read
#reversing#custom#medium#crc32_verification#data_table_analysis#static_analysis#xor_decryption

Adooha

Platform: CUSTOM | Category: Reversing | Type: Challenge | Difficulty: Medium | OS: N/A | **Author: XESXOR Techniques: crc32_verification, data_table_analysis, static_analysis, xor_decryption

Summary

Walkthrough of the CUSTOM Reversing Adooha. Task: 64-bit stripped ELF with CRC32 validation table and XOR-encrypted flag. Solution: identify 50 valid indices via CRC32 matching, use sorted indices as XOR key to decrypt flag.

Description

Pass all checks, and app will give you the flag. Note: Old 32-bit binary does not accept correct input. New 64-bit does.

A 64-bit stripped ELF binary that requires specific numeric input to pass validation checks and reveal the flag. The binary contains a data table with 100 entries, but only 50 have valid CRC32 checksums.

Analysis

Binary Information

  • adooha64.elf: ELF 64-bit LSB executable, x86-64, dynamically linked, stripped
  • URL: https://rev-kids20.forkbomb.ru/files/rev/re3/adooha64.elf ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Strings Analysis

Key strings found in the binary:

  • Error messages: "You gave me the shit", "You gave me unsorted shit", "Give me more numbers", "You still trying to drown me in the shit"
  • Input format: %1024s — reads a string up to 1024 characters
  • Delimiter: "123456789"
  • Two suspicious encrypted strings at the end of .rodata: "fmccZn{R$%!u$-t.~+-~" and "[rzqry(kjmqrx}|~@" — XOR-encrypted flag parts

Data Table Structure

At address 0x6020c0: 100 entries, each containing:

  • Pointer to a 20-character alphanumeric string
  • Pointer to an 8-character hex CRC32 value
  • Entry 0 is the delimiter "123456789" ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Validation Logic

  1. Program reads input as numbers separated by the delimiter "123456789" (using strtok + strtol)
  2. Expects exactly 50 numbers, sorted in ascending order
  3. For each number (used as index into the table), computes CRC32 of the corresponding 20-char string and compares it with the stored hex CRC32 value
  4. Only 50 out of 100 entries have matching CRC32 values (the other 50 are intentionally wrong — traps)

Flag Decryption

  • Encrypted flag stored at 0x602080 (50 bytes total, the two suspicious strings concatenated)
  • Each byte is XORed with the corresponding sorted valid index number
  • This produces the plaintext flag ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Solution

python
#!/usr/bin/env python3
"""
Adooha solver - spbctf
Finds valid indices via CRC32 verification and decrypts the flag
"""
import binascii

# Data extracted from binary analysis
# 100 entries: (20-char string, expected CRC32 hex)
data_table = [
    # Entry 0 is delimiter "123456789"
    # Entries 1-99 are the actual data
    # ... (extracted from binary)
]

# Encrypted flag bytes (from .rodata at 0x602080)
encrypted_flag = bytes([
    # "fmccZn{R$%!u$-t.~+-~" + "[rzqry(kjmqrx}|~@"
    0x66, 0x6d, 0x63, 0x63, 0x5a, 0x6e, 0x7b, 0x52, 0x24, 0x25,
    0x21, 0x75, 0x24, 0x2d, 0x74, 0x2e, 0x7e, 0x2b, 0x2d, 0x7e,
    0x5b, 0x72, 0x7a, 0x71, 0x72, 0x79, 0x28, 0x6b, 0x6a, 0x6d,
    0x71, 0x72, 0x78, 0x7d, 0x7c, 0x7e, 0x40,
    # ... remaining bytes
])
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

def crc32(data):
    """Calculate CRC32 of data"""
    return binascii.crc32(data.encode()) & 0xffffffff

def find_valid_indices():
    """Find indices where computed CRC32 matches stored value"""
    valid = []
    for i, (string, expected_crc_hex) in enumerate(data_table):
        if i == 0:  # Skip delimiter entry
            continue
        computed = crc32(string)
        expected = int(expected_crc_hex, 16)
        if computed == expected:
            valid.append(i)
    return sorted(valid)
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

def decrypt_flag(valid_indices, encrypted):
    """XOR encrypted flag with sorted valid indices"""
    flag = ""
    for i, idx in enumerate(valid_indices):
        if i < len(encrypted):
            flag += chr(encrypted[i] ^ idx)
    return flag

# Main solution
valid_indices = find_valid_indices()
print(f"Found {len(valid_indices)} valid indices: {valid_indices}")

# Generate input string for the binary
delimiter = "123456789"
input_string = delimiter.join(str(i) for i in valid_indices)
print(f"Input: {input_string}")
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# Decrypt flag
flag = decrypt_flag(valid_indices, encrypted_flag)
print(f"Flag: {flag}")
# REDACTED

Approach Summary

  1. Extract the data table (100 entries of string + CRC32 pairs) from the binary
  2. Compute CRC32 for each 20-char string and compare with stored value
  3. Collect the 50 indices where CRC32 matches (valid entries)
  4. Sort the valid indices in ascending order
  5. XOR each byte of the encrypted flag with the corresponding sorted index
  6. Result: REDACTED ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Key Takeaways / Lessons

  • Mastering crc32_verification, data_table_analysis, static_analysis, xor_decryption was key to this challenge.
  • Always check for common misconfigurations and verify assumptions.

Crafted by XESXOR Research • 2026-03-26 • CUSTOM • Adooha • Difficulty: Medium