RE4 what
RE4 what
Platform: CUSTOM | Category: Reversing | Type: Challenge | Difficulty: Easy | OS: N/A | **Author: XESXOR Techniques: little_endian_reconstruction, magic_constant_extraction, partial_strncmp_compare, static_analysis
Summary
Walkthrough of the CUSTOM Reversing RE4 what. Task: 64-bit non-stripped ELF that reads an integer then a string, validates the flag via a 20-byte strncmp plus a hidden dword check. Solution: extract the .rodata prefix 'flag_cafe_0129837465' and a
Description
Enter some number and some string. Valid string is the flag
A 64-bit ELF what.elf is given (not stripped, non-PIE, base 0x400000). The
flag is the string that passes the binary's validation. It is submitted to the
platform via POST flag.
Analysis
Disassembly of main (0x4006fd) reveals a simple but two-staged input flow:
buf = malloc(0x1c)— a 28-byte buffer.scanf("%d\n", buf)(format at0x400854is"%d\n") reads an integer into the first dword ofbuf(buf[0..3]).- That integer is then loaded into
eaxand used as the size limit forfgets(buf+4, eax, stdin)— i.e. the number you type controls how many bytes of the stringfgetswill read. strncmp(buf+4, "flag_cafe_0129837465", 0x14)compares the first 20 bytes of the string to the constant at0x400858. Mismatch → prints"Nope!1"(0x40086d) and returns.- On match:
printf("%x\n", *(uint*)(buf+0x18))prints the dword atbuf+0x18, thencmp eax, 0x61626364. Equal →"OK!"(0x400878), otherwise"Nope!"(0x40087c).
Key offset reasoning: the string lives at buf+4. buf+0x18 = buf+24, which is
offset 20..23 of the string — the four bytes immediately after the 20-byte
prefix. The check cmp eax, 0x61626364 compares that dword to a magic constant.
Because x86-64 is little-endian, the dword 0x61626364 in memory is the byte
sequence 0x64, 0x63, 0x62, 0x61 = 'd', 'c', 'b', 'a' = the ASCII string
"dcba".
.rodata strings
| Offset | String |
|---|---|
0x400854 | "%d\n" |
0x400858 | "flag_cafe_0129837465" |
0x40086d | "Nope!1" |
0x400874 | "%x\n" |
0x400878 | "OK!" |
0x40087c | "Nope!" |
| |
Solution
To reach the "OK!" branch the string must:
- Begin with the 20-byte prefix
flag_cafe_0129837465(satisfiesstrncmp). - Have its bytes at offset 20..23 equal
0x61626364little-endian ="dcba".
So the full valid flag is the prefix plus the "dcba" suffix:
REDACTED
The integer entered first must be large enough for fgets to read all 24+ bytes
of the string (e.g. 30).
Runtime confirmation
bash read-only • copy allowed# Run under linux/amd64 (e.g. Docker on Apple Silicon) printf '30\nREDACTED\n' | ./what.elf # Output: # 61626364 # OK!
The printed 61626364 is exactly the dword read at buf+0x18, confirming the
suffix bytes line up with the magic constant.
Reconstruction snippet
python read-only • copy allowed#!/usr/bin/env python3 import struct prefix = "flag_cafe_0129837465" # from .rodata @0x400858 (20 bytes, strncmp len 0x14) magic = 0x61626364 # cmp eax, 0x61626364 suffix = struct.pack("<I", magic).decode() # little-endian -> "dcba" print(prefix + suffix) # REDACTED
Note: the platform rejected the prefix-only string flag_cafe_0129837465 (which
only satisfies the strncmp). The accepted flag is the full valid string
including the dcba suffix that triggers the final OK! branch.
Key Takeaways / Lessons
- Mastering little_endian_reconstruction, magic_constant_extraction, partial_strncmp_compare, static_analysis was key to this challenge.
- Always check for common misconfigurations and verify assumptions.
Crafted by XESXOR Research • 2026-06-15 • CUSTOM • RE4 what • Difficulty: Easy