rea 逆向 Electron 应用实战:从 app.asar 静态分析到功能重建的完整流程
【免费下载链接】reaReverse engineer anything with agents, from app behavior down to native binaries.项目地址: https://gitcode.com/GitHub_Trending/rea2/rea
rea 把逆向能力以 MCP 交给 AI 助手:零逆向引擎,只读 Electron 安装包即可还原模块、IPC 通道与进程边界。本文给出从 app.asar 到功能重建的完整走法。
一、先看全局:rea 的"四段证据链" 🧭
rea 逆向 Electron 应用不是一步出源码,而是把结论拆成四段、每段独立负责的取证:
| 阶段 | 负责回答什么 | 产出什么证据 |
|---|---|---|
| 静态解析 | 代码里有什么:模块、导入、IPC 通道、Electron 边界 | 内容寻址的 JavaScript Application Graph,每条边带来源与置信度 |
| 运行时捕获 | 跑起来后实际加载了哪些脚本、走了哪些通道 | 脚本稳定身份、DOM 结构、IPC 参数形状等捕获记录 |
| 静动调和 | 运行时实例对应静态图里的哪个节点 | 跨层 observed_as 边,以及 loaded / ambiguous / mismatch 分类 |
| 特征追踪 | 一个功能从种子出发能到达哪些代码 | 完整可达子图、终点路径与 native 交接点 |
四段各自独立,静态结论绝不冒充运行时结论。
二、从 0 到 1:装好并跑出第一个分析结果
前置条件只有 Node.js 22.19+(或 24.11+/26+)与 npm,静态 JavaScript 分析不需要任何逆向引擎。
动手清单:
# 方式一:把 AI 助手(Claude Code、Codex、Cursor、Gemini CLI 等)注册为 MCP 客户端 npx rea-agents setup # 方式二:跳过 Agent,CLI 直跑;目标可以是解压目录,也可以是 app.asar npx -y rea-agents@latest analyze-javascript-application /absolute/path/to/app --jsonElectron 是首选靶子:业务逻辑几乎全部是app.asar里的 JavaScript 字节,只读不跑就能全量静态解析;主进程 / preload / 渲染进程的三层边界,又恰好覆盖 rea 的 IPC 通道还原、contextBridge API 恢复与静动调和这些核心能力。
三、读静态图:先想好你要问什么
分析产出的是一张图,读图前先想清楚要问什么:
Q:应用从哪启动?A:package 与入口节点。package.json主入口、preload 路径、HTML script 入口,都是图里的显式节点。
Q:bundle 里有哪些模块?A:chunk 与 module 节点。Webpack/Rspack 的 chunk 注册与模块工厂以 AST 字面量恢复,静态/动态 import 与 CommonJS require 都画成边。
Q:页面能用哪些宿主能力?A:contextBridge 与 BrowserWindow 节点。暴露的 API key、成员路径、webPreferences配置均带源码位置。
Q:页面调了哪些 IPC,谁在主进程应答?A:IPC channel 与 handler 节点。renderer 的 send/invoke 与主进程 ipcMain.on/handle 按字面量通道配对。
Q:有没有原生插件?A:native add-on 与 export 节点。.node文件的请求路径与导出成员名被恢复,是深挖二进制的入口。
Q:有没有 source map?A:source map 与原始源模块节点。本地声明、原始源文件名与内容摘要都有记录,但原始源只作静态证据。
每条事实还带两套"成色"标签:authority 分三级——artifact 字节、AST 分析、静态推断,越靠前越硬;epistemic state 分四态——observed / inferred / unknown / unavailable。IPC 配对刻意保守:一个invoke只有在同字面量通道上恰好有一个ipcMain.handle时才与之配对;运行时拼出的动态通道一律不配对;候选不止一个时只报ambiguous,边不画。规则细节见 docs/javascript-application-graph.md。
四、运行时求证:偷看与彩排两种方式 📹
静态图回答"代码里有什么",运行时观察回答"跑起来真的发生了什么"。rea 给两条通道。
偷看(被动观察):附加到已运行 Electron 的 CDP 端点(Chrome DevTools Protocol,浏览器的调试接口),不注入、不点击、不调 Electron API,返回 canonical 本地路径、frame 与 DOM 结构、脚本稳定身份与内容摘要、worker 清单和显式完整性声明。
彩排(主动场景捕获):rea 通过官方 Playwright Electron API 自己拉起应用并拥有其生命周期,按场景文件执行 click / wait / renderer-crash / deep-link 等动作;记录捕获范围内的窗口与 WebContents 身份、进程指标、IPC 通道与参数形状元数据——payload 值永不保留。启动有 60 秒截止,SIGINT/SIGTERM 会请求取消并等待清理。
rea inspect-electron-page http://127.0.0.1:9223 TARGET_ID --include-script-sources --json rea capture-electron-scenario scenario.json --json两类 Evidence 的 authority 不同,不能混用;reconcile-javascript-runtime负责把运行时实例绑回静态图。匹配规则按证据强度排序:
- 捕获源 SHA-256 + 唯一映射位置 → 内容与位置匹配;
- 无位置映射,但内容摘要全局唯一 → 仍可匹配,依据单独标注;
- 没有捕获字节,仅唯一映射路径 → 只有中等置信度的位置匹配。
多候选报ambiguous不画边;捕获字节与该路径的静态候选不符,则显式记mismatch——路径永远压不过摘要分歧。静态资产被分成loaded、resident-in-loaded-asset、not-observed-in-capture、unknown四类;not-observed-in-capture绝不等于"全局未加载",没观察到 ≠ 不存在。详见 docs/electron-observation.md。
五、把一个功能重建成可读代码:以剪贴板为例 📋
先看案例。对 Notion Desktop 的 preload 脚本做分析,rea 定位到contextBridge暴露的__electronApiAPI key,打包的 API 对象里有clipboard.write成员,参数是字面量通道notion:clipboard:write。顺通道追进主进程 bundle:handler 包装 → 剪贴板接收器 → 发送方检查适配器 → 最终落到clipboard.write(data)。完整链路记录在 website/evidence/notion-clipboard.md。
把这种"顺着一条链读到底"自动化的是trace-application-feature:种子可以是 node ID、route、string、API、IPC channel、module、native export 中的任一字面量,返回完整可达子图与终点路径。
rea analyze-javascript-application /absolute/path/to/app --json > application-evidence.json rea trace-application-feature ./trace-input.json --jsontrace-javascript-semantics再进一步做语义级溯源:闭包捕获、唯一解析的本地调用、参数/返回值流、Promise 链、EventEmitter 注册与派发、Node timers、node:child_process创建与所有权、配置来源与默认值、请求构造与消费方,全部静态恢复。
手里有两个版本时,compare-application-versions按五级配对模块:内容摘要 > 模块源摘要 > 节点身份 > source map 身份 > 结构指纹,低级别永不覆盖高级别的唯一匹配;每个模块归为 unchanged / added / removed / changed / unknown。compare-source-to-bundle则把历史源码与当前 bundle 对齐,识别 split / merged / duplicated。函数指纹刻意忽略局部变量名,但保留语法形状、字面量集、运算符与对象键——压缩改名因此不影响跨版本比对。
追踪走到.node边界时,结果会给出 native 交接点,下一步交给 Hopper / Ghidra 深挖:
六、怎么判断重建结果可信:三个验证 + 一条认知边界
能落盘再解析一遍吗?export-web-scripts把捕获的脚本写入全新目录并生成 manifest,再拿analyze-javascript-application重新分析导出文件——"捕获字节 → 落盘 → 重新静态解析"形成闭环(docs/website-script-export.md)。
和真实运行时对得上吗?npm run verify:javascript-runtime -- --application ... --runtime-evidence ...由操作者提供真实 Electron 运行时,演练编译后 CLI 与 stdio MCP 发现、页面/脚本检查、静动调和与主动观察,并在检查 IPC、renderer crash/reload、deep-link 与 blocked-effect fixture 前先做清理。
和原始字节/基准一致吗?官方 showcase 给出量化基准:DX-Ball 的音效 pan 计算重建通过 3,205 个原始 x86 用例,复现了编译函数全部 63 个字节;TH04 的弹幕环形角重建与历史编译器输出逐项对比。
认知边界一条,用表格说清:
| 类别 | 规则 |
|---|---|
| 观察 | AST 语法、artifact 字节、被动捕获给出的事实 |
| 推断 | 入口解析与调用关系;静态推断从不声称"运行时执行过" |
| source map 原始源 | 仅作静态证据,永不作运行时字节匹配的主证据 |
| 遗漏数未知 | omitted_count输出null,不猜 |
这条走法把 rea 逆向 Electron 应用变成可追溯、可复现、可交叉验证的工程能力:每条结论带证据、置信度与局限,重建结果再拿原始字节和行为验一遍。后续可以沿三条路继续:用compare-application-versions对比两个版本找差异,按 docs/ghidra-provider.md 对.node原生边界做二进制深挖,或用 docs/process-capture.md 的进程级捕获当行为探针。
【免费下载链接】reaReverse engineer anything with agents, from app behavior down to native binaries.项目地址: https://gitcode.com/GitHub_Trending/rea2/rea
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考