← Back to Writeups
CUSTOMEasyReversing

s6.out

XESXOR9/2/20262 min read
#reversing#custom#easy#character_by_character_validat#position_mapping#static_disassembly

s6.out

Platform: CUSTOM | Category: Reversing | Type: Challenge | Difficulty: Easy | OS: N/A | **Author: XESXOR Techniques: character_by_character_validation, position_mapping, static_disassembly

Summary

Walkthrough of the CUSTOM Reversing s6.out. A 32-bit ELF binary (also provided as PE32 for Windows). Serial number validation crackme compiled from C++. The goal is to find a valid serial number which serves as the flag.

Description

Language: C. Download binary: s6.out (ELF 32-bit) or s6.exe (PE32). Flag is the correct serial number.

A 32-bit ELF binary (also provided as PE32 for Windows). Serial number validation crackme compiled from C++. The goal is to find a valid serial number which serves as the flag.

Analysis

  1. File reconnaissance:

    • file s6.out shows: ELF 32-bit LSB executable, Intel 80386, dynamically linked, not stripped (7476 bytes)
    • s6.exe: PE32 executable (console) Intel 80386 (2560 bytes)
    • Not stripped — function names visible: main, _Z5CheckPc (Check(char*)), _Z7PrintOKi, _Z10PrintErrori ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍
  2. Main function analysis:

    • Prints "Enter serial number: "
    • Reads up to 11 bytes (0xb) via fgets from stdin
    • Calls Check(input)
  3. Check function analysis: The Check function uses a counter (ebx=0) and performs 6 independent character comparisons:

    • First: strlen(input) must be > 6 (at least 7 characters), otherwise all checks are skipped
    • Six character checks (each increments counter if match):
      • input[3] == 0x77 ('w')
      • input[6] == 0x44 ('D')
      • input[5] == 0x33 ('3')
      • input[2] == 0x46 ('F')
      • input[1] == 0x32 ('2')
      • input[4] == 0x31 ('1')
    • Final check: counter must equal 6 (all checks passed)
    • Calls PrintOK(result) and PrintError(!result) ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍
  4. Key observation: Position 0 (first character) is never checked! The serial must be 7+ characters where positions 1-6 match specific values. Position 0 can be any character.

Solution

Reconstructing the serial by position:

  • [0] = ? (unchecked — any character works)
  • [1] = '2' (0x32)
  • [2] = 'F' (0x46)
  • [3] = 'w' (0x77)
  • [4] = '1' (0x31)
  • [5] = '3' (0x33)
  • [6] = 'D' (0x44)

Valid serial: ?2Fw13D where ? is any character.

python
#!/usr/bin/env python3
"""
s6.out serial keygen - rev-kids20
The Check function validates positions 1-6, position 0 is unchecked.
"""
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

# Character requirements from disassembly
checks = {
    1: 0x32,  # '2'
    2: 0x46,  # 'F'
    3: 0x77,  # 'w'
    4: 0x31,  # '1'
    5: 0x33,  # '3'
    6: 0x44,  # 'D'
}

# Build serial (position 0 can be anything)
serial = ['A']  # Any character for position 0
for i in range(1, 7):
    serial.append(chr(checks[i]))

result = ''.join(serial)
print(f"Serial: {result}")
# Output: REDACTED

Verification:

bash
$ echo "REDACTED" | ./s6.out
Enter serial number: 
OK

$ echo "X2Fw13D" | ./s6.out
Enter serial number: 
OK

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Key Takeaways / Lessons

  • Mastering character_by_character_validation, position_mapping, static_disassembly was key to this challenge.
  • Always check for common misconfigurations and verify assumptions.

Crafted by XESXOR Research • 2026-03-23 • CUSTOM • s6.out • Difficulty: Easy