* docs(website): add a worked CTF reverse-engineering showcase * docs(website): add a dedicated FAQ page
7.5 KiB
DownUnderCTF masked-squares evidence
Fresh inspection and process captures on 8 October 2026, using the published REA 4.1.0 package with Ghidra 12.1.4 on Linux x64. The challenge is masked squares flag checker, by joseph, tagged easy in the official DownUnderCTF 2023 repository.
Target
- Original handout:
publish/ms_flag_checker, stripped Linux x86-64 ELF. - Size: 15,248 bytes.
- SHA-256:
dcd3bec4f608e11f3a12ce461100aaf5f621851ee63a1f870d7c90d4e3dd51ae. - Upstream revision:
b48f83db2984bc7fa2ec7879a32d7efb1be8d333. - Git blob:
af95d9e109b5b700b3285e7e9f3b341dc716d34a. - REA analysis-profile digest:
7cb87eeb3886b20e336087d762d35caac496279cf9839dcc5e741b973627c1ba.
The original challenge was downloaded from GitHub's contents API and decoded from its base64 representation. The decoded length matches the API's size; REA's target digest matches the downloaded bytes. The byte digest was checked again after analysis and execution. The page links to the original handout; the executable is not copied into the website.
The supplied AGENTS.md and website writing/design guidelines were followed in an isolated worktree. Raw results and local target paths stay in private scratch storage; the public page uses a shortened target name in its example request.
Discovery through REA
The following requests preceded reading the organizers' source, solution or flag metadata. Searching the challenge README established its name/difficulty, and the handout was analyzed directly.
| Operation | Observed result | Evidence ID |
|---|---|---|
search_strings, regex flag|correct|wrong|input |
Prompt at 0x102004; failure at 0x10201c; success at 0x102027 |
ev_375cf2c47d9cd666eeb5527e13863ce8d01ca86d11a6957fde79227aab1266c8 |
xrefs, address 0x102004 |
Reference at 0x10126d |
ev_31fb7e370e0ce8bccdf981167f49ad9196f67ac06c88eb2c1a19e3cb367e22f3 |
resolve_containing_procedure, address 0x10126d |
Function at 0x10124d, inclusive body through 0x10134f, 259 bytes |
ev_0627cfd459c1d9255ae1b03355987a93a0827e658a7ff40abcbf2cb1cfd8e613 |
analyze_function, procedure 0x10124d |
Input conversion, two helper calls, mask/target pointers, success/failure branch | ev_4ba6d97358da28a23dc69cb6fde01cc929f28fc14f3a3661f4c65bbb6d86ec29 |
analyze_function, procedure 0x101189 |
Signed-byte run-length mask expansion | ev_9e4f339895223a21cbf5bcd008ba8b5890e2e804675a11cb286f7af19246f766 |
analyze_function, procedure 0x101217 |
Add input integers at selected mask positions | ev_d89261458e3faddd85110185bcd97f0f3c87e0992edc64cb3b2a1ed44846c3e9 |
read_bytes, address 0x104060, length 144 |
Target numbers followed by padding and the start of the mask table | ev_f8a3529dd5d583b06177be5ce76ca6de36f3242ac90ab30f9a3a96159ff84e53 |
read_bytes, address 0x1040e0, length 624 |
All 26 mask records, 24 bytes each | ev_944d9664d6167bf46c72b9fce662e573ea4e017c5a8ebbc305b1d943a1623301 |
The first 104 bytes of the target read hold the 26 little-endian integers.
The displayed read_bytes requests preserve the actual lengths; the page
selects the seventh entries from those complete results.
Interpretation
CMP EDI,0x24 terminates the input conversion at 36 characters. Its inner
loop groups six integer cells per row. The checking loop walks from 0x1040e0
to 0x104350 in 24-byte steps: 0x270 / 0x18 = 26 masks.
In the mask helper, MOVSX loads each byte with its sign. Positive runs write
ones, negative runs write zeros, and a zero terminates a record. All extracted
records decode to exactly 36 cells. In the summing helper, a zero mask cell
skips the addition; a nonzero cell adds the corresponding input integer.
The caller compares the returned sum against a stored target.
The seventh record starts at 0x104170 and begins eb 01 f2 00, meaning
-21, +1, -14, stop. It selects only zero-based input position 21.
Its target at 0x104078 is 37 00 00 00, decimal 55, the code for 7.
The SVG is calculated from this record, with only cell 21 highlighted.
The first mask selects 16 cells and its target is 1441. In the recovered flag,
changing position 8 from z (122) to y (121) changes that sum to 1440.
The website's C is an analyst-written summary of the sum helper and caller, with a flattened 36-cell loop and descriptive names. Its selected assembly is transcribed from the returned dossiers. The mask/target addresses are analysis-image addresses; the executable's PIE runtime load address can differ.
Solver and source cross-check
The downloadable Python script embeds the REA-extracted masks and targets,
expands their run lengths and gives the 26 sums to Z3. It asks for 36 character
codes using a conventional DUCTF{...} prefix/suffix and an alphabet of
letters, digits, underscores and braces. Those format restrictions are analyst
assumptions, distinguished from the observed binary checks in the script and
page caption.
The solver returned DUCTF{ezzzpzzz_07bcda7bfe81faf43caa} and all 26 extracted
equations match that value. A separate second-model search reached its timeout;
the completed verification concerns the returned candidate.
After obtaining and executing the candidate, the organizers' source confirmed the decoding/summing interpretation, all masks and all targets. The challenge metadata records the same flag.
Original-program verification
Two capture_process_scenario requests launched the original handout in its
scratch directory, supplied one line of input and retained terminal output.
| Input | Output | Exit | Evidence ID |
|---|---|---|---|
DUCTF{ezzzpzzz_07bcda7bfe81faf43caa} |
Correct! |
0 | ev_99f724502d14c798959f510d274f3de0f554a27b5df5dd6cb322acfa3e90a452 |
DUCTF{ezyzpzzz_07bcda7bfe81faf43caa} |
Incorrect! |
255 | ev_2d164f7f4c7eb139e5df8be21c1e52dc34f0ad238aea384e407a2bd6277024cb |
Both captures completed without truncation. REA verified its owned process-group cleanup and removed the capture temporary roots. Filesystem observation paths were not requested. The native analysis session was closed afterward.
The challenge's original code and metadata are credited to DownUnderCTF/joseph. The page, readable C summary, equation figure and Python solver are new work based on this inspection.