diff --git a/website/README.md b/website/README.md index abbce8908..23fbca052 100644 --- a/website/README.md +++ b/website/README.md @@ -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 . 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 `
` 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`. diff --git a/website/evidence/ctf-masked-squares.md b/website/evidence/ctf-masked-squares.md new file mode 100644 index 000000000..82f126be3 --- /dev/null +++ b/website/evidence/ctf-masked-squares.md @@ -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. diff --git a/website/figures.md b/website/figures.md index 525c3df1c..ff8f7bba3 100644 --- a/website/figures.md +++ b/website/figures.md @@ -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. diff --git a/website/public/assets/figures/ctf-mask-equation.svg b/website/public/assets/figures/ctf-mask-equation.svg new file mode 100644 index 000000000..9b6da9680 --- /dev/null +++ b/website/public/assets/figures/ctf-mask-equation.svg @@ -0,0 +1,23 @@ + +One check reveals one character +The seventh mask selects only position 21 in the six by six input grid. Its character code must equal 55, so the character is 7. The other masks select different positions and give further equations. + + + +One check reveals one character +The seventh check. Cell labels are input positions, starting at 0. + +Encoded mask: −21, +1, −14, 0 +Skip 21 cells. Select 1. Skip 14. Stop at 0. +000102030405060708091011121314151617181920212223242526272829303132333435 + + +Only one cell contributes to this sum +code[21] = 55 +55 → '7' +Position 21 in the flag must contain 7. + +Selected: one cell +26 masks give 26 equations. +Solve them together to find the flag. + \ No newline at end of file diff --git a/website/public/assets/main.js b/website/public/assets/main.js index 1cdb38e0e..e11e0c161 100644 --- a/website/public/assets/main.js +++ b/website/public/assets/main.js @@ -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; diff --git a/website/public/assets/styles.css b/website/public/assets/styles.css index d1f36e0ee..a7694af9b 100644 --- a/website/public/assets/styles.css +++ b/website/public/assets/styles.css @@ -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; diff --git a/website/public/faq/index.html b/website/public/faq/index.html new file mode 100644 index 000000000..f6e24ca09 --- /dev/null +++ b/website/public/faq/index.html @@ -0,0 +1,413 @@ + + + + + + FAQ — REA + + + + + + + + + +
+
+ +

REA FAQ.

+

Setup, updates, analysis and troubleshooting.

+
+
+ +
+
+

Setup and updates

+
+
+ How do I install REA? +

+ With Node.js and npm available, run setup, choose your coding + agent and review the proposed changes. +

+
+
+ Terminal · agent setup +
+
npx rea-agents@latest setup
+
+

+ 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. + Follow the setup guide for + prerequisites and your first analysis. +

+
+
+ Which coding agents can use REA? +

+ 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. +

+

+ Connect your coding agent. +

+
+
+ How do I update REA? +

+ REA releases frequently, including bug fixes. If you installed + the CLI with npm: +

+
+
+ Terminal · installed CLI +
+
rea update
+
+

+ Follow the setup refresh command printed by the update. If you + set up your agent through npx, run: +

+
+
+ Terminal · refresh agent setup +
+
npx rea-agents@latest setup
+
+

+ 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 + npx -y rea-agents@latest followed by the command. +

+
+
+ + Is installing the skill from skills.sh enough? + +

+ The skill gives your agent investigation instructions. Run + REA setup to connect the MCP server and + install the matching skill, then restart your agent so it can + call the tools. +

+
+
+
+ +
+

Analysis

+
+
+ What can I analyze with REA? +

Start with the kind of software you have:

+ +

+ REA also has workflows for managed assemblies, Android APKs, + firmware and packaged resources. + See the case studies for worked + investigations. +

+
+
+ Do I need Hopper, Ghidra or IDA? +

+ 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. +

+

+ 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. + Set up native analysis. +

+
+
+ Can I use REA without a coding agent? +

+ Yes. The CLI uses the same analysis workflows. For a local + JavaScript or Electron app: +

+
+
+ Terminal · static application analysis +
+
npx -y rea-agents@latest analyze-javascript-application \
+  /absolute/path/to/app --json
+
+

+ Replace the path with an extracted application folder or ASAR + file. Use the CLI for + installation options. +

+
+
+ What code does REA return? +

+ Native analysis returns assembly and pseudocode, with calls, + references and relevant constants. JavaScript analysis returns + modules, their relationships and source locations. +

+

+ Your agent uses these findings to explain the behavior or + write and test an implementation. The + DX-Ball calculation + and CTF flag checker show how + that process works. +

+
+
+ What should I ask my agent? +

+ Give it a local target and one behavior to investigate. For a + JavaScript or Electron app: +

+
+
+ Your coding agent +
+

+ Use REA to analyze /absolute/path/to/app and explain how + it exports data. Show the relevant code and source + locations. +

+
+

+ Replace the path with your target. The + guides provide prompts for native, + Electron and browser examples. +

+
+
+
+ +
+

Troubleshooting

+
+
+ Why can't my agent see the REA tools? +

+ Restart or reconnect your agent after setup. Check its REA + registration with doctor; for Codex: +

+
+
+ Terminal · check one client +
+
npx -y rea-agents@latest doctor --client codex --json
+
+

+ Replace codex with your client ID, such as + claude_code or cursor. If the report + shows a missing or stale registration, run setup for that + client: +

+
+
+ Terminal · repair one client's setup +
+
npx rea-agents@latest setup --client codex
+
+

+ Review its plan and restart the client. If registration is + healthy but tools remain absent, check the client's MCP + connection error. + More setup diagnostics. +

+
+
+ Do I need to start Hopper first? +

+ REA starts Hopper when an operation needs it. On macOS, + complete the first-run choice of demo mode or license + activation before unattended analysis. + See native provider setup. +

+
+
+ What should I do if I hit a bug? +

+ Update REA, restart your agent and retry + the same task. A recent release may already fix the problem. +

+

+ If it persists, + open an issue + with your REA version, operating system, target type, steps to + reproduce and error output. Include the provider name when the + problem involves native analysis. +

+
+
+
+ +
+

Data and sharing

+
+
+ Does REA upload my app? +

+ REA analyzes targets on your machine. Your agent receives the + results, and its model provider's data policy applies to those + results. +

+
+
+ How can I share an example or contribute? +

+ 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 + issue + or + pull request. Short code excerpts and figures help others follow the + investigation. +

+

+ Bug reports, feature requests, documentation and code + improvements are welcome too. You can also discuss an example + in the community. +

+
+
+
+
+
+
+ +

+ Top + + diff --git a/website/public/get-started/index.html b/website/public/get-started/index.html index be8b31d02..042c74c45 100644 --- a/website/public/get-started/index.html +++ b/website/public/get-started/index.html @@ -24,8 +24,8 @@ @@ -367,6 +367,10 @@ npx rea-agents@latest setup

The report gives the failed check and a suggested next step.