RE4_JoeFain
RE4_JoeFain
Platform: rev_kids20 | Category: Reversing | Type: Challenge | Difficulty: Easy | OS: Windows | Author: XESXOR | Date: 2026-06-15 | Status: Solved Techniques: arithmetic_reconstruction, diophantine_system_solving, scanf_argument_order_analysis, trivial_root_recognition
Summary
Task: 32-bit PE32 console binary reads two integers via scanf and checks two integer polynomial constraints; flag is the input without spaces. Solution: reconstruct the two polynomials from radare2 disassembly, determine scanf argument order from cdecl push order, and solve the Diophantine system (sympy) to get the non-trivial root (a=-5, b=4) -> input '4 -5' -> flag 'REDACTED'.
RE4_JoeFain — rev_kids20
Description
Flag is your input without spaces
English summary: A 32-bit PE32 console executable JoeFain.exe (Intel 80386, MS Windows) prints
Input complex number: >, reads two integers with scanf("%d %d"), evaluates two integer
polynomial expressions of those inputs, and prints You are welcome! on success or
Go out of here! otherwise. The flag is the accepted input with spaces removed.
Analysis
file JoeFain.exe → PE32 executable, Intel 80386, console subsystem.
Disassembling main with radare2 reveals:
-
scanf("%d %d", &v1, &v2)is called. Under cdecl, arguments are pushed right-to-left, so the push order maps the FIRST typed number tov2(kept inebx, call itb) and the SECOND typed number tov1(kept inecx, call ita). -
Two integer polynomial expressions are computed from
(a, b)via the usualimul/lea/neg/shlarithmetic sequences:edx = (b*b - a*a - 1) - 5*b - 6*a eax = 2*a*b - 5*a + 6*b - 9
- A special-case guard: if
b == 1ANDa == -1, the program printsAlmost. But the root is too simple.— this deliberately rejects the trivial root of the system. - Success (
You are welcome!) requiresedx == 0ANDeax == 0.
So we must satisfy the system while avoiding the rejected trivial root.
Solution
Solve the integer system:
b*b - a*a - 1 - 5*b - 6*a == 0
2*a*b - 5*a + 6*b - 9 == 0
python read-only • copy allowed#!/usr/bin/env python3 from sympy import symbols, Eq, solve a, b = symbols('a b', integer=True) sols = solve( [Eq(b*b - a*a - 1 - 5*b - 6*a, 0), Eq(2*a*b - 5*a + 6*b - 9, 0)], [a, b], ) print(sols) # [(-5, 4), (-1, 1)]
Two integer solutions exist:
(a=-1, b=1)— the trivial root, explicitly rejected by the binary.(a=-5, b=4)— the valid root.
Recall the scanf order: FIRST number = b = 4, SECOND number = a = -5.
So the input is 4 -5. The flag is the input without spaces: REDACTED.
A quick brute-force confirmation instead of sympy:
python read-only • copy allowedfor a in range(-50, 51): for b in range(-50, 51): if (b*b - a*a - 1 - 5*b - 6*a) == 0 and (2*a*b - 5*a + 6*b - 9) == 0: print(a, b) # (-5, 4) and (-1, 1)
The "complex number" framing hints the two integers are the real/imaginary
parts; concatenating them without the separating space yields the flag.
The challenge also accepted equivalent encodings (-54, 4,-5, -5,4), but
the canonical answer is REDACTED.