An agent can read a binary and tell you what it does. That is the easy part. The hard part is knowing whether the explanation is true. The best projects built with REA settle the question the same way: they rebuild a small piece of the program and test the rebuild against the original. This guide shows that method step by step so you can reuse it.
If you have not set REA up yet, start with our install and first-run guide. For examples of the method in the wild, see the top 10 projects built with REA.
TL;DR: the proof ladder
| Level | What you did | What it proves | Cost |
|---|---|---|---|
| 0 | Read the agent's explanation | Nothing yet | Free |
| 1 | Asked for evidence: addresses, constants, call chain | The claim is traceable | Low |
| 2 | Rebuilt the function in your language | You can express the logic | Medium |
| 3 | Differential tests on many inputs | Behavior matches on those inputs | Medium |
| 4 | Byte-exact compile comparison | Machine code matches | High |
| 5 | Verified against known source | Measures the tool's accuracy | Needs open source |
Most useful work stops at level 3. Level 4 needs the original toolchain. Level 5 only works when the source is public, but it is the only level that tells you how often the agent is wrong.
Why the explanation alone is not enough
Decompilers produce pseudocode, and pseudocode is an interpretation. The DX-Ball case study shows how this bites. The decompiler view of a sound helper showed only a call to __ftol() with no visible input. The instructions revealed the missing argument loaded from the stack. An agent that trusted the pseudocode alone would have explained a function whose key input it never saw.
Three failure types come up again and again:
- Hidden inputs. Arguments passed in registers or on the stack that the decompiler does not show.
- Wrong widths and signs. A 16-bit value treated as 32-bit, or a signed comparison read as unsigned.
- Reordered state changes. Side effects that happen in a different order than the pseudocode suggests.
A fluent, confident paragraph hides all three. A failing test does not.
Step 1: pick one function and one question
Narrow scope is the single biggest predictor of success. The official case studies each answer one question: one sound-pan calculation, one clipboard path, one bullet-ring angle. None says "rebuild the app."
Write the question as a sentence with an observable answer:
Given a brick's screen x coordinate, what pan value does the game send to the sound call?
If you cannot describe the expected output as a number, string or state change, the question is too vague to test.
Step 2: demand evidence before code
Ask the agent to investigate with REA and report findings with their evidence. A useful prompt:
Using REA, find the function that computes the pan value for a brick sound.
Show its address, the instructions that load each input, every constant you
read from memory, and the callers. Do not write code yet. List what you could
not confirm.
You want addresses, constants and call relationships, because those are the things a test can later confirm or contradict. REA returns pseudocode, assembly, strings, symbols, calls and references for native targets. Insist the agent cite the instructions, not only the pseudocode, so hidden inputs surface.
A test bench with a green probe touching a block, representing verification of a rebuilt function
Step 3: rebuild the function in plain code
Now ask for a small, typed implementation. In the DX-Ball case, the recovered rule converted a screen coordinate to a double, multiplied by 1.5625, subtracted 500.0, multiplied by a stored pan scale and truncated. That is short enough to read in one glance, which is the point.
Keep the rebuild boring:
- Use fixed-width integer types that match the original.
- Copy constants exactly, including floating-point values.
- Do not "improve" the logic. A faithful bug is still faithful.
Step 4: build a differential test
A differential test runs the original and the rebuild on the same inputs and compares outputs. You need a way to call the original. Options include running the original executable in an emulator or compatibility layer, calling the function in a harness, or replaying recorded inputs.
Design the inputs deliberately, not randomly only:
| Input group | Why |
|---|---|
| Boundaries | Minimum, maximum, zero, one |
| Every value of a small domain | DX-Ball covered every position from 0 to 640 |
| Several parameter settings | Pan scales of 0, 0.5, 1, 20 and minus 1 |
| Odd values | Negative numbers, overflow edges |
That design produced the 3,205 cases in the DX-Ball study. The number looks large, but it comes from a small grid, which is the reason it is cheap to run and hard to argue with.
Write a test harness that runs the original function and my C version on
every x from 0 to 640 at pan scales 0, 0.5, 1, 20 and -1, and prints any
mismatch with both outputs. Do not stop at the first failure.
Ask for all mismatches, not the first, because the pattern of failures usually points at the cause.
Step 5: treat every mismatch as a finding
When the outputs disagree, resist the urge to patch the test. Go back to the instructions and ask what you missed. Typical causes are a rounding mode, a signed shift, or an input the decompiler hid. Rerun the full grid after each fix so a repair does not break an earlier case.
This loop is the heart of the method. It also keeps the agent honest, because a model that is rewarded for passing tests will find real bugs, while one that is only asked to explain will not.
Step 6: go byte-exact if the stakes justify it
The DX-Ball project goes one level further. Per its README, it compiles each recovered function with the original Visual C++ 4.0 compiler and compares the machine code with the original. A byte-exact match means the entire function's code agrees after mapping addresses for calls and data, because the original and rebuilt programs place functions and globals at different addresses. The showcase reports all 63 bytes matching for the sound-pan function.
This level is expensive. The project documents a Linux workspace with Node.js, Wine with 32-bit support, Xvfb, CMake and a compiler, and setup scripts that download the JDK, Ghidra and the compiler. It is worth it when you are preserving a game or need legal-grade equivalence. It is overkill for learning how a clipboard bridge works.
Step 7: check the tool against known source
The cleanest accuracy test is to point REA at software whose source you can read. The hexgrab project did this: the author studied Microsoft PowerToys' Color Picker from its shipped binaries, then checked each finding against the public MIT-licensed source. By the README's count, REA got 8 of 9 findings fully right, and the findings are documented in the repository.
Do the same on your own code. Compile a small program you wrote, strip the symbols, ask the agent to explain it, and compare with your source. You will learn what kinds of mistakes your agent and provider make, which is worth more than any benchmark.
Step 8: write the report so a stranger can rerun it
Good reverse engineering reports share a shape. Copy it.
| Section | Contents |
|---|---|
| Target | Name, version, hash, how you obtained it |
| Question | One sentence |
| Evidence | Addresses, instructions, constants, call chain |
| Rebuild | The code and where it differs from the original on purpose |
| Tests | The input grid, number of cases, pass count |
| Not verified | Everything you could not confirm |
The "not verified" section is not weakness. Open Scrantic, the Rust Johnny Castaway engine, documents its deliberate deviations, such as full-frame redraw instead of dirty rectangles. That honesty is why a reader can believe the rest.
Common mistakes
- Testing only the happy path. Include boundaries and negative cases.
- Letting the agent write both the code and the oracle. The oracle must be the original program, not a second guess.
- Pinning nothing. Record the target version and hash, because addresses change.
- Claiming whole-program equivalence. One verified function is one verified function.
- Skipping the legal check. See our clean-room checklist before you publish.
For a skeptical look at how other agent decompilation claims hold up, read how AI agents decompile games: claimed vs verified, and the REA case-study breakdown for the full DX-Ball story. If you want to practice loops like this with an agent, our workshops cover agent workflows from setup to review.
Frequently asked questions
Why can't I just trust the agent's explanation? Pseudocode can hide inputs and misstate widths, and an agent can describe it fluently while being wrong.
What is differential testing? Running the original and your rebuild on the same inputs and comparing outputs.
What does byte-exact mean? The compiled rebuild produces the same machine code as the original function after address mapping.
Do I need the original compiler? No. Behavior tests alone are valuable; byte-exact comparison is an extra layer.
What belongs in the report? Target and hash, question, evidence, tests and what you could not confirm.
Related reading
- How to install and use the REA skill with Claude Code
- Top 10 projects built with the REA skill
- Reverse engineering is now a prompt: REA's case studies
- How AI agents decompile games: claimed vs verified
- Legal and clean-room checklist for AI reverse engineering
- What are agent skills? A complete guide
- Official: REA on GitHub · DX-Ball reconstruction · DX-Ball case study
Figures come from REA's showcase and the DX-Ball and hexgrab repositories as of October 19, 2026. Those projects are in progress and may change.
