dsh-plugin-rea 1.0.6 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.zh-CN.md CHANGED
@@ -4,136 +4,237 @@
4
4
 
5
5
  [English](README.md) · **简体中文**
6
6
 
7
+ > **这是哪个版本?2.x —— 而 `main` 就是它。** 2.x 自己准备运行时(Node、REA CLI、JDK、Ghidra)再把那一行接好:
8
+ > 装插件 → 跑一次 `scripts/setup.mjs` → 重启 dsh。
9
+ > **1.x** 是更早的纯配置适配器 —— 它假设 `rea` 在 PATH 上、Ghidra 由你自己装好 —— 保留在
10
+ > [`v1` 分支](https://github.com/czcdr/dsh-plugin-rea/tree/v1),npm 上仍是 `dsh-plugin-rea@1.0.6`。
11
+ > 完整对比:[两条线:1.x 与 2.x](#两条线1x-与-2x) · 升级:[从 1.x 升级](#从-1x-升级)。
12
+
7
13
  把上游 **[REA — Reverse Engineer Anything](https://github.com/morluto/rea)** 的 MCP 服务接入
8
14
  **DeepSeek Harness**(dsh),让它的工具在会话里以 `mcp__rea__*` 出现。
9
15
 
10
- ![dsh-plugin-rea:会话经官方 MCP 客户端行调用本机 rea mcp,再把 Evidence 带回会话](assets/screenshot-1.png)
16
+ ![dsh-plugin-rea:会话经官方 MCP 客户端行启动本包供给的 shim,再由 shim 拉起 bundle 内置的 REA,最后把 Evidence 带回会话](assets/screenshot-1.png)
11
17
 
12
18
  ## 这是什么
13
19
 
14
- 一个**纯配置型 Cordis bundle**。`package.json` 声明 `dsh.bundle.patch`,该 patch 插入一行官方 MCP
15
- 客户端插件(`@deepseek-ai/dsh-mcp-client`)的记录,指向你本机已安装的 `rea mcp`(stdio)服务。
16
- 本仓库不含任何分析代码。
20
+ 一个**带供给层的 Cordis bundle**。`package.json` 声明 `dsh.bundle.patch`,该 patch 插入一行官方 MCP 客户端
21
+ 插件(`@deepseek-ai/dsh-mcp-client`)。这一行用当前运行的 Node 可执行文件启动 `bin/rea-shim.mjs`,由 shim
22
+ 读取 `scripts/setup.mjs` 写下的本机状态,再拉起它供给的 REA CLI。这里没有任何分析代码,且**发布出去的
23
+ patch 里不含任何机器路径**。
17
24
 
18
- > **第三方适配。** 本仓库不是 REA 项目的组成部分,不分发 REA 的任何代码,也不由 REA 作者维护;
19
- > 它只组合一行配置。
25
+ > **第三方适配。** 本仓库不属于 REA,不携带 REA 的任何代码,也不由 REA 作者维护;它只组装一行配置,
26
+ > 并从上游官方源拉取上游自己的发布物。
20
27
  > 上游:[github.com/morluto/rea](https://github.com/morluto/rea)(MIT)·
21
- > [文档](https://github.com/morluto/rea#what-you-can-analyze) ·
22
28
  > [中文文档](https://github.com/morluto/rea/blob/main/README_zh.md#可以分析什么) ·
23
29
  > [rea.tools](https://rea.tools/) · npm 包 `rea-agents`。
24
- > REA 自身的问题请提到上游;**本插件**的问题提到
25
- > [本仓库 Issues](https://github.com/czcdr/dsh-plugin-rea/issues)。
30
+ > REA 自身的问题请提给上游;**本插件**的问题提到
31
+ > [本仓库 issues](https://github.com/czcdr/dsh-plugin-rea/issues)。
26
32
 
27
- **它只增加两件事**:把工具注册成 `mcp__rea__*`,以及让引擎环境变量(`GHIDRA_INSTALL_DIR` 等)
28
- 只作用于这个 MCP 子进程,而不是整个 harness。
33
+ **它只做三件事**:注册 `mcp__rea__*` 这批工具名;把每台机器各自的引擎环境
34
+ (`GHIDRA_INSTALL_DIR`、`JAVA_HOME`、`REA_ADB_PATH`、`REA_APKTOOL_COMMAND`、`REA_JADX_MCP_JAR`、
35
+ `REA_BROWSER_EXECUTABLE` 等)限定在那一个 MCP 子进程上、而不是整个 harness;以及把这些组件装到盘上。
29
36
 
30
37
  ## 能做什么、不能做什么
31
38
 
32
- 分析能力由上游提供;这里只复述上游自己的契约,避免预期错位。
33
-
34
- - **无法完整还原源代码。** 上游对原生二进制返回的是**伪代码与汇编**,对 Android APK 返回
35
- **反编译的方法**,对 JEB 单元返回**伪代码**,对 JavaScript/Electron 返回**模块及其关系**。
36
- 上游的工具契约明确写着:伪代码是反编译器输出,**不是原始源码**,且与其他提供方的输出
37
- **不保证文本等价**。
38
- - 实践中不可恢复的内容:原始标识符命名、类型、注释、宏与模板展开、构建脚本与资源;
39
- 优化(内联、指令重排)、去符号(strip)、混淆、加壳与 VM 保护只会让可读性更差。
40
- - 每条结论都自带**置信度与限制**(`observed` / `derived` / `inferred`,另有 limitations 列表):
41
- 请把它们当作证据使用,而不要当作「已还原的源码」。
42
- - 适合做:理解行为、定位实现、互操作与兼容实现、安全审计、迁移参考。
43
- **要拿到真正的源码,请走正规渠道**——上游代码仓库、厂商授权,或厂商自己的 SDK。
39
+ 分析能力属上游,本节只是复述上游自己的契约,避免预期错位。
44
40
 
45
- ## 实测版本
41
+ - **它无法还原完整源码。** 原生二进制上游给的是*伪代码与汇编*,APK 是*反编译方法*,JEB 单元是*伪代码*,
42
+ JavaScript/Electron 是*模块及其关系*。上游的工具契约明确写着伪代码"是反编译器输出,不是原始源码,
43
+ 也不与另一 provider 的输出文本等价"。
44
+ - 实际上拿不回来的:原始标识符名、类型、注释、宏与模板展开、构建脚本与资源。优化(内联、重排)、
45
+ 符号剥离、混淆、加壳、VM 保护只会让输出更差。
46
+ - 每个结果都带**置信度与限制**(`observed` / `derived` / `inferred`,外加一份明确的 limitations 列表)。
47
+ 请当证据读,别当还原出来的源码。
48
+ - 适合:理解行为、定位实现、互操作与兼容重写、安全审阅、迁移参考。要拿真正的源码,走正规渠道 ——
49
+ 上游仓库、厂商授权,或厂商自己的 SDK。
46
50
 
47
- 作者机器,2026-10-12/13:
51
+ **供给解决不了的部分。** 这些是上游的宿主门槛,不是本插件漏配了什么:
48
52
 
49
- | 组件 | 版本 |
53
+ | 能力 | 门槛 |
50
54
  |---|---|
51
- | REA(`rea-agents`) | **6.4.0** |
52
- | DeepSeek Harness | 桌面运行时 **0.2.0-rc.2**,自带 dsh CLI 0.1.7-rc.2 |
53
- | `@deepseek-ai/dsh-mcp-client`(行提供方) | 由 harness 自带;npm 最新 `0.0.1-rc.1` |
54
- | Ghidra | 12.1.4(REA 当前接受 12.1.x) |
55
- | Node.js | 24.21.0(REA engines:`^22.19.0 \|\| ^24.11.0 \|\| >=26.0.0`) |
56
- | 主机 | Windows 11 x64 |
57
-
58
- 发布用的这一行**实测跑通过**:`list_documents` 在 `cmd.exe` 形式下正常应答,`open_binary` 走
59
- `ghidra` 提供方成功,而引擎目录仅来自本机 profile 覆盖。
55
+ | Hopper provider | 仅 macOS |
56
+ | IDA provider | 需要你自己的 IDA 与 `REA_IDA_MCP_CONFIG`;REA 从不启动 IDA |
57
+ | 固件 `binwalk` / `unblob` | 仅 Linux |
58
+ | Wakaru JS 还原、pwntools 的 ELF/宕机转储路径 | 仅 Linux x64 |
59
+ | pwndbg / gdb 核心上下文 | 仅 Linux、macOS |
60
+ | 原生 mitmproxy 抓包 | 仅 Linux(`REA_MITMDUMP_COMMAND`);HAR 不需要引擎 |
61
+ | 苹果工具链(Mach-O、plist、资源目录、LLDB) | 仅 macOS |
62
+ | `capture_process_scenario` | 仅 Linux/macOS 的 PTY |
63
+ | apktool(Android 资源解码) | 仅当 `REA_APKTOOL_COMMAND` 指向 Node 能**直接执行**的文件时才可用:上游用 `execFile` 不加 shell 直接起这个命令,而 Windows 上 Node 无法直接执行 `.bat`/`.cmd`(EINVAL)。本包按上游文档接的是官方 `apktool.bat`,所以在 Windows 上它拿不到版本、该能力不可用;JADX 走 jar,不受影响 |
64
+
65
+ ## 两条线:1.x 与 2.x
66
+
67
+ | | **2.x** —— 当前这条,`main` | **1.x** —— [`v1`](https://github.com/czcdr/dsh-plugin-rea/tree/v1) |
68
+ |---|---|---|
69
+ | 是什么 | 适配器**加供给**:自己准备 Node、REA CLI、JDK、Ghidra,再把那一行接好 | 纯配置适配器:一行 MCP 行,指向你自己装好的 `rea` |
70
+ | 前置 | 运行时什么都不用装 —— 缺什么它去取(`--reuse` 则复用机器上已有的 Ghidra/JDK) | Node.js(满足 REA engines)、`npm i -g rea-agents`,原生分析还要 Ghidra 12.1.x |
71
+ | 首次运行 | 先跑一次 `scripts/setup.mjs`(或引导脚本),再重启 dsh | 不用跑任何东西 |
72
+ | 那一行启动什么 | 当前 Node 可执行文件 + `<DSH_HOME>/plugins/rea-bundle/bin/rea-shim.mjs`(由 shim 读本机状态) | Windows 上 `cmd.exe /c rea mcp`,macOS/Linux 上 `rea mcp` |
73
+ | 机器状态 | `<DSH_HOME>/plugins/rea-bundle/` —— `bundle.json`、`vendor/`、`cache/` | 你自己的 REA 与 Ghidra 安装 |
74
+ | 安装 | `dsh plugin --profile <profile> add dsh-plugin-rea`(npm `latest` ≥ 2.0.0) | `… add dsh-plugin-rea@1.0.6`,或 `github:czcdr/dsh-plugin-rea#v1.0.6` |
75
+
76
+ 两条线发布的是**同一种 patch 形态**(一条 `insert` 行,`@deepseek-ai/dsh-mcp-client`),对外也提供同一套
77
+ `mcp__rea__*` 工具面;区别只在"谁准备运行时"。从 1.x 到 2.x 只要两条命令,见
78
+ [从 1.x 升级](#从-1x-升级)。
60
79
 
61
80
  ## 安装
62
81
 
63
- **前置条件**
82
+ **前置什么都不用装。** 在干净的 Windows x64 机器上:
64
83
 
65
- - Node.js 满足 REA 要求(`^22.19.0 || ^24.11.0 || >=26.0.0`)。
66
- - 全局安装 REA CLI:`npm i -g rea-agents`。
67
- - 原生分析需要 Ghidra **12.1.x**(Hopper / IDA 为替代方案,各自需授权);
68
- 静态 JavaScript/Electron 与 .NET 分析不需要引擎。
84
+ ```
85
+ powershell -ExecutionPolicy Bypass -File scripts\rea-bundle-bootstrap.ps1 -Reuse
86
+ ```
69
87
 
70
- **安装插件**
88
+ `-Reuse` 会复用你已有的 Ghidra/JDK;去掉它则从官方发布下载两者(约 775 MB,逐个校验和验证)。然后为你的
89
+ profile 安装插件:
71
90
 
72
91
  ```
73
- dsh plugin --profile <profile> add github:czcdr/dsh-plugin-rea
74
- # 或从 npm 安装:
75
92
  dsh plugin --profile <profile> add dsh-plugin-rea
93
+ # 或钉住这个版本,而不是跟着 npm latest 走:
94
+ dsh plugin --profile <profile> add github:czcdr/dsh-plugin-rea#v2.0.0
76
95
  ```
77
96
 
78
- [Releases](https://github.com/czcdr/dsh-plugin-rea/releases) 附带预构建 tarball(资产名不带版本号,
79
- 链接不会失效)。
97
+ > **Electron 宿主(DeepSeek Harness 桌面版)的 profile 由应用独占。** 那种机器上 `dsh plugin --profile desktop …`
98
+ > 会被 CLI 直接拒绝(`profile "desktop" is managed exclusively by the Electron application`),请改用**应用内的
99
+ > 插件管理器**安装/更新;上面这条 CLI 只适用于你自己用 CLI 建的非 `desktop` profile。
80
100
 
81
- ## 配置——通常什么都不用改
101
+ 如果机器上已经有 Node,可以跳过引导脚本直接供给:
82
102
 
83
- 发布出去的那一行**不含任何机器相关路径**:
103
+ ```
104
+ node scripts/setup.mjs --reuse # 或先 --dry-run 看计划
105
+ ```
84
106
 
85
- - Windows:`command: cmd.exe`、`args: ['/c', 'rea', 'mcp']` —— npm 的 shim 是 `.cmd`,必须经 shell。
86
- - macOS/Linux:`command: rea`、`args: ['mcp']` —— 见
87
- [`examples/cordis.patch.posix.yml`](examples/cordis.patch.posix.yml)。
107
+ 反过来**先装插件**也可以,但要分两步:发布的行指向 `<DSH_HOME>/plugins/rea-bundle/bin/rea-shim.mjs`,
108
+ 而那个文件**只有 setup 会创建**——所以在第一次供给之前,该行会以 `MODULE_NOT_FOUND` 退出,也就没有
109
+ 任何东西能去启动后台供给(harness 本身不受影响:`failOnStartupError: false` 是刻意的)。先手动跑一次
110
+ `node scripts/setup.mjs`;此后 shim 就位,之后每一次「状态缺失」都由它自己发现并在后台补供给。
88
111
 
89
- 唯一可选的是分析引擎。REA 从环境读取 `GHIDRA_INSTALL_DIR`,二选一:
112
+ ## 配置 —— 不需要
90
113
 
91
- 1. 设为**系统级环境变量**,然后重启 harness(让 MCP 子进程继承);
92
- 2. 只为这个 MCP 子进程指定 —— 见
93
- [`examples/cordis.patch.with-env.yml`](examples/cordis.patch.with-env.yml)。
114
+ 发布的那一行**不含任何机器路径**:
94
115
 
95
- 两种方式都不需要写死路径:客户端会把父进程环境传给子进程(只剔除名字像密钥的变量),
96
- 而补丁方言支持 `!!js` 表达式,所以 `GHIDRA_INSTALL_DIR: !!js process.env.GHIDRA_INSTALL_DIR`
97
- 同样可用。
116
+ ```yaml
117
+ - insert:
118
+ - id: mcp-rea
119
+ name: '@deepseek-ai/dsh-mcp-client'
120
+ config:
121
+ serverName: rea
122
+ transport: stdio
123
+ command: !!js process.execPath
124
+ args:
125
+ - !!js "(process.env.DSH_HOME && process.env.DSH_HOME.trim() !== '' ? process.env.DSH_HOME : (process.env.USERPROFILE || process.env.HOME || '') + '/.dsh') + '/plugins/rea-bundle/bin/rea-shim.mjs'"
126
+ - mcp
127
+ env:
128
+ ELECTRON_RUN_AS_NODE: '1'
129
+ failOnStartupError: false
130
+ ```
98
131
 
99
- **机器相关值不要写进插件。** 用你自己的 profile `cordis.patch.yml` **按 id 覆盖**这一行即可;
100
- 该文件只在你本机、永不随插件发布:
132
+ 这一行里有四个"承重"细节,而且**都先以 bug 的形式出现过**:
101
133
 
102
- ```yaml
103
- - id: mcp-rea
104
- config:
105
- env:
106
- GHIDRA_INSTALL_DIR: '<你的 Ghidra 12.1.x 目录>'
134
+ - **`!!js` 标量必须加引号。** 裸标量里同时出现 `? ` 和 `: ` 时,它就不是一个标量了:YAML 会把它读成显式键值对,于是 loader 拿到的是一个 **mapping** 而不是表达式节点。用 harness 自己的方言实测(`JSON_SCHEMA` + `app.asar` 里的 `!!js` 类型),不加引号时 `args[0]` 变成 `{"[object Object]": "..."}` —— 一个行根本无法用来启动的对象。加引号消除歧义,内部的 JS 字符串改用单引号。
135
+ - **必须用正斜杠,不能用反斜杠。** YAML 单引号标量会保留 `\` 字面量,接着 JavaScript 会把它吃掉:`'\plugins'` 不是路径而是 BEL 控制字符,`'\rea-bundle'` 变成回车、`'\bin'` 变成退格 —— 路径被静默摧毁。正斜杠在 Windows 与 POSIX 上都成立。
136
+ - **`DSH_HOME` 的兜底是 `<home>/.dsh`,不是 `<home>`。** shim、`setup.mjs`、`bootstrap.ps1` 三者都把未设置的 `DSH_HOME` 解析到 `<home>/.dsh/...`;兜底少这一层,行就会指向供给永远不会写的位置 —— 而在 `DSH_HOME` 恰好被设置的机器上,这个错误完全不可见。
137
+ - **`!!js` 表达式里没有 `path`/`require`**:`ctx` 是 loader 作用域,所以 DSH_HOME 的兜底写成纯字符串拼接。
138
+
139
+ `npm run bundle:audit` 会把前三条钉住:它用「`DSH_HOME` 未设 / 为空 / 已设」三种情形求值这个表达式,并拒绝会被 YAML 读成 mapping 的裸标量。
140
+
141
+ `ELECTRON_RUN_AS_NODE` 只在 harness 本身跑在 Electron 上时才有意义;对纯 Node 宿主无害,而显式写出来胜过依赖它恰好能在子进程环境清洗中存活。
142
+
143
+ `command` 是当前运行的 Node 可执行文件,`args[0]` 由 `DSH_HOME` 在启动时算出,所以同一份 patch 在
144
+ Windows、macOS、Linux 上都成立,且不依赖 PATH 上的 `rea`。所有机器相关的真相都放在
145
+ `<DSH_HOME>/plugins/rea-bundle/bundle.json`,由 setup 写入,可随时查看:
146
+
147
+ ```
148
+ node bin/rea-shim.mjs --shim-status # 解析到的路径、版本、校验状态
149
+ node bin/rea-shim.mjs --shim-print-env # MCP 子进程将看到的环境变量
107
150
  ```
108
151
 
109
- 同一 profile 内 `serverName: rea` 只能有一条记录。
152
+ 这两个命令在**插件目录**(checkout 副本)或 `<DSH_HOME>/plugins/rea-bundle`(镜像副本)里跑都给出同一
153
+ 答案:checkout 副本按与 setup 相同的规则解析供给位置,镜像副本用自身位置(因为 MCP 子进程的环境里
154
+ `DSH_*` 会被剥掉,它不能依赖 `DSH_HOME`)。
155
+
156
+ 设 `REA_BUNDLE_AUTO_PROVISION=0` 可关掉首次运行的后台自动供给。
157
+
158
+ 想在本机把这一行改成别的启动命令(例如用你自己全局装的 `rea`),从 profile 自己的
159
+ `cordis.patch.yml` 按 id 覆盖即可 —— 那个文件是机器本地的,永不发布。一个 profile 里只允许一行使用
160
+ `serverName: rea`。
110
161
 
111
162
  ## 验证
112
163
 
113
- 调用任一 `mcp__rea__*` 工具:`binary_session` 会给出引擎检查项
114
- (configuration / installation / headless / native_decompiler / java),应全部 `ok: true`;
115
- 随后 `open_binary` 打开一个 PE → `binary_overview` → `procedure_pseudo_code`。
164
+ 随便发一个 `mcp__rea__*` 调用 —— `binary_session` 会报引擎各项检查
165
+ (`configuration` / `installation` / `headless` / `native_decompiler` / `java`),应当全为 `ok: true`。
166
+ 然后 `open_binary` 一个 PE、`binary_overview`、`procedure_pseudo_code`。
116
167
 
117
- ## 范围与注意
168
+ 供给本身结束时也会跑两道探针:`rea doctor --json`(如实报告,并点名未满足项),以及**与 MCP 行完全相同的
169
+ shim 启动**。
118
170
 
119
- REA 在 6.4.0 暴露 170+ 个工具,注入后每个会话的工具列表都会变大;行内设置
120
- `failOnStartupError: false`,因此 REA 缺失也不会阻塞 harness 启动。部分 REA 工具会启动进程、
121
- 写文件、访问网络,按 DSH 的权限策略执行。请仅分析你已获得授权的目标。
171
+ ## 实测环境
122
172
 
123
- ## 更新:两件事,且都要手动
173
+ 作者机器,2026-10-13 / 14:
174
+
175
+ | 组件 | 版本 |
176
+ |---|---|
177
+ | REA(`rea-agents`) | **6.4.0**(170 个工具) |
178
+ | DeepSeek Harness | desktop runtime **0.2.0-rc.2**,内含 dsh CLI 0.1.7-rc.2 |
179
+ | `@deepseek-ai/dsh-mcp-client`(行 provider) | 随 harness 打包 |
180
+ | Ghidra | 12.1.4 |
181
+ | JDK | Temurin 21(供给)/ Microsoft OpenJDK 25.0.4(复用) |
182
+ | Node.js | 24.21.0(REA engines:`^22.19.0 \|\| ^24.11.0 \|\| >=26.0.0`) |
183
+ | 宿主 | Windows 11 x64(build 26200) |
124
184
 
125
- - **本插件**不会自动更新。**从插件市场安装的,就在市场里更新**;本地 `file:` 目录方式安装的,
126
- 覆盖目录后在插件管理器里重装。下面更新 REA **不会**更新本插件,反过来也一样。
127
- - **上游 REA**:用 `npm i -g rea-agents@latest` 更新。它的 `bin` 入口(`scripts/rea.mjs`)
128
- 跨版本稳定,所以本插件无需改动。
129
- - **Ghidra**:受 REA 版本门槛限制(当前 12.1.x),先升 REA,再确认它接受新版 Ghidra。
130
- - **DeepSeek Harness**:升级可能改变 MCP 客户端配置结构,用
131
- `Config.listConfigs name=@deepseek-ai/dsh-mcp-client` 看该行 schema 并调整字段名。
185
+ 实测跑过:一次干净的 `setup.mjs --reuse` 走到 `setup complete`;一次**不经 PATH 上的 `rea`、完全经由
186
+ shim** 的 MCP `initialize` 握手返回 `serverInfo {name: rea, version: 6.4.0}`;以及**真实桌面宿主下的完整链路** ——
187
+ 宿主自己的 Electron 二进制启动 `<DSH_HOME>/plugins/rea-bundle/bin/rea-shim.mjs mcp`,shim 拉起 **bundle 内置**
188
+ 的 REA,随后一次真实工具调用报出 `path_source: environment`,而那个路径只有该机的 `bundle.json` 知道。
132
189
 
133
- `check-updates.ps1`(Windows PowerShell)会把上述四项一次跑完;
134
- `.github/workflows/validate.yml` 在 CI 里守住 bundle 的形状(含「发布物不得含机器路径」这一条)。
190
+ 本机**没有**端到端跑过、因此不做承诺的:约 775 MB 的 JDK + Ghidra 下载分支(`--dry-run` 有计划,本机用
191
+ `--reuse` 复用了已有安装),以及 macOS/Linux 的首次运行。
135
192
 
136
- ## 许可
193
+ ## 边界与注意事项
194
+
195
+ - REA 在 6.4.0 有 170 个工具,每个会话的工具列表都会变长。
196
+ - 校验和对得起良心:厂商发布了的就固定并验证;没发布的(jadx-headless-mcp、apktool 包装脚本、
197
+ Android platform-tools、滚动的 `latest` 地址)则**实测一次并记录**,之后若漂移是**报告**而不是默默接受。
198
+ `bundle.json` 的 `unverifiedChecksums` 会列出处于该状态的组件。
199
+ - 某些网络下很慢(这里实测 GitHub release CDN 只有 0.35–0.54 MiB/s,光 Ghidra 就要 25–45 分钟)。
200
+ 下载是**可续传**的:缓存保留并重新校验,被中断的一轮会继续而不是从头再来。
201
+ - **代理**:Node 的全局 `fetch` 不读系统代理,而 .NET/PowerShell 会读。在开着 WinINET 代理的机器上,
202
+ 同一个地址 `Invoke-WebRequest` 通、Node 却 `ECONNRESET`/超时。setup 自己解析代理
203
+ (环境变量优先,Windows 上回退读注册表)并用 CONNECT 隧道,`NO_PROXY` 也照常生效。
204
+ - REA 的部分工具会启动进程、写文件、访问网络 —— DSH 的权限策略照常适用。只分析你有权检视的样本。
205
+ - `scripts/setup.mjs` 为 REA CLI 跑的是带 `--ignore-scripts` 的 `npm install`:官方 tarball 不带
206
+ `node_modules`,必须解析依赖闭包;而供给过程中**刻意跳过包的 lifecycle 脚本**。
207
+
208
+ ## 更新 —— 三件互相独立的事
209
+
210
+ ### 从 1.x 升级
211
+
212
+ 装上 2.x 后,**先跑一次供给**,再重启 dsh:
213
+
214
+ ```
215
+ node scripts/setup.mjs # 或:powershell -File scripts\rea-bundle-bootstrap.ps1 -Reuse
216
+ ```
137
217
 
138
- 本适配器为 MIT;REA 为 MIT,版权归其作者;Ghidra 为 Apache-2.0,版权归 NSA。
139
- 本仓库不再分发上游代码。
218
+ 为什么必须先跑:1.x 的行从 PATH 上启动 `rea mcp`,而 2.x 的行启动
219
+ `<DSH_HOME>/plugins/rea-bundle/bin/rea-shim.mjs` —— 那个文件**只有 `setup.mjs` 会创建**。升级后直接重启,
220
+ 该行会以 `MODULE_NOT_FOUND` 退出:harness 本身照常(`failOnStartupError: false` 是刻意的),但
221
+ `mcp__rea__*` 工具会消失,而且**不会有任何修复提示** —— 会打提示的 shim 本身还不存在。跑完 setup 再启动,
222
+ 工具就回来了。
223
+
224
+ - **本插件**从不自更新。从市场装的就在市场更新;从 `file:` 检出的就覆盖目录重装。
225
+ - **从 `2.0.0-bundle.1` 升级**:那一版镜像了 shim 与 `setup.mjs`,却漏了 manifest,也没有留下插件 checkout
226
+ 的记录,所以它供给出来的 bundle **无法自愈** —— 后台供给会因缺 manifest 而崩溃且完全不可见,而它自己写下的
227
+ lock 又会让重试被抑制六小时。请**从插件目录**重跑一次 `node scripts/setup.mjs`:它会重新镜像三个文件,
228
+ 并写下让后续运行找到真源的记录。`check-updates.ps1` 会报告这个状态。
229
+ - **供给的组件**:重跑 `node scripts/setup.mjs`,它会重新校验盘上的东西,只补缺失或不对的。
230
+ 版本钉在 `manifest/bundle.manifest.json`。
231
+ - **上游 REA / Ghidra**:改清单里的钉子再重跑 setup。REA 对 Ghidra 有版本闸门(目前 12.1.x),
232
+ 所以先更新 REA。
233
+
234
+ `check-updates.ps1`(Windows PowerShell)会一次性报告以上各项的状态。
235
+
236
+ ## 许可证
237
+
238
+ MIT(本适配器)。REA 是 MIT、归其作者;Ghidra 是 Apache-2.0、归 NSA;Temurin 是 GPLv2+CE;Node.js 是
239
+ MIT;apktool、jadx-headless-mcp、Android platform-tools 各自保留自己的许可。
240
+ **本包不再分发任何上游代码或二进制** —— 供给过程是从各组件的官方源逐个拉取。
@@ -11,7 +11,13 @@
11
11
  (用 pwsh 7 编辑则无此限制,但保持 BOM 对两者都安全)。
12
12
  #>
13
13
  [CmdletBinding()]
14
- param([string]$OutDir = (Join-Path $PSScriptRoot '.'))
14
+ param([string]$OutDir)
15
+
16
+ # The documented invocation (`powershell -File .\make-screenshots.ps1`) died right here:
17
+ # "Cannot bind argument to parameter 'Path' because it is an empty string" — $PSScriptRoot
18
+ # is not reliably populated while parameter defaults are bound, so this script had never
19
+ # actually regenerated a screenshot. Resolve the default in the body instead.
20
+ if (-not $OutDir -or $OutDir.Trim() -eq '') { $OutDir = $PSScriptRoot }
15
21
 
16
22
  Add-Type -AssemblyName System.Drawing
17
23
 
@@ -73,7 +79,7 @@ function Save-Png($bmp, $g, $path) { $g.Dispose(); $bmp.Save($path, [System.Draw
73
79
  # ---------------------------------------------------------------- 图 1:插件做了什么
74
80
  $r = New-Canvas; $bmp = $r[0]; $g = $r[1]
75
81
  Draw-Text $g 'dsh-plugin-rea:把 REA 接入 DeepSeek Harness' $fTitle $ink 60 46
76
- Draw-Text $g '第三方适配 · 自身不做逆向分析 · 只插入一条 MCP 客户端记录,并把引擎环境变量限制在该子进程内' $fSub $muted 62 98
82
+ Draw-Text $g '第三方适配 · 自身不做逆向分析 · 自供给 Node/REA/JDK/Ghidra 后自动接好那一行' $fSub $muted 62 98
77
83
 
78
84
  $rowY = 180; $boxH = 158; $boxW = 250
79
85
  Draw-Box $g 60 $rowY $boxW $boxH $([System.Drawing.Color]::White) $line
@@ -82,16 +88,16 @@ Draw-Text $g "mcp__rea__* 工具`n(6.4.0 暴露 170+)`n工具随会话注入
82
88
 
83
89
  Draw-Box $g 360 $rowY $boxW $boxH $([System.Drawing.Color]::FromArgb(255,239,246,255)) $accent
84
90
  Draw-Text $g '官方 MCP 客户端行' $fBox $accent 380 ($rowY + 18)
85
- Draw-Text $g "@deepseek-ai/dsh-mcp-client`nserverName = rea`ntransport = stdio`ncommand = node" $fBody $muted 380 ($rowY + 50)
91
+ Draw-Text $g "@deepseek-ai/dsh-mcp-client`nserverName = rea / transport = stdio`ncommand = 当前 Node 可执行文件`nargs[0] = <DSH_HOME>/plugins/rea-bundle/`n bin/rea-shim.mjs" $fBody $muted 380 ($rowY + 50)
86
92
  Draw-Text $g '↑ 本插件插入的就是这一行' $fSmall $accent 360 ($rowY + $boxH + 8)
87
93
 
88
94
  Draw-Box $g 660 $rowY $boxW $boxH $([System.Drawing.Color]::White) $line
89
- Draw-Text $g 'rea mcp(本机进程)' $fBox $ink 680 ($rowY + 18)
90
- Draw-Text $g "node …`n \rea-agents\scripts`n \rea.mjs mcp`nenv: GHIDRA_INSTALL_DIR`n JAVA_HOME(仅此处)" $fBody $muted 680 ($rowY + 50)
95
+ Draw-Text $g 'rea-shim(供给后镜像到此)' $fBox $ink 680 ($rowY + 18)
96
+ Draw-Text $g "读 bundle.json 里的本机真相`n导出 GHIDRA_INSTALL_DIR /`n JAVA_HOME / REA_*`n再拉起 bundle 内置的 REA" $fBody $muted 680 ($rowY + 50)
91
97
 
92
98
  Draw-Box $g 960 $rowY $boxW $boxH $([System.Drawing.Color]::FromArgb(255,240,253,244)) $accent2
93
- Draw-Text $g '分析引擎' $fBox $accent2 980 ($rowY + 18)
94
- Draw-Text $g "Ghidra 12.1.4(本机已装)`nHopper / IDA(可选,`n各自需授权)`n静态 JS / .NET 无需引擎" $fBody $muted 980 ($rowY + 50)
99
+ Draw-Text $g '分析引擎(供给或复用)' $fBox $accent2 980 ($rowY + 18)
100
+ Draw-Text $g "Ghidra 12.1.x / JDK 21:`n缺则下载并校验,`n已有则 --reuse 复用`n静态 JS / .NET 无需引擎" $fBody $muted 980 ($rowY + 50)
95
101
 
96
102
  Draw-Arrow $g 310 ($rowY + 40) 358 ($rowY + 40) $muted
97
103
  Draw-Arrow $g 610 ($rowY + 40) 658 ($rowY + 40) $muted
@@ -106,7 +112,7 @@ Draw-Line $g 358 446 150 446 $muted
106
112
  Draw-Arrow $g 150 446 150 342 $muted
107
113
 
108
114
  Draw-Text $g '上游 REA(MIT):github.com/morluto/rea 本插件:github.com/czcdr/dsh-plugin-rea' $fSmall $muted 60 620
109
- Draw-Text $g '实测 REA 6.4.0 + DSH 桌面运行时 0.2.0-rc.2 + Ghidra 12.1.4 + Node 24.21.0(Windows 11 x64,2026-10-12)' $fSmall $muted 60 646
115
+ Draw-Text $g '实测 REA 6.4.0 + DSH 桌面运行时 0.2.0-rc.2 + Ghidra 12.1.4 + Node 24.21.0(Windows 11 x64,2026-10-14)' $fSmall $muted 60 646
110
116
  Draw-Text $g 'Ghidra 为 Apache-2.0(NSA);REA 为 MIT。本仓库不分发上游代码。' $fSmall $muted 60 672
111
117
  Save-Png $bmp $g (Join-Path $OutDir 'screenshot-1.png')
112
118
 
Binary file