0xF20B
0xF20B
Platform: CUSTOM | Category: Reversing | Type: Challenge | Difficulty: Easy | OS: N/A | **Author: XESXOR Techniques: import_table_analysis, memfrob_inversion, stack_constant_recovery, xor_0x2a
Summary
Walkthrough of the CUSTOM Reversing 0xF20B. Task: 32-bit stripped PIE ELF flag checker. memfrob in the import table obfuscates input with XOR 0x2A before comparing to a stack-built constant. Solution: recover the 27-byte target via radare2 and
Description
How did I hide the flag? >:-)
A 32-bit PIE ELF 0xF20B.elf (Intel 80386, dynamically linked, stripped). It prints
Enter flag to check: , reads a string, and answers either Correct! Submit as the flag.
or Wrong.. The flag is submitted to the platform (rev-kids20.forkbomb.ru) via POST flag.
Goal: recover the input that makes the checker print "Correct!".
Analysis
file confirms a 32-bit Intel 80386 PIE, dynamically linked and stripped. Since it is
stripped, there are no symbols for main, so analysis is done in radare2:
r2 -A 0xF20B.elf
afl # list functions, identify entry → main
pdf @ main # disassemble main
ii # list imports
The giveaway is in the import table: the binary imports glibc's memfrob.
memfrob(buf, n) XORs each of n bytes with 0x2A (42) — and it is its own inverse
(applying it twice returns the original). The title "0xF20B" and the taunt
"how did I hide the flag?" both point straight at this trivial XOR obfuscation
(FROBNICATE is exactly what memfrob does).
main builds a 27-byte target constant byte-by-byte on the stack
(mov byte [var_124h..], 0x5d/0x42/...), then:
scanf("%s", input)strlen(input)memfrob(input, len)— XORs each input byte with0x2Astrcmp(target, frobbed_input)→ equal means "Correct!"
The 27 target bytes recovered from the stack stores:
5d 42 1e 1d 75 5e 42 19 75 62 19 66 66 75 43 59 75 6c 78 1a 68 64 1b 69 6b 7e 6f
Solution
The check is memfrob(input) == target. Because memfrob is XOR with 0x2A and
self-inverse, the correct flag is simply memfrob(target) = each target byte XOR 0x2A.
No need to run the binary at all:
python read-only • copy allowed#!/usr/bin/env python3 target = [0x5d,0x42,0x1e,0x1d,0x75,0x5e,0x42,0x19,0x75,0x62,0x19,0x66,0x66, 0x75,0x43,0x59,0x75,0x6c,0x78,0x1a,0x68,0x64,0x1b,0x69,0x6b,0x7e,0x6f] flag = ''.join(chr(b ^ 0x2A) for b in target) print(flag) # REDACTED
Output: REDACTED — reads as "what the HELL is FROBNICATE".
The platform accepted both the bare value and the flag{...} wrapped form.
Key Takeaways / Lessons
- Mastering import_table_analysis, memfrob_inversion, stack_constant_recovery, xor_0x2a was key to this challenge.
- Always check for common misconfigurations and verify assumptions.
Crafted by XESXOR Research • 2026-06-15 • CUSTOM • 0xF20B • Difficulty: Easy