← Back to Writeups
CUSTOMEasyReversing

Puzzle

XESXOR9/2/20263 min read
#reversing#custom#easy#static_analysis#constraint_solving#diophantine_equation#md5_flag_derivation

Puzzle

Platform: CUSTOM | Category: Reversing | Type: Challenge | Difficulty: Easy | OS: N/A | **Author: XESXOR Techniques: static_analysis, constraint_solving, diophantine_equation, md5_flag_derivation

Summary

Walkthrough of the CUSTOM Reversing Puzzle. Task: 32-bit stripped ELF reads three integers and validates them against two linear equations plus positivity, then prints flag as MD5 of the concatenated counts. Solution: recover the constraints fr

Description

Input number of students to solve python tasks: Input number of students to solve php tasks: Input number of students to solve c++ tasks: Welldone! The flag is flag{md5}, where md5 is MD5 of concatenation (python_count, php_count, cpp_count)!

puzzle is a 32-bit stripped ELF (Intel 80386, dynamically linked, GCC Debian 6.3.0). It reads three integers via scanf("%d") — the number of students solving python, php, and c++ tasks — validates them, and on success prints the flag derived from the counts. The goal is to find the counts that pass validation. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Analysis

Disassembly of main (radare2: aaa; s main; pdf) shows a set of local constants and validation checks.

Constants set at function start:

LocalValueRole
var_ch100 (0x64)sum target
var_10h400 (0x190)weighted-sum target
var_14h60 (0x3c)coefficient for python
var_18h4coefficient for php
var_1ch1coefficient for c++

Inputs: python = var_120h, php = var_124h, cpp = var_128h. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Validation (all must hold, else it prints Error):

  1. python + php + cpp == 100
  2. python > 0
  3. php > 0
  4. cpp > 0
  5. 60*python + 4*php + 1*cpp == 400

This is the classic "100 birds for 100 coins" linear Diophantine puzzle: two equations plus positivity constraints.

On success the binary prints: flag{md5} where md5 = MD5( str(python) + str(php) + str(cpp) ) — the decimal-string concatenation of the three counts, not their numeric sum. Ordering therefore matters.

Solution

Subtracting equation (1) from (5) eliminates cpp: 59*python + 3*php = 300. With positivity, brute force yields a single solution. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

python
#!/usr/bin/env python3
import hashlib
for p in range(1, 101):
    for h in range(1, 101):
        c = 100 - p - h
        if c <= 0:
            continue
        if 60 * p + 4 * h + c == 400:
            s = f"{p}{h}{c}"
            print(s, "flag{" + hashlib.md5(s.encode()).hexdigest() + "}")

Output:

34156 flag{REDACTED}

The unique solution is python = 3, php = 41, cpp = 56. The concatenation "3" + "41" + "56" = "34156", and MD5("34156") = REDACTED.

No native execution was needed (32-bit i386 binary, no qemu-i386 on the host) — the constraint logic is fully deterministic from the disassembly. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Key Takeaways / Lessons

  • Mastering static_analysis, constraint_solving, diophantine_equation, md5_flag_derivation was key to this challenge.
  • Always check for common misconfigurations and verify assumptions.

Crafted by XESXOR Research • 2026-07-01 • CUSTOM • Puzzle • Difficulty: Easy