docs(website): add a CTF showcase and FAQ (#1077)

* docs(website): add a worked CTF reverse-engineering showcase

* docs(website): add a dedicated FAQ page
This commit is contained in:
Ysopwnable 2026-10-08 22:30:10 +08:00 committed by GitHub
parent 82a1a525d7
commit a4d77f0ff0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 1399 additions and 27 deletions

View File

@ -4,7 +4,7 @@
>
> — N0zoM1z0
An English static website with explanatory figures, worked guides and DX-Ball, Notion and TH04 investigations.
An English static website with explanatory figures, worked guides and DX-Ball, Notion, TH04 and CTF investigations.
The public files are in `website/public/`. The site uses HTML, CSS and a small
script for copying code and following the assembly-to-C comparison. Python
packages the downloadable example; there is no frontend bundler or npm dependency.
@ -30,7 +30,9 @@ Open <http://127.0.0.1:4173/>. Refresh the browser after editing a file.
- `public/showcase/dx-ball/index.html`: sound-pan investigation and project status.
- `public/showcase/notion/index.html`: Notion's Electron clipboard bridge and rich clipboard format.
- `public/showcase/th04/index.html`: TH04's 16-bit DOS bullet-angle calculation and compiler checks.
- `public/showcase/ctf/index.html`: DownUnderCTF's masked-squares flag checker, extracted equations and real process captures.
- `public/get-started/index.html`: agent setup, first CLI result and provider guides.
- `public/faq/index.html`: concise answers about setup, updates, analysis and troubleshooting.
- `public/guides/`: a guide hub and native, JavaScript/Electron and browser examples.
- `public/examples/`: downloadable Electron source and an interactive Notes browser app.
- `public/assets/`: shared styles, interactions, favicon and explanatory figures.
@ -69,6 +71,13 @@ scrolling and returns to the page header, with smooth scrolling when reduced
motion is disabled. Keyboard activation returns focus to the first navigation
link. Without JavaScript, the link stays visible and uses its `#top` anchor.
The FAQ uses native `<details>` for its answers. Keep replies short and link to
on-site guides for the next step. Individual answers have stable fragment IDs;
the shared script opens an answer when its fragment is visited. The questions
and disclosure controls remain usable without JavaScript. Check FAQ commands
and support statements against the English README and relevant guides when
updating them.
DX-Ball figures and findings refer to the linked 7 October 2026 checkpoint,
commit `a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4`. Update those links and figures
together when moving to another checkpoint. Case-study source excerpts come
@ -107,6 +116,20 @@ records the fresh load-image/function evidence and separately credited TH04
source and historical compiler replay. The figure illustrates the calculation;
original game assets and executable bytes are not website downloads.
## CTF case study
The DownUnderCTF 2023 case follows the official `ms_flag_checker` handout from
prompt references to checking functions, compressed masks, equations and an
accepted flag. [evidence/ctf-masked-squares.md](evidence/ctf-masked-squares.md)
records the REA analysis, extracted data and positive/negative process captures.
The downloadable `public/showcase/ctf/solve.py` uses Python and `z3-solver`;
its constants come from REA's byte reads. The original executable stays in the
organizers' repository and is linked from the page.
The mask SVG is drawn from the seventh decoded mask. It selects zero-based
position 21 and compares its character code with 55 (`7`). Keep the figure,
solver constants and evidence notes aligned when changing this case.
## GitHub Pages
`.github/workflows/website-pages.yml` prepares and deploys only `website/public`.

View File

@ -0,0 +1,110 @@
# 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](https://github.com/DownUnderCTF/Challenges_2023_Public/tree/b48f83db2984bc7fa2ec7879a32d7efb1be8d333/rev/masked-squares-flag-checker).
## 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](https://github.com/DownUnderCTF/Challenges_2023_Public/blob/b48f83db2984bc7fa2ec7879a32d7efb1be8d333/rev/masked-squares-flag-checker/src/ms_flag_checker.c)
confirmed the decoding/summing interpretation, all masks and all targets.
The
[challenge metadata](https://github.com/DownUnderCTF/Challenges_2023_Public/blob/b48f83db2984bc7fa2ec7879a32d7efb1be8d333/rev/masked-squares-flag-checker/ctfcli.yaml)
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.

View File

@ -114,3 +114,17 @@ Second check labels verbatim:
Use enough horizontal space for clear check names and generous typography. A two-line label is fine where needed.
Text constraints: render every supplied English label and number verbatim with correct spelling. No extra claims, no additional labels, no footnotes, no source code or assembly, no logos or watermarks. Keep all connectors complete and directed correctly. Large legible labels matter more than decorative density. Never say full reconstruction, exact game clone, all bytes, or automatic source recovery.
## CTF masked-squares figure
`public/assets/figures/ctf-mask-equation.svg` explains the seventh check in
DownUnderCTF 2023's masked-squares flag checker. The original encoded mask is
`-21, +1, -14, 0`: expand it to 36 cells, highlight zero-based cell 21 and
compare its code with the recorded target 55 (`7`). Labels and selected cells
come from the fresh REA byte reads documented in
[evidence/ctf-masked-squares.md](evidence/ctf-masked-squares.md).
The diagram is maintained as SVG source using the shared blue/gray palette.
It illustrates one equation; the downloadable Python solver uses all 26.
Keep code selectable in HTML and use the existing scrollable figure viewport
on smaller screens.

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@ -61,6 +61,28 @@ function initializeStepComparisons() {
initializeStepComparisons();
function initializeFaqAnswers() {
const answers = document.querySelectorAll("[data-faq] details[id]");
if (answers.length === 0) return;
const revealAnswer = (fragment) => {
answers.forEach((answer) => {
if (`#${answer.id}` === fragment) answer.open = true;
});
};
window.addEventListener("hashchange", () =>
revealAnswer(window.location.hash),
);
document.querySelectorAll('[data-faq] a[href^="#"]').forEach((link) => {
link.addEventListener("click", () =>
revealAnswer(link.getAttribute("href")),
);
});
revealAnswer(window.location.hash);
}
initializeFaqAnswers();
function initializeBackToTop() {
const link = document.querySelector(".back-to-top");
if (link === null) return;

View File

@ -171,6 +171,26 @@ section[id] {
.navigation .nav-start {
color: var(--ink);
}
.faq-list {
border-top: 1px solid var(--line);
}
.faq-item {
padding-block: 1rem;
border-bottom: 1px solid var(--line);
scroll-margin-top: 2rem;
}
.faq-item summary {
cursor: pointer;
color: var(--ink);
font-weight: 600;
line-height: 1.55;
}
.faq-item[open] summary {
margin-bottom: 0.9rem;
}
.faq-item > :last-child {
margin-bottom: 0;
}
.eyebrow {
margin-bottom: 1.2rem;
font-size: 0.875rem;
@ -872,7 +892,8 @@ pre code {
.th04-overview {
margin-bottom: 3.2rem;
}
.th04-ring-figure img {
.th04-ring-figure img,
.ctf-mask-figure img {
min-width: 680px;
}
.th04-preview img {
@ -1057,10 +1078,16 @@ pre code {
}
.header-inner {
min-height: 78px;
gap: 1rem;
flex-wrap: wrap;
justify-content: flex-start;
gap: 0.55rem;
padding-block: 0.8rem;
}
.navigation {
gap: 1rem;
width: 100%;
justify-content: space-between;
flex-wrap: wrap;
gap: 0.5rem 0.25rem;
font-size: 0.875rem;
}
.hero {
@ -1179,16 +1206,6 @@ pre code {
}
@media (max-width: 360px) {
.header-inner {
flex-wrap: wrap;
justify-content: flex-start;
gap: 0.3rem;
padding-block: 0.65rem;
}
.navigation {
width: 100%;
justify-content: space-between;
}
.stats,
.case-stats {
grid-template-columns: 1fr;

View File

@ -0,0 +1,413 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>FAQ — REA</title>
<meta
name="description"
content="Answers to common REA questions: installation, updates, analysis tools, coding agents, troubleshooting and sharing examples."
/>
<meta name="theme-color" content="#ffffff" />
<link rel="icon" href="../assets/favicon.svg" type="image/svg+xml" />
<link rel="stylesheet" href="../assets/styles.css" />
<script src="../assets/main.js" defer></script>
</head>
<body id="top">
<a class="skip-link" href="#main">Skip to content</a>
<header class="site-header">
<div class="container header-inner">
<a class="brand" href="../" aria-label="REA home"
><span class="brand-name">REA</span
><span class="brand-caption">Reverse Engineer Anything</span></a
>
<nav class="navigation" aria-label="Main navigation">
<a href="../showcase/">Showcases</a>
<a class="nav-start" href="../get-started/">Get started</a>
<a href="../guides/">Guides</a>
<a href="./" aria-current="page">FAQ</a>
<a href="https://github.com/morluto/rea">GitHub</a>
</nav>
</div>
</header>
<main id="main" class="container">
<div class="page-heading">
<p class="breadcrumb"><a href="../">Home</a> / FAQ</p>
<h1>REA FAQ.</h1>
<p class="lede">Setup, updates, analysis and troubleshooting.</p>
</div>
<div class="article-layout">
<nav class="contents" aria-label="On this page">
<p>Topics</p>
<ul>
<li><a href="#setup">Setup and updates</a></li>
<li><a href="#analysis">Analysis</a></li>
<li><a href="#troubleshooting">Troubleshooting</a></li>
<li><a href="#sharing">Data and sharing</a></li>
</ul>
</nav>
<article
class="article"
data-faq
aria-label="Frequently asked questions about REA"
>
<section class="article-section" id="setup">
<h2>Setup and updates</h2>
<div class="faq-list">
<details class="faq-item" id="install">
<summary>How do I install REA?</summary>
<p>
With Node.js and npm available, run setup, choose your coding
agent and review the proposed changes.
</p>
<div class="code-block">
<div class="code-header">
<span>Terminal · agent setup</span
><button
class="copy-button"
type="button"
data-copy="faq-setup"
aria-label="Copy REA setup command"
>
Copy
</button>
</div>
<pre><code id="faq-setup">npx rea-agents@latest setup</code></pre>
</div>
<p>
Setup registers REA's MCP connection and installs the matching
investigation skill. Restart your agent when it finishes, then
give it a target path and a question.
<a href="../get-started/">Follow the setup guide</a> for
prerequisites and your first analysis.
</p>
</details>
<details class="faq-item" id="agents">
<summary>Which coding agents can use REA?</summary>
<p>
Any agent that supports local MCP servers. Setup includes
Claude Code, Claude Desktop, Codex, Cursor, Gemini CLI,
Windsurf, Devin, OpenCode, Antigravity, GitHub Copilot CLI,
Command Code and VS Code.
</p>
<p>
<a href="../get-started/#agent">Connect your coding agent</a>.
</p>
</details>
<details class="faq-item" id="update">
<summary>How do I update REA?</summary>
<p>
REA releases frequently, including bug fixes. If you installed
the CLI with npm:
</p>
<div class="code-block">
<div class="code-header">
<span>Terminal · installed CLI</span
><button
class="copy-button"
type="button"
data-copy="faq-update-cli"
aria-label="Copy REA update command"
>
Copy
</button>
</div>
<pre><code id="faq-update-cli">rea update</code></pre>
</div>
<p>
Follow the setup refresh command printed by the update. If you
set up your agent through <code>npx</code>, run:
</p>
<div class="code-block">
<div class="code-header">
<span>Terminal · refresh agent setup</span
><button
class="copy-button"
type="button"
data-copy="faq-update-agent"
aria-label="Copy agent setup refresh command"
>
Copy
</button>
</div>
<pre><code id="faq-update-agent">npx rea-agents@latest setup</code></pre>
</div>
<p>
Review the changes and restart your agent. Its REA connection
pins a package version, so refreshing setup makes it use the
new release. For one-off CLI commands, use
<code>npx -y rea-agents@latest</code> followed by the command.
</p>
</details>
<details class="faq-item" id="skill">
<summary>
Is installing the skill from skills.sh enough?
</summary>
<p>
The skill gives your agent investigation instructions. Run
<a href="#install">REA setup</a> to connect the MCP server and
install the matching skill, then restart your agent so it can
call the tools.
</p>
</details>
</div>
</section>
<section class="article-section" id="analysis">
<h2>Analysis</h2>
<div class="faq-list">
<details class="faq-item" id="targets">
<summary>What can I analyze with REA?</summary>
<p>Start with the kind of software you have:</p>
<ul>
<li>
<a href="../guides/native/"
>Native executables and libraries</a
>: functions, assembly, pseudocode and references.
</li>
<li>
<a href="../guides/javascript/"
>JavaScript and Electron apps</a
>: modules, imports, IPC and source locations.
</li>
<li>
<a href="../guides/browser/">Browser pages</a>: scripts,
requests and runtime observations.
</li>
</ul>
<p>
REA also has workflows for managed assemblies, Android APKs,
firmware and packaged resources.
<a href="../showcase/">See the case studies</a> for worked
investigations.
</p>
</details>
<details class="faq-item" id="providers">
<summary>Do I need Hopper, Ghidra or IDA?</summary>
<p>
Deep native analysis uses one of them. Static JavaScript and
.NET inspection work with the supplied files and do not need a
native analysis engine.
</p>
<p>
Connect your existing Ghidra or IDA installation, or let setup
detect Hopper and propose an installation. Your host and
target determine which provider can be used.
<a href="../get-started/#native">Set up native analysis</a>.
</p>
</details>
<details class="faq-item" id="cli">
<summary>Can I use REA without a coding agent?</summary>
<p>
Yes. The CLI uses the same analysis workflows. For a local
JavaScript or Electron app:
</p>
<div class="code-block">
<div class="code-header">
<span>Terminal · static application analysis</span
><button
class="copy-button"
type="button"
data-copy="faq-cli-analysis"
aria-label="Copy REA CLI analysis command"
>
Copy
</button>
</div>
<pre><code id="faq-cli-analysis">npx -y rea-agents@latest analyze-javascript-application \
/absolute/path/to/app --json</code></pre>
</div>
<p>
Replace the path with an extracted application folder or ASAR
file. <a href="../get-started/#terminal">Use the CLI</a> for
installation options.
</p>
</details>
<details class="faq-item" id="code">
<summary>What code does REA return?</summary>
<p>
Native analysis returns assembly and pseudocode, with calls,
references and relevant constants. JavaScript analysis returns
modules, their relationships and source locations.
</p>
<p>
Your agent uses these findings to explain the behavior or
write and test an implementation. The
<a href="../showcase/dx-ball/#sound-pan"
>DX-Ball calculation</a
>
and <a href="../showcase/ctf/">CTF flag checker</a> show how
that process works.
</p>
</details>
<details class="faq-item" id="prompt">
<summary>What should I ask my agent?</summary>
<p>
Give it a local target and one behavior to investigate. For a
JavaScript or Electron app:
</p>
<div class="agent-terminal">
<div class="terminal-header">
<span class="terminal-title"
><span class="terminal-dots" aria-hidden="true"
><i></i><i></i><i></i></span
>Your coding agent</span
><button
class="copy-button"
type="button"
data-copy="faq-analysis-prompt"
aria-label="Copy example analysis prompt"
>
Copy
</button>
</div>
<p class="terminal-prompt">
<span class="prompt-symbol" aria-hidden="true">›</span
><span id="faq-analysis-prompt"
>Use REA to analyze /absolute/path/to/app and explain how
it exports data. Show the relevant code and source
locations.</span
><span class="terminal-cursor" aria-hidden="true"></span>
</p>
</div>
<p class="caption">
Replace the path with your target. The
<a href="../guides/">guides</a> provide prompts for native,
Electron and browser examples.
</p>
</details>
</div>
</section>
<section class="article-section" id="troubleshooting">
<h2>Troubleshooting</h2>
<div class="faq-list">
<details class="faq-item" id="connection">
<summary>Why can't my agent see the REA tools?</summary>
<p>
Restart or reconnect your agent after setup. Check its REA
registration with <code>doctor</code>; for Codex:
</p>
<div class="code-block">
<div class="code-header">
<span>Terminal · check one client</span
><button
class="copy-button"
type="button"
data-copy="faq-doctor"
aria-label="Copy client diagnosis command"
>
Copy
</button>
</div>
<pre><code id="faq-doctor">npx -y rea-agents@latest doctor --client codex --json</code></pre>
</div>
<p>
Replace <code>codex</code> with your client ID, such as
<code>claude_code</code> or <code>cursor</code>. If the report
shows a missing or stale registration, run setup for that
client:
</p>
<div class="code-block">
<div class="code-header">
<span>Terminal · repair one client's setup</span
><button
class="copy-button"
type="button"
data-copy="faq-repair"
aria-label="Copy scoped setup command"
>
Copy
</button>
</div>
<pre><code id="faq-repair">npx rea-agents@latest setup --client codex</code></pre>
</div>
<p>
Review its plan and restart the client. If registration is
healthy but tools remain absent, check the client's MCP
connection error.
<a href="../get-started/#help">More setup diagnostics</a>.
</p>
</details>
<details class="faq-item" id="hopper">
<summary>Do I need to start Hopper first?</summary>
<p>
REA starts Hopper when an operation needs it. On macOS,
complete the first-run choice of demo mode or license
activation before unattended analysis.
<a href="../get-started/#native">See native provider setup</a
>.
</p>
</details>
<details class="faq-item" id="bugs">
<summary>What should I do if I hit a bug?</summary>
<p>
<a href="#update">Update REA</a>, restart your agent and retry
the same task. A recent release may already fix the problem.
</p>
<p>
If it persists,
<a href="https://github.com/morluto/rea/issues/new/choose"
>open an issue</a
>
with your REA version, operating system, target type, steps to
reproduce and error output. Include the provider name when the
problem involves native analysis.
</p>
</details>
</div>
</section>
<section class="article-section" id="sharing">
<h2>Data and sharing</h2>
<div class="faq-list">
<details class="faq-item" id="privacy">
<summary>Does REA upload my app?</summary>
<p>
REA analyzes targets on your machine. Your agent receives the
results, and its model provider's data policy applies to those
results.
</p>
</details>
<details class="faq-item" id="contribute">
<summary>How can I share an example or contribute?</summary>
<p>
Have a useful REA example? We'd love to see it. Share the
target, your question, the findings and how you checked them
in an
<a href="https://github.com/morluto/rea/issues/new/choose"
>issue</a
>
or
<a href="https://github.com/morluto/rea/pulls">pull request</a
>. Short code excerpts and figures help others follow the
investigation.
</p>
<p>
Bug reports, feature requests, documentation and code
improvements are welcome too. You can also discuss an example
in the <a href="https://discord.gg/GkcryMnJDM">community</a>.
</p>
</details>
</div>
</section>
</article>
</div>
</main>
<footer class="site-footer">
<div class="container footer-inner">
<p>REA · Reverse Engineer Anything</p>
<div class="footer-links">
<a href="https://github.com/morluto/rea">Source</a
><a href="https://github.com/morluto/rea/blob/main/LICENSE"
>MIT license</a
><a href="https://discord.gg/GkcryMnJDM">Community</a>
</div>
</div>
</footer>
<p class="sr-only" id="copy-status" role="status" aria-live="polite"></p>
<a class="back-to-top" href="#top" aria-label="Back to top"
><span aria-hidden="true">↑</span> Top</a
>
</body>
</html>

View File

@ -24,8 +24,8 @@
<nav class="navigation" aria-label="Main navigation">
<a href="../showcase/">Showcases</a
><a class="nav-start" href="./" aria-current="page">Get started</a
><a href="../guides/">Guides</a
><a href="https://github.com/morluto/rea">GitHub</a>
><a href="../guides/">Guides</a><a href="../faq/">FAQ</a>
<a href="https://github.com/morluto/rea">GitHub</a>
</nav>
</div>
</header>
@ -367,6 +367,10 @@ npx rea-agents@latest setup</code></pre>
</div>
<p>The report gives the failed check and a suggested next step.</p>
<ul class="reading-list">
<li>
<a href="../faq/">REA FAQ</a
><span>Quick answers on updates, agents and analysis.</span>
</li>
<li>
<a href="../guides/">Choose an investigation guide</a
><span

View File

@ -24,8 +24,8 @@
<nav class="navigation" aria-label="Main navigation">
<a href="../../showcase/">Showcases</a
><a class="nav-start" href="../../get-started/">Get started</a
><a href="../">Guides</a
><a href="https://github.com/morluto/rea">GitHub</a>
><a href="../">Guides</a><a href="../../faq/">FAQ</a>
<a href="https://github.com/morluto/rea">GitHub</a>
</nav>
</div>
</header>

View File

@ -24,8 +24,8 @@
<nav class="navigation" aria-label="Main navigation">
<a href="../showcase/">Showcases</a
><a class="nav-start" href="../get-started/">Get started</a
><a href="./" aria-current="page">Guides</a
><a href="https://github.com/morluto/rea">GitHub</a>
><a href="./" aria-current="page">Guides</a><a href="../faq/">FAQ</a>
<a href="https://github.com/morluto/rea">GitHub</a>
</nav>
</div>
</header>

View File

@ -24,8 +24,8 @@
<nav class="navigation" aria-label="Main navigation">
<a href="../../showcase/">Showcases</a
><a class="nav-start" href="../../get-started/">Get started</a
><a href="../">Guides</a
><a href="https://github.com/morluto/rea">GitHub</a>
><a href="../">Guides</a><a href="../../faq/">FAQ</a>
<a href="https://github.com/morluto/rea">GitHub</a>
</nav>
</div>
</header>

View File

@ -24,8 +24,8 @@
<nav class="navigation" aria-label="Main navigation">
<a href="../../showcase/">Showcases</a
><a class="nav-start" href="../../get-started/">Get started</a
><a href="../">Guides</a
><a href="https://github.com/morluto/rea">GitHub</a>
><a href="../">Guides</a><a href="../../faq/">FAQ</a>
<a href="https://github.com/morluto/rea">GitHub</a>
</nav>
</div>
</header>

View File

@ -25,6 +25,7 @@
<a href="showcase/">Showcases</a>
<a class="nav-start" href="get-started/">Get started</a>
<a href="guides/">Guides</a>
<a href="faq/">FAQ</a>
<a href="https://github.com/morluto/rea">GitHub</a>
</nav>
</div>
@ -264,6 +265,37 @@
</div>
</section>
<section class="section">
<div class="container feature-case">
<div>
<p class="eyebrow">Case study · CTF</p>
<h2>Solve a CTF flag checker</h2>
<p>
Use REA to inspect an easy DownUnderCTF binary. Extract its
checking rules, solve for the flag and confirm that the original
program accepts it.
</p>
<a class="text-link" href="showcase/ctf/">See the CTF solution</a>
</div>
<figure class="workflow-figure case-preview">
<p class="figure-title">One check reveals one character</p>
<div class="code-block">
<div class="code-header">
<span>From REA's code and data</span>
</div>
<pre><code>Mask: skip 21, select 1, skip 14
Target: 55
code[21] = 55 → '7'</code></pre>
</div>
<figcaption>
Each mask selects characters whose codes must add up to a stored
number. This one selects a single character.
</figcaption>
</figure>
</div>
</section>
<section class="section">
<div class="container start-row">
<div>

View File

@ -0,0 +1,620 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Solve a CTF flag checker — REA</title>
<meta
name="description"
content="Use REA to solve DownUnderCTF's masked squares flag checker. Find the checking functions, extract the masks and compare a recovered flag with the original program."
/>
<meta name="theme-color" content="#ffffff" />
<link rel="icon" href="../../assets/favicon.svg" type="image/svg+xml" />
<link rel="stylesheet" href="../../assets/styles.css" />
<script src="../../assets/main.js" defer></script>
</head>
<body id="top">
<a class="skip-link" href="#main">Skip to content</a>
<header class="site-header">
<div class="container header-inner">
<a class="brand" href="../../" aria-label="REA home"
><span class="brand-name">REA</span
><span class="brand-caption">Reverse Engineer Anything</span></a
>
<nav class="navigation" aria-label="Main navigation">
<a href="../">Showcases</a>
<a class="nav-start" href="../../get-started/">Get started</a>
<a href="../../guides/">Guides</a>
<a href="../../faq/">FAQ</a>
<a href="https://github.com/morluto/rea">GitHub</a>
</nav>
</div>
</header>
<main id="main" class="container">
<div class="page-heading">
<p class="breadcrumb">
<a href="../../">Home</a> / <a href="../">Showcases</a> / CTF
</p>
<p class="eyebrow">Case study · DownUnderCTF 2023</p>
<h1>Find the flag in<br />a CTF binary.</h1>
<p class="lede">
Use REA to inspect a small flag checker, turn its rules into equations
and find an input that makes the original program print
<code>Correct!</code>.
</p>
<p class="page-meta">
masked squares flag checker · Easy · Linux x86-64
</p>
<a
class="text-link"
href="https://github.com/DownUnderCTF/Challenges_2023_Public/tree/b48f83db2984bc7fa2ec7879a32d7efb1be8d333/rev/masked-squares-flag-checker"
>View the original challenge</a
>
</div>
<figure class="workflow-figure case-figure">
<p class="figure-title">From a binary to a checked answer</p>
<ol class="flow-steps">
<li>
<span class="flow-label">01 · Find the check</span
><strong class="flow-node">Strings → checking functions</strong
><span class="flow-note"
>REA finds the prompt, its references and the code that accepts or
rejects an input.</span
>
</li>
<li>
<span class="flow-label">02 · Extract the rules</span
><strong class="flow-node">36 characters · 26 sums</strong
><span class="flow-note"
>REA returns the instructions and data behind each check. The
agent turns them into equations.</span
>
</li>
<li>
<span class="flow-label">03 · Solve and run</span
><strong class="flow-node">Recovered flag → Correct!</strong
><span class="flow-note"
>A Python script solves the equations. REA captures the original
program accepting the result.</span
>
</li>
</ol>
<figcaption>
The challenge is by joseph, published in DownUnderCTF's official
repository.
</figcaption>
</figure>
<div class="article-layout">
<nav class="contents" aria-label="On this page">
<p>In this case study</p>
<ul>
<li><a href="#find">Find the checking code</a></li>
<li><a href="#mask">Read one mask</a></li>
<li><a href="#code">Assembly to readable code</a></li>
<li><a href="#solve">Solve the equations</a></li>
<li><a href="#verify">Check the answer</a></li>
<li><a href="#try">Try it yourself</a></li>
</ul>
</nav>
<article class="article" aria-label="CTF flag-checker case study">
<section class="article-section" id="find">
<h2>Find the checking code</h2>
<p>
The handout is a 15 KB executable. It asks for a flag, then prints
<code>Correct!</code> or <code>Incorrect!</code>. Start with a
simple request to your agent.
</p>
<div class="agent-terminal">
<div class="terminal-header">
<span class="terminal-title"
><span class="terminal-dots" aria-hidden="true"
><i></i><i></i><i></i></span
>Your coding agent</span
>
<button
class="copy-button"
type="button"
data-copy="ctf-prompt"
aria-label="Copy CTF example prompt"
>
Copy
</button>
</div>
<p class="terminal-prompt">
<span class="prompt-symbol" aria-hidden="true">›</span
><span id="ctf-prompt"
>Use REA to analyze ms_flag_checker and find the flag. Explain
how the checks work, then verify the answer with the original
program.</span
><span class="terminal-cursor" aria-hidden="true"></span>
</p>
</div>
<p class="caption">
An example prompt, with the downloaded challenge available locally
and a native analysis provider connected.
</p>
<ol class="rea-queries">
<li>
<h4>Follow the input prompt to its function</h4>
<div class="rea-query-pair">
<div class="code-block">
<div class="code-header"><span>Agent → REA</span></div>
<pre><code>open_binary
{"path": "ms_flag_checker"}
search_strings
{"pattern": "flag|correct|wrong|input",
"mode": "regex", "case_sensitive": false}
xrefs
{"address": "0x102004"}
resolve_containing_procedure
{"address": "0x10126d"}</code></pre>
</div>
<div class="code-block">
<div class="code-header">
<span>REA → agent · selected results</span>
</div>
<pre><code>0x102004 "What is the flag? "
0x10201c "Incorrect!"
0x102027 "Correct!"
Prompt referenced at: 0x10126d
Containing function: 0x10124d</code></pre>
</div>
</div>
<p>
The reference gives the agent a place to investigate, even
though the executable's original function names have been
removed.
</p>
</li>
<li>
<h4>Read the checker and its two helpers</h4>
<div class="rea-query-pair">
<div class="code-block">
<div class="code-header"><span>Agent → REA</span></div>
<pre><code>analyze_function
{"procedure": "0x10124d"}
analyze_function
{"procedure": "0x101189"}
analyze_function
{"procedure": "0x101217"}</code></pre>
</div>
<div class="code-block">
<div class="code-header">
<span>REA → agent · selected instructions</span>
</div>
<pre><code>0x1012c1: CMP EDI, 0x24
0x1012c6: LEA RBX, [0x1040e0]
0x1012cd: LEA RBP, [0x104060]
0x1012d4: LEA R13, [RBX + 0x270]
0x1012e1: CALL 0x00101189
0x1012ec: CALL 0x00101217
0x1012f1: CMP dword ptr [RBP], EAX
0x1012f4: JNZ 0x00101335
0x1012f6: ADD RBX, 0x18</code></pre>
</div>
</div>
<p>
The first loop copies 36 character codes. The checking loop
decodes a mask, sums the selected codes and compares the
result with a stored number. Its <code>0x18</code>-byte steps
across <code>0x270</code> bytes give 26 masks.
</p>
</li>
</ol>
<p class="caption">
These are selected results from a fresh REA analysis. The local
target path is shortened for display; addresses refer to REA's
imported image.
</p>
</section>
<section class="article-section" id="mask">
<h2>One check reveals one character</h2>
<p>
The checker arranges the input in a 6×6 grid. A mask chooses which
cells contribute to a sum. Its compact encoding uses negative
numbers to skip cells and positive numbers to select them.
</p>
<figure class="explanatory-figure ctf-mask-figure">
<div
class="figure-viewport"
tabindex="0"
role="region"
aria-label="CTF mask equation; scroll horizontally on smaller screens"
>
<img
src="../../assets/figures/ctf-mask-equation.svg"
width="760"
height="475"
alt="The seventh mask skips 21 cells, selects position 21, then skips 14. Only that cell contributes to the sum. Its required character code is 55, which means the character is 7."
decoding="async"
/>
</div>
<figcaption>
The seventh check selects just one position.
<a href="../../assets/figures/ctf-mask-equation.svg"
>Open figure</a
>.
</figcaption>
</figure>
<h3 class="small-heading">
Read the mask and its target from the binary
</h3>
<div class="rea-query-pair">
<div class="code-block">
<div class="code-header">
<span>Agent → REA · read_bytes</span>
</div>
<pre><code>{"address": "0x1040e0", "length": 624}
{"address": "0x104060", "length": 144}</code></pre>
</div>
<div class="code-block">
<div class="code-header">
<span>REA → agent · seventh entries</span>
</div>
<pre><code>Mask at 0x104170:
eb 01 f2 00 → -21, +1, -14, stop
Target at 0x104078:
37 00 00 00 → 55</code></pre>
</div>
</div>
<p>
The instruction <code>MOVSX</code> reads mask bytes as signed
values. This is why <code>eb</code> means −21. The target is a
little-endian integer. Together, these bytes tell the agent that
<code>code[21] = 55</code>, so that character is <code>7</code>.
</p>
</section>
<section class="article-section" id="code">
<h2>From instructions to a readable check</h2>
<p>
Select a step to connect the summing helper and its caller to the
same rule in C.
</p>
<div class="step-comparison" data-step-comparison>
<div
class="step-selector"
role="group"
aria-label="Follow the CTF check"
>
<button
type="button"
data-select-step="1"
aria-pressed="true"
aria-controls="ctf-assembly ctf-check ctf-step-detail"
>
<span>01</span> Start
</button>
<button
type="button"
data-select-step="2"
aria-pressed="false"
aria-controls="ctf-assembly ctf-check ctf-step-detail"
>
<span>02</span> Select
</button>
<button
type="button"
data-select-step="3"
aria-pressed="false"
aria-controls="ctf-assembly ctf-check ctf-step-detail"
>
<span>03</span> Add
</button>
<button
type="button"
data-select-step="4"
aria-pressed="false"
aria-controls="ctf-assembly ctf-check ctf-step-detail"
>
<span>04</span> Advance
</button>
<button
type="button"
data-select-step="5"
aria-pressed="false"
aria-controls="ctf-assembly ctf-check ctf-step-detail"
>
<span>05</span> Compare
</button>
</div>
<div class="code-comparison">
<div class="code-block">
<div class="code-header">
<span>REA · selected original instructions</span
><button
class="copy-button"
type="button"
data-copy="ctf-assembly"
aria-label="Copy CTF assembly"
>
Copy
</button>
</div>
<pre><code id="ctf-assembly"><span class="code-step is-active" data-step="1">0x10121c: MOV ECX, 0x0</span>
<span class="code-step" data-step="2">0x10122c: CMP dword ptr [RSI + RAX*0x1], 0x0
0x101230: JZ 0x00101223</span>
<span class="code-step" data-step="3">0x101232: ADD ECX, dword ptr [RDI + RAX*0x1]</span>
<span class="code-step" data-step="4">0x101223: ADD RAX, 0x4</span>
<span class="code-step" data-step="5">0x1012f1: CMP dword ptr [RBP], EAX
0x1012f4: JNZ 0x00101335</span></code></pre>
</div>
<div class="code-block">
<div class="code-header">
<span>Readable C · one-check summary</span
><button
class="copy-button"
type="button"
data-copy="ctf-check"
aria-label="Copy readable CTF check"
>
Copy
</button>
</div>
<pre><code id="ctf-check">int check_one_mask(const int codes[36],
const int mask[36],
int target) {
<span class="code-step is-active" data-step="1"> int total = 0;</span>
<span class="code-step" data-step="4"> for (int i = 0; i &lt; 36; ++i) {</span>
<span class="code-step" data-step="2"> if (mask[i]) {</span>
<span class="code-step" data-step="3"> total += codes[i];</span>
}
}
<span class="code-step" data-step="5"> return total == target;</span>
}</code></pre>
</div>
</div>
<div
class="step-detail"
id="ctf-step-detail"
aria-live="polite"
aria-atomic="true"
>
<p data-step-note="1">
<strong>01 · Start at zero.</strong> <code>ECX</code> holds
the running sum.
</p>
<p data-step-note="2" hidden>
<strong>02 · Check the mask cell.</strong> A zero value skips
the character; a nonzero value includes it.
</p>
<p data-step-note="3" hidden>
<strong>03 · Add a character code.</strong> The input's
integer at the same offset is added to the sum.
</p>
<p data-step-note="4" hidden>
<strong>04 · Move to the next cell.</strong> The original loop
advances four bytes per integer and visits six rows of six
cells.
</p>
<p data-step-note="5" hidden>
<strong>05 · Compare with the stored target.</strong> The
caller receives the sum in <code>EAX</code>. A mismatch jumps
to <code>Incorrect!</code>.
</p>
</div>
</div>
<p class="caption">
The instructions come from the summing helper and its caller. The
C is an explanatory summary with descriptive names and a flattened
36-cell loop.
</p>
</section>
<section class="article-section" id="solve">
<h2>Solve the 26 equations</h2>
<p>
Most masks select several cells. For example, the first check adds
16 character codes and requires a total of 1441. The overlapping
selections give equations that a small Python script can solve
together.
</p>
<div class="code-block">
<div class="code-header">
<span>Python · solver excerpt</span
><button
class="copy-button"
type="button"
data-copy="ctf-solver-excerpt"
aria-label="Copy CTF solver excerpt"
>
Copy
</button>
</div>
<pre><code id="ctf-solver-excerpt">from z3 import Int, Or, Solver, Sum, sat
codes = [Int(f"code_{i}") for i in range(36)]
solver = Solver()
alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_{}"
for code in codes:
solver.add(Or(*[code == ord(c) for c in alphabet]))
for code, char in zip(codes, "DUCTF{"):
solver.add(code == ord(char))
solver.add(codes[-1] == ord("}"))
for selected, target in checks:
solver.add(Sum([codes[i] for i in selected]) == target)
assert solver.check() == sat
model = solver.model()
print("".join(chr(model.eval(code).as_long()) for code in codes))</code></pre>
</div>
<p class="caption">
Z3 is a solver that finds values satisfying these equations. This
excerpt uses the extracted checks and assumes a
<code>DUCTF{…}</code> flag with letters, digits, underscores and
braces. The complete download includes all 26 masks and targets.
</p>
<a class="text-link" href="solve.py" download="solve.py"
>Download the complete solver</a
>
</section>
<section class="article-section" id="verify">
<h2>Check the answer with the original program</h2>
<p>
REA's process capture records the original executable accepting
the solved flag. Changing one selected character from
<code>z</code> to <code>y</code> makes the first sum 1440 instead
of 1441, and the program rejects it.
</p>
<div class="evidence-table-wrap">
<table class="evidence-table">
<thead>
<tr>
<th>Input</th>
<th>Observed output</th>
<th>Exit code</th>
</tr>
</thead>
<tbody>
<tr>
<td>Solver's flag</td>
<td><code>Correct!</code></td>
<td>0</td>
</tr>
<tr>
<td>One character changed</td>
<td><code>Incorrect!</code></td>
<td>255</td>
</tr>
</tbody>
</table>
</div>
<details class="evidence-details">
<summary>Show the recovered flag and captured output</summary>
<div class="code-block">
<div class="code-header">
<span>REA · original program output</span
><button
class="copy-button"
type="button"
data-copy="ctf-flag"
aria-label="Copy recovered flag"
>
Copy flag
</button>
</div>
<pre><code>What is the flag? <span id="ctf-flag">DUCTF{ezzzpzzz_07bcda7bfe81faf43caa}</span>
Correct!</code></pre>
</div>
<p>
The recovered value also matches the flag in the organizers'
published challenge metadata, checked after solving the binary.
</p>
</details>
<details class="evidence-details">
<summary>Source, target identity and analysis details</summary>
<p>
Fresh analysis and two process captures on 8 October 2026, using
REA 4.1.0 with Ghidra 12.1.4 on Linux x64. The binary is a
stripped x86-64 ELF, 15,248 bytes.
</p>
<div class="code-block">
<div class="code-header">
<span>Original executable · SHA-256</span>
</div>
<pre><code>dcd3bec4f608e11f3a12ce461100aaf5f621851ee63a1f870d7c90d4e3dd51ae</code></pre>
</div>
<p>
The string references, functions and constants were inspected
before reading the organizers' source or solution. The Python
solver and the diagram were built from those REA results.
</p>
<p>
<a
href="https://github.com/DownUnderCTF/Challenges_2023_Public/blob/b48f83db2984bc7fa2ec7879a32d7efb1be8d333/rev/masked-squares-flag-checker/src/ms_flag_checker.c"
>Compare with the organizers' source</a
>
·
<a
href="https://github.com/DownUnderCTF/Challenges_2023_Public/blob/b48f83db2984bc7fa2ec7879a32d7efb1be8d333/rev/masked-squares-flag-checker/ctfcli.yaml"
>Challenge metadata and flag</a
>
·
<a
href="https://github.com/morluto/rea/blob/main/website/evidence/ctf-masked-squares.md"
>REA evidence notes</a
>
</p>
</details>
</section>
<section class="article-section" id="try">
<h2>Try it yourself</h2>
<p>
Download the original challenge and the solver into one folder.
Use the prompt above to investigate with your agent, or run the
included script.
</p>
<div class="actions">
<a
class="button"
href="https://raw.githubusercontent.com/DownUnderCTF/Challenges_2023_Public/b48f83db2984bc7fa2ec7879a32d7efb1be8d333/rev/masked-squares-flag-checker/publish/ms_flag_checker"
>Download the original challenge</a
><a class="text-link" href="solve.py" download="solve.py"
>Download solver</a
>
</div>
<div class="code-block">
<div class="code-header">
<span>Terminal · solve and run</span
><button
class="copy-button"
type="button"
data-copy="ctf-run"
aria-label="Copy CTF solver commands"
>
Copy
</button>
</div>
<pre><code id="ctf-run">python3 -m venv .venv
.venv/bin/python -m pip install z3-solver
.venv/bin/python solve.py
chmod +x ms_flag_checker
./ms_flag_checker</code></pre>
</div>
<p class="caption">
The script prints a candidate flag; paste it at the program's
prompt. Solving needs Python and <code>z3-solver</code>. Running
the original executable needs Linux x86-64.
</p>
<a class="text-link" href="../../get-started/"
>Set up REA with your coding agent</a
>
</section>
</article>
</div>
</main>
<footer class="site-footer">
<div class="container footer-inner">
<p>REA · Reverse Engineer Anything</p>
<div class="footer-links">
<a href="https://github.com/morluto/rea">Source</a
><a href="https://github.com/morluto/rea/blob/main/LICENSE"
>MIT license</a
><a href="https://discord.gg/GkcryMnJDM">Community</a>
</div>
</div>
</footer>
<p class="sr-only" id="copy-status" role="status" aria-live="polite"></p>
<a class="back-to-top" href="#top" aria-label="Back to top"
><span aria-hidden="true">↑</span> Top</a
>
</body>
</html>

View File

@ -0,0 +1,72 @@
#!/usr/bin/env python3
"""Solve the DownUnderCTF 2023 masked-squares handout from REA-extracted checks.
Requires Python 3 and z3-solver. The constants below were read from the original
ELF with SHA-256 dcd3bec4f608e11f3a12ce461100aaf5f621851ee63a1f870d7c90d4e3dd51ae.
Challenge by joseph / DownUnderCTF:
https://github.com/DownUnderCTF/Challenges_2023_Public/tree/b48f83db2984bc7fa2ec7879a32d7efb1be8d333/rev/masked-squares-flag-checker
"""
from z3 import Int, Or, Solver, Sum, sat
TARGETS = [1441, 2043, 1259, 2031, 1799, 746, 55, 1450, 1485, 1362, 611, 1314, 358, 1834, 1500, 1355, 2011, 1990, 1939, 1990, 278, 1859, 2111, 1510, 888, 1224]
RUNS = [
(-5, 1, -2, 1, -1, 3, -3, 2, -1, 1, -1, 1, -1, 1, -1, 2, -3, 2, -2, 2),
(-1, 1, -3, 2, -3, 2, -1, 1, -2, 3, -1, 1, -1, 7, -1, 3, -1, 2),
(-1, 1, -1, 1, -1, 2, -1, 1, -6, 1, -1, 1, -2, 1, -1, 1, -1, 1, -4, 3, -1, 1, -2),
(2, -1, 5, -3, 3, -1, 4, -1, 2, -1, 5, -3, 2, -3),
(-1, 1, -3, 1, -1, 1, -2, 1, -1, 3, -1, 1, -1, 1, -2, 5, -1, 4, -1, 1, -3),
(1, -2, 2, -8, 1, -7, 2, -1, 1, -3, 1, -2, 1, -4),
(-21, 1, -14),
(-2, 3, -4, 4, -5, 1, -2, 1, -1, 1, -2, 1, -2, 1, -1, 4, -1),
(-4, 5, -3, 1, -5, 1, -3, 1, -2, 5, -4, 2),
(-1, 2, -4, 1, -1, 4, -3, 1, -4, 1, -1, 2, -1, 1, -3, 1, -1, 2, -2),
(-2, 1, -8, 1, -1, 1, -3, 1, -1, 1, -7, 1, -8),
(1, -2, 5, -1, 1, -8, 3, -2, 1, -2, 1, -3, 1, -4, 1),
(-3, 1, -9, 1, -2, 1, -17, 1, -1),
(3, -5, 4, -1, 1, -2, 1, -1, 2, -3, 3, -1, 1, -1, 3, -1, 2, -1),
(-2, 2, -3, 1, -1, 1, -1, 1, -1, 1, -7, 1, -1, 6, -1, 3, -1, 1, -1),
(1, -5, 1, -2, 2, -1, 2, -1, 1, -1, 1, -5, 1, -1, 1, -1, 5, -4),
(2, -3, 1, -5, 4, -2, 3, -2, 5, -1, 2, -1, 2, -1, 2),
(-1, 1, -3, 1, -1, 2, -2, 1, -1, 7, -2, 3, -1, 4, -1, 1, -2, 1, -1),
(2, -1, 1, -2, 2, -1, 2, -2, 5, -1, 1, -1, 2, -3, 2, -1, 1, -2, 2, -1, 1),
(1, -3, 3, -1, 1, -2, 1, -1, 6, -1, 1, -1, 2, -2, 1, -1, 1, -1, 3, -1, 2),
(-9, 1, -9, 1, -5, 1, -10),
(1, -1, 2, -2, 1, -1, 9, -1, 1, -1, 1, -7, 2, -2, 1, -2, 1),
(-1, 9, -1, 3, -1, 6, -1, 1, -1, 1, -2, 1, -3, 1, -4),
(-2, 1, -3, 1, -1, 2, -5, 6, -1, 2, -2, 4, -1, 1, -4),
(-2, 1, -4, 1, -1, 1, -2, 1, -3, 1, -3, 1, -3, 3, -6, 1, -2),
(-8, 4, -2, 2, -1, 3, -5, 1, -2, 2, -1, 1, -4),
]
def decode_mask(runs):
"""Expand signed run lengths into 36 selected/unselected cells."""
cells = [selected for run in runs for selected in [run > 0] * abs(run)]
if len(cells) != 36:
raise ValueError('A mask must cover all 36 input positions.')
return [i for i, selected in enumerate(cells) if selected]
codes = [Int(f'code_{i}') for i in range(36)]
solver = Solver()
solver.set(timeout=60000)
# Analyst assumptions about a conventional flag's format and alphabet.
alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_{}'
for code in codes:
solver.add(Or(*[code == ord(char) for char in alphabet]))
for code, char in zip(codes, 'DUCTF{'):
solver.add(code == ord(char))
solver.add(codes[-1] == ord('}'))
for runs, target in zip(RUNS, TARGETS):
solver.add(Sum([codes[i] for i in decode_mask(runs)]) == target)
status = solver.check()
if status != sat:
raise SystemExit(f'No candidate returned: {status}. {solver.reason_unknown()}')
model = solver.model()
values = [model.eval(code).as_long() for code in codes]
if not all(sum(values[i] for i in decode_mask(runs)) == target
for runs, target in zip(RUNS, TARGETS)):
raise SystemExit('Candidate did not pass the extracted checks.')
print(''.join(map(chr, values)))

View File

@ -25,6 +25,7 @@
<a href="../">Showcases</a>
<a class="nav-start" href="../../get-started/">Get started</a>
<a href="../../guides/">Guides</a>
<a href="../../faq/">FAQ</a>
<a href="https://github.com/morluto/rea">GitHub</a>
</nav>
</div>

View File

@ -6,7 +6,7 @@
<title>Case studies — REA</title>
<meta
name="description"
content="Follow REA investigations through code and figures: DX-Ball's sound pan, Notion's Electron clipboard and TH04's aimed bullet rings."
content="Follow REA investigations through code and figures: DX-Ball, Notion, TH04 and a DownUnderCTF flag checker."
/>
<meta name="theme-color" content="#ffffff" />
<link rel="icon" href="../assets/favicon.svg" type="image/svg+xml" />
@ -25,6 +25,7 @@
<a href="./" aria-current="page">Showcases</a>
<a class="nav-start" href="../get-started/">Get started</a>
<a href="../guides/">Guides</a>
<a href="../faq/">FAQ</a>
<a href="https://github.com/morluto/rea">GitHub</a>
</nav>
</div>
@ -34,11 +35,29 @@
<p class="breadcrumb"><a href="../">Home</a> / Showcases</p>
<h1>REA case studies.</h1>
<p class="lede">
Game reconstruction and Electron analysis, with examples from DX-Ball,
Notion and TH04.
Game reconstruction, Electron analysis and a CTF challenge, with code,
figures and checked results.
</p>
</div>
<div class="guide-index">
<section class="guide-entry">
<p class="eyebrow">CTF · Native analysis</p>
<div>
<h2>Solve a CTF flag checker</h2>
<p>
Inspect an easy DownUnderCTF challenge with REA. Find its checking
functions, turn masks and sums into equations, then verify the
solved flag with the original program.
</p>
<div class="guide-route">
<span>Binary</span> <b aria-hidden="true">→</b>
<span>Checking code</span> <b aria-hidden="true">→</b>
<span>Equations</span> <b aria-hidden="true">→</b>
<span>Correct!</span>
</div>
<a class="text-link" href="ctf/">Read the CTF case study</a>
</div>
</section>
<section class="guide-entry">
<p class="eyebrow">Native · Reconstruction</p>
<div>

View File

@ -25,6 +25,7 @@
<a href="../">Showcases</a>
<a class="nav-start" href="../../get-started/">Get started</a>
<a href="../../guides/">Guides</a>
<a href="../../faq/">FAQ</a>
<a href="https://github.com/morluto/rea">GitHub</a>
</nav>
</div>

View File

@ -25,6 +25,7 @@
<a href="../">Showcases</a>
<a class="nav-start" href="../../get-started/">Get started</a>
<a href="../../guides/">Guides</a>
<a href="../../faq/">FAQ</a>
<a href="https://github.com/morluto/rea">GitHub</a>
</nav>
</div>