What REA can do, what it can do only under conditions, and what it does not support
A capability matrix for REA from its docs at a pinned commit: built-in static paths, paths that need a provider or change state, unsupported targets, and how to read Evidence and its unknowns.
“Reverse Engineer Anything” is a name, not a specification. What REA actually covers depends on the kind of target, the operating system, which external tools you have installed and licensed, and whether the work only reads files or runs something. This post sorts that out into three groups: possible, possible only under conditions, and not supported or out of scope.
It is part 2 of a four-part series that follows the overview:
- What recent write-ups actually tested
- Capabilities and limits (this post)
- Strengths, trade-offs and where it might go
- Getting started safely
Observation date: 14 October 2026. Everything below comes from REA’s official documentation pinned to commit 29d3dcb on the main branch, and from the 6.4.0 release. It is what the project documents, not what Motitory measured: we did not run REA. The full, current list is the README’s capability table; this post picks the rows most people will meet and leaves the rarer targets to it.
First: which REA do you have?
Before any matrix, there is a version question, because “REA” can mean three different things at once.
- The npm release and main are not the same. The 6.4.0 package and the main branch differ, and a feature that is only on main needs a source build or a later release (installation: released package and main).
- An MCP setup is pinned to the version you set it up with. Running
@latestpicks whatever package is published at that moment; an MCP client configuration keeps using the version it was set up with until you change it. - What is listed is not what is available. A tool appearing in
tools/listdoes not mean it works on your machine. The docs say actual availability comes from the connected session, inbinary_session.result.tool_availability, which reflects the providers and platform you really have (identity and discovery).
So when a blog post, including this one, says “REA can do X”, the honest reading is “the docs at some commit say X is possible with some providers”. Check your own session.
The matrix
| Target or workflow | Status | What it needs | Static or runtime | Can change state | What can stay unknown |
|---|---|---|---|---|---|
| JavaScript and Electron bundles | Possible, built in | No native provider | Static; does not run the app | No | Minified code, dynamic imports, computed paths, missing source maps, native module boundaries |
| .NET assemblies | Possible, built in | No native provider | Static metadata and CIL | No | Reflection, code generated at runtime, what P/Invoke calls actually do |
| Native executables, deep pseudocode and cross-references | Conditional | Hopper, Ghidra or IDA, installed by you, under their own licences | Static | The target does not run; the provider may keep its own project files | Decompiler output is not source; types and indirect calls are inferred |
| Native executables, light inspection | Conditional, limited | GNU objdump or Rizin | Static | No | Much less than a full decompiler |
| Android APK | Conditional | JADX and a JDK | Static | No | Obfuscation, code loaded at runtime, native libraries |
| Android device | Conditional | ADB and a device you control | Runtime | Yes: can push, install, uninstall, start and stop apps | Only what happened while observed |
| Browser scenario | Conditional | A Chrome-family browser via CDP or Playwright | Runtime | Yes: navigates, clicks, types, changes storage, network and application state | Only the captured interval |
| Existing HAR or SAZ capture | Possible | A capture file you already have | Static parsing | No | Whatever the capture did not record |
| Fresh proxy capture | Conditional | A proxy path you set up | Runtime | Yes, and it records traffic that may include other people’s data | Only the captured interval |
| Firmware images | Conditional | Binwalk or Unblob | Static, but writes extracted files | Writes extraction output to disk | Encrypted or custom filesystems |
| Frida instrumentation | Conditional, high risk | Frida | Runtime | Yes: the injected script runs with the target process’s access to memory, files and network | The target’s state afterwards may be uncertain |
| Windows process capture | Not supported at this commit | — | — | — | — |
| Ghidra on Windows x64 | Experimental, read-only | Ghidra | Static | — | Marked experimental in the docs |
The sources for these rows are the capability table, do I need Hopper, Ghidra or IDA? and the local-effects section of the MCP contracts.
Two rows deserve a second look. The only paths that need nothing extra are the JavaScript/Electron and .NET static ones, and they are also the only ones the two public independent runs touched (part 1). And for native code, REA is a bridge to Hopper, Ghidra or IDA, not a replacement for them: without one of those, deep pseudocode and cross-references are not available, and objdump or Rizin give you much less.
Out of scope, whatever the tooling
REA’s responsible-use section puts these outside supported use: bypassing DRM, licence checks or anti-cheat; making cheats; bypassing authentication or bot protection without authorisation; and copying proprietary code or assets. That is not a technical limit that a future provider might lift. It is the project saying it does not support that use.
Seven constraints that cut across every row
The table has one row per target, but whether something works for you is decided by constraints that run across all of them.
- Provider. Many rows depend on an external tool. REA does not silently install the big ones; you install, license and update them.
- Operating system. Support differs by platform. Windows process capture is unsupported and the Windows Ghidra x64 path is experimental at this commit.
- Licence. REA’s MIT licence covers REA. Hopper and IDA are commercial and keep their own terms, and every provider has its own (third-party tools and licences). None of them gives you rights to the target. Analyse only what you own or are explicitly authorised to analyse; this post is not legal advice.
- Authority. A runtime path acts with real permissions: the browser has your session, the ADB connection controls the device, a Frida script runs inside the process. REA’s security policy is explicit that REA is not a sandbox.
- Static or dynamic. Static paths read bytes and do not run the target. Dynamic paths observe a run, so they see only what happened during it.
- Side effects. Dynamic paths can create and delete files, install and remove apps, send requests and change stored state. MCP annotations such as
destructive,executesForeignCodeandmutatesDeviceare hints for your client; the per-call approval is enforced by the client or host, not by REA (local effects). - Data flow. Analysis runs locally, but the agent sends tool results, which can include strings, decompiled code and captured traffic, to its model provider. “Local” describes where the tools run, not where the results end up.
Reading Evidence: what an answer does not say
REA returns results in an Evidence structure with identity, coverage, limitations and unknowns (tool results). That structure is the most useful part of REA and also the easiest to misread.
- An empty list is not proof of absence. If a facet is unavailable or partial, or coverage is not declared, an empty array just means nothing was found in what was looked at. A partial or unknown call list that comes back empty does not show the function makes no calls.
- A changed function text may not be a changed function. Comparing function text across builds can show differences that come only from moved addresses or regenerated names. And the reverse: identical observed control-flow properties are not the same thing as identical behaviour.
- Big answers come back by reference. The default stdio result budget is 10 MiB. Above that, complete Evidence can be kept and the call returns a resource-constraint reference that you page through or summarise. HackerNoon’s run in part 1 hit exactly this.
- The target can talk back. Results can contain content the target controls, such as strings or a provider’s error output. The docs say not to treat it as instructions to the agent (untrusted target content). A string in a binary that says “ignore previous instructions” is data.
What no result proves
A few conclusions need saying plainly, because demos often imply them.
- Static analysis does not prove runtime behaviour. It shows what the code could do, not what it did on a given run.
- Pseudocode is not the original source. It is a decompiler’s reconstruction.
- Equality on some checks is not equivalence. Matching static properties, output that looks like source, or a reimplementation passing a rules test does not show the two behave the same in every case. A test you wrote from the same investigation is not an independent oracle.
- None of it says who owns what. Recovering how something works does not give rights to it.
Part 3 takes these same facts and asks what they make REA good and bad at, and where things might go.
References
- REA at commit
29d3dcb: what you can analyse, do I need Hopper, Ghidra or IDA?, installation: release and main - MCP contracts: identity and discovery, tool results, request scope and local effects, untrusted target content
- Security boundary; disclaimer: responsible use, results and generated output, third-party tools and licences
- Release: rea-agents-6.4.0
Links and content checked on 14 October 2026.