rea

命令行工具

morluto/rea

让 AI 智能体逆向分析应用与二进制的 MCP 工具。

项目简介

REA 通过 MCP 将 AI 编程智能体接入逆向工程能力,无需源码即可分析原生二进制、JavaScript/Electron 应用、.NET 程序集和网站。可集成 Hopper 与 Ghidra 进行深度静态分析,本地运行并给出带证据与局限说明的结论,也可作为命令行工具独立使用。

README 预览

\n\n**English** · [简体中文](README_zh.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · [العربية](README_ar.md)\n\n# REA: Reverse Engineer Anything\n\n### One MCP for reverse engineering across binaries, applications, and runtime behavior.\n\n**See a feature you like. Understand how it works, down to the binary level.**\n\n[](https://www.npmjs.com/package/rea-agents)\n[](https://github.com/morluto/rea/actions/workflows/ci.yml)\n[](#tool-catalog-for-investigation)\n[](https://nodejs.org/)\n[](LICENSE)\n[](https://discord.gg/GkcryMnJDM)\n\n\n\n[Quick start](#quick-start) · [Current status](#current-status) · [Investigation model](#the-investigation-model) · [Tool catalog](#tool-catalog-for-investigation) · [Roadmap](#roadmap) · [How it works](#how-it-works)\n\nnpx rea-agents setup\n\n\n\n\n\n\n\n\n\n\n  \n    \n    Join the Reverse Engineering Community\n  \n  Discord · Q&A · Show and Tell\n\n\n\n\n\n\n\n\n---\n\nSee a feature in an app that you want in your own product? Ask your agent to investigate it with REA. It can inspect the app without its source code, explain how the feature works, show the evidence, and build a version for your project.\n\nREA connects your agent to tools for inspecting native binaries, JavaScript and Electron apps, .NET assemblies, and websites. You can also use the same tools from your terminal. Analysis runs locally, and results include the evidence and limitations behind each conclusion.\n\nSetup registers REA with your agent and installs matching workflow instructions. Native analysis can use an existing Hopper or Ghidra installation; setup can optionally install Hopper with approval. Static JavaScript analysis needs neither engine.\n\n## Quick start\n\n### Run setup (recommended)\n\nSet up REA with your agent:\n\n```bash\nnpx rea-agents setup\n```\n\nChoose which supported agents should use REA, then review the exact paths and changes before approving. Existing REA registrations are selected by default; newly detected agents are avail

常见问题 (5)

故障排除
为什么 Ghidra MCP 响应(例如 list_procedures)在仅约 20k 行时就会触发 10 MiB 的 resource_constraint 限制,以及如何修复重复的 raw_result 数据?

这是 REA ≤6.7.0 中的一个 bug:Ghidra 适配器(GhidraProviderClient.ts projectExecution)无条件地将 bridge 回复复制到 raw_result 中,尽管它与 normalized_result 逐字节相同。于是每条 Evidence 记录都携带了两次结果,而且由于 MCP 响应在文本和结构化内容中都嵌入了 Evidence,回复中包含了约 4 份副本——这使 10 MiB 响应预算内能容纳的清单数量减半(大型清单在约 20k 行时就会因 resource_constraint 而失败,而不是约 40k 行)。修复方法:升级到包含 PR #5355 的构建版本,该版本在 normalized_result 与 raw_result 逐字节相同时将 raw_result 设为 null(根据 AnalysisProvider.ts 和 docs/mcp-contracts.md 中的约定,raw_result 只应保存与 result 不同的提供方表示)。不会丢失任何数据,因为 wrapper 的 limitations 已经合并到 Evidence limitations 中。破坏性变更说明:通过 raw_result.value 解析 analyze_function 输出的客户端必须改用 normalized_result,因为对于这些操作,raw_result 现在为 null。

来源 Issue #5337
故障排除
为什么 rizin_debug_session_status 对 CJK 或 emoji 输出保留的内容会超过 16KB 的最近输出预算?

最近的帧历史记录是按码点数量而非 UTF-8 字节数来截断的,因此像"雪"这样的 3 字节 CJK 字符会使保留的大小变为原来的三倍(49,152 字节而非 16,384 字节),而且截断还可能拆散 emoji 的代理对,导致产生格式错误的 UTF-8。此问题已在 6.8.0 版本中通过 PR #5246 修复:请升级到 6.8.0+。该修复通过测量字节长度(例如 TextEncoder().encode)并仅在码点边界处截断,使 CJK 输出保持在 16,384 字节的预算范围内,并保证 emoji 前缀格式正确。

来源 Issue #5091
故障排除
为什么 Rizin 的 recent_output 在输出 CJK 或 emoji 内容时会超出其 16 KB 帧限制,以及如何修复截断问题并保留 3 倍的 UTF-8 字节预算?

根本原因:在 src/rizin/RizinDebugSessionManager.ts(第 1068-1078 行)中,最近帧的截断对 frame.text(一个已解码的 JS 字符串)进行切片,因此 String.prototype.slice 按 UTF-16 码元计数,而不是按字节计数。在 MAX_RECENT_FRAME_BYTES = 16 * 1024 的情况下,一个 3 字节的 CJK 字符只按 1 个码元计入,因此单个帧最多可保留 49,152 字节(预算的 3 倍),64 帧的环形缓冲区便从预期的 1 MiB 膨胀到 3 MiB。

修复:使用 Buffer 在字节层面进行切片,并回退 UTF-8 续字节(continuation bytes),这与 #startupCapturedOutput 在第 1046-1052 行已采用的方法相同:

const bytes = Buffer.from(frame.text, "utf8");
let end = Math.min(bytes.length, MAX_RECENT_FRAME_BYTES);
// avoid splitting a multi-byte sequence: back off continuation bytes (0b10xxxxxx)
while (end > 0 && (bytes[end] & 0xc0) === 0x80) end--;
const kept = bytes.subarray(0, end).toString("utf8");
const historyFrame =
  frameBytes > MAX_RECENT_FRAME_BYTES || frame.truncated
    ? `${kept}[recent frame truncated]`
    : frame.text;

注意:现有测试仅覆盖 ASCII(此时码元数 == 字节数),这正是该回归问题未被发现的原因——应添加 CJK/emoji 截断测试。此 issue(#5242)是 #5091 的重复;请在 #5091 中跟踪修复进展。

来源 Issue #5242
故障排除
如何修复 rea 在分析 React bundle 时出现的 'Owned JavaScript worker exhausted its heap' 错误?

这是 rea 的 JavaScript member-mutation pass 中的一个已知回归问题,由 PR #4243(提交 42fc6c53a)引入。循环检测从 bindings 移到了各个 initializer 上,因此别名循环(alias cycle)内部的结果永远不会被 memoize,分析过程会枚举 initializer 的顺序,在处理 React 风格的 bundle(playwright-core、Notion 渲染器、Next.js 的 framework-*.js chunk)时耗尽 worker 堆内存(即使设置为 4 GiB 也不例外)。

修复方法:
1. 升级到超过当前 npm 发布版本的版本。该 bug 存在于 rea-agents@6.7.0(当前 npm 最新版本)中,但已在 main 分支的提交 e4c3d7239 中修复。请安装 main 分支的构建版本(已在 58d6043 验证可用),而不是 npm 包。
2. 变通方案:锁定/降级到 #4243 之前的构建版本(提交 1bd5c5c87),该版本分析相同文件仅需约 1–2 秒。

注意:提高堆内存上限无济于事——搜索呈指数级增长,约 17 秒内就会耗尽 4 GiB。修复后,相同文件约在 10 秒内完成,RSS 约为 430 MB,且不会出现因资源约束导致的 unknowns。

来源 Issue #4348
故障排除
如何修复 match_native_functions 拒绝处理大型函数清单时出现的 'AnalysisResourceConstraintError'(96 MiB 限额)?

match_native_functions(仅存在于 main 分支,未包含在 6.7.0 版本中)每次调用收取固定的 96 MiB 表示配额,拒绝处理每侧超过约 1 万行的 Ghidra 格式清单(纯 address+name 行超过约 1.95 万行时拒绝)。修复内容:(1) PR #7108 修正了计费逻辑,使共享清单的 Evidence ID 仅计费一次,而非按函数逐个计费,在 96 MiB 默认值保持不变的情况下,将上限提升至每侧约 2.2 万行 Ghidra 格式数据。(2) PR #7112 新增了覆盖项:在配置中设置 native.matching_representation_bytes(由 rea setup 复制),或设置 REA_NATIVE_MATCHING_REPRESENTATION_BYTES 环境变量——默认 96 MiB,最大 1 GiB。在 512 MiB 下,每侧 50,000 行成功完成匹配(CLI:8.7 秒,峰值内存 1.34 GB;MCP:2.7 秒)。拒绝仍然不可重试,并在 details.limit 中指明限制值和覆盖项。

来源 Issue #6406