← Back to Writeups
CUSTOMEasyReversing

s5.out

XESXOR9/2/20263 min read
#reversing#custom#easy#disassembly#forward_solving#recurrence_relation#static_analysis

s5.out

Platform: CUSTOM | Category: Reversing | Type: Challenge | Difficulty: Easy | OS: N/A | **Author: XESXOR Techniques: disassembly, forward_solving, recurrence_relation, static_analysis

Summary

Walkthrough of the CUSTOM Reversing s5.out. Task: 32-bit ELF serial validation crackme with recurrence relation. Solution: forward solve from known first character 'a' using input[i] = input[i-1] + i.

Description

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

A 32-bit ELF executable compiled from C++. Serial number validation crackme where the Check function uses a recurrence relation to validate characters.

Analysis

  1. File reconnaissance:

    • file s5.out shows: ELF 32-bit LSB executable, Intel 80386, dynamically linked, not stripped (7492 bytes)
    • s5.exe: PE32 executable (console) Intel 80386 (2048 bytes)
    • Key symbols from nm: main, _Z5Checkv (Check()), _Z7PrintOKv, _Z10PrintErrorv
    • Source file: s5.cpp ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍
  2. main() function analysis:

    • Prints "Enter serial number: "
    • Reads input via scanf("%s") into global buffer at 0x804a02c
    • Calls Check() function
    • If Check() returns true → calls PrintOK() which prints "Serial number is correct!"
    • If Check() returns false → calls PrintError() which prints "Error! Serial number is wrong!"
  3. Check() function disassembly (at 0x8048523):

c
bool Check() {
    int len = strlen(input) - 1;
    if (len != 6) return false;  // strlen must be 7
    
    if (input[0] != 0x61) return false;  // input[0] must be 'a'
    
    for (int i = 1; i < len; i++) {  // i = 1, 2, 3, 4, 5
        if (input[i] != input[i-1] + i) return false;
    }
    
    return true;
}

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

  1. Validation logic:
    • Length check: strlen(input) - 1 == 6, so string must be 7 characters
    • First character must be 'a' (ASCII 0x61 = 97)
    • Recurrence relation: each character equals previous character plus current index
    • Loop runs for i = 1 to 5 (position 6 is unchecked)

Solution

Forward solve from the known first character using the recurrence relation:

python
#!/usr/bin/env python3
"""
s5.out Check function:
  len = strlen(input) - 1
  if len != 6: fail  (so strlen == 7, string is 7 chars)
  if input[0] != 'a': fail
  for i in range(1, len):  # i = 1..5
    if input[i] != input[i-1] + i: fail
  return true
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Position 6 is unchecked by the loop.
"""

serial = [0] * 7
serial[0] = ord('a')  # 97

for i in range(1, 6):
    serial[i] = serial[i-1] + i

# Position 6 - not checked, but continuing the pattern
serial[6] = serial[5] + 6

result = ''.join(chr(c) for c in serial)
print(f"Serial: {result}")

# Verification
print(f"\nVerification:")
for i in range(1, 7):
    print(f"  serial[{i}]({serial[i]}='{chr(serial[i])}') == serial[{i-1}]({serial[i-1]}='{chr(serial[i-1])}') + {i} = {serial[i-1]+i}")

Computation table: ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

IndexCalculationASCIICharacter
0given97'a'
197 + 198'b'
298 + 2100'd'
3100 + 3103'g'
4103 + 4107'k'
5107 + 5112'p'
6112 + 6118'v'

Position 6 is unchecked by the loop (loop condition is i < 6), but continuing the arithmetic pattern gives 'v'.

Verification:

$ echo "REDACTED" | ./s5.out
Enter serial number: Serial number is correct!

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

Key Takeaways / Lessons

  • Mastering disassembly, forward_solving, recurrence_relation, static_analysis was key to this challenge.
  • Always check for common misconfigurations and verify assumptions.

Crafted by XESXOR Research • 2026-03-25 • CUSTOM • s5.out • Difficulty: Easy