alexbevi/ghidra-manager
GitHub: alexbevi/ghidra-manager
一款跨平台的 Ghidra 命令行管理工具,用于自动化安装特定版本、管理兼容插件并启动 GhidraMCP 逆向分析项目。
Stars: 0 | Forks: 0
# Ghidra 管理器
Ghidra Manager 是一个跨平台的 CLI,用于安装 Ghidra 并为特定版本编译经过审查的扩展集合。它跟踪稳定的 GitHub 发布版本,要求发布资产提供 GitHub 发布的 SHA-256 摘要,从不可变的发布提交构建插件,并保留当前活动的安装以及一个完整的回滚配对。
`ghidra-manager` Python 命令是 Windows、Linux 和 macOS 上唯一受支持的面向用户的入口点。
对于 Codex 工作流,此仓库还包含 [`ghidra-manager` skill](https://github.com/alexbevi/ghidra-manager/blob/main/skills/ghidra-manager/SKILL.md)。
调用 `$ghidra-manager` 以检查管理状态、选择已审查的插件、启动并验证项目、连接 bridge、定位项目内的特定程序、比较二进制文件,或开发 manager 本身。该 skill 遵循与 CLI 相同的安全规则:将 `instances` 作为运行时的事实来源,当打开多个程序时显式指定程序,并在执行写入操作前审查比较结果。该 skill 在源代码仓库中维护,不会通过 PyPI 包安装到 Codex 中。
## 命令摘要
以下示例使用尖括号缩写了路径、进程 ID 和版本。不带子命令运行 `ghidra-manager` 等同于 `ghidra-manager sync`。
| 命令 | 选项 | 示例输出 |
| --- | --- | --- |
| `ghidra-manager help` | 全局: `-h`, `--help` | `usage: ghidra-manager ... {help,sync,status,...}` |
| `ghidra-manager --version` | 无 | `ghidra-manager 0.1.0` |
| `ghidra-manager sync` | `--dry-run` 解析但不改变状态 | `Active pair: Ghidra
; plugins ghidra-lx-loader, mcp.` |
| `ghidra-manager status` | 无 | `Active Ghidra: ` |
| `ghidra-manager doctor [PROJECT]` | `--program PROGRAM`, `--json`, `--base-port PORT` | `Doctor result: ready` |
| `ghidra-manager rollback` | 无 | `Rolled back to Ghidra ; plugins mcp.` |
| `ghidra-manager projects` | 无 | `Projects known to Ghidra :` |
| `ghidra-manager plugins discover` | `--json` | `mcp` 显示为 `selected` 或 `available` |
| `ghidra-manager plugins list` | `--json` | `Plugins for Ghidra :` |
| `ghidra-manager plugins install PLUGIN` | `mcp` 或 `ghidra-lx-loader` | `Installed plugin mcp for Ghidra .` |
| `ghidra-manager plugins remove PLUGIN` | `mcp` 或 `ghidra-lx-loader` | `Removed plugin mcp from Ghidra .` |
| `ghidra-manager open PROJECT` | `--program PROGRAM`, `--timeout SECONDS`, `--base-port PORT` | `GhidraMCP instance ready:` |
| `ghidra-manager launch [GHIDRA_ARGS...]` | 其余参数直接传递给 Ghidra | `Launching Ghidra with JDK 21...` |
| `ghidra-manager launch-multi [PROJECT.gpr ...]` | `--count N`, `--timeout SECONDS`, `--base-port PORT` | `GhidraMCP instances ready:` |
| `ghidra-manager bridge [BRIDGE_ARGS...]` | 其余参数直接传递给 bridge | `` |
| `ghidra-manager compare SOURCE_PROJECT TARGET_PROJECT` | `--base-port PORT` | `Plan saved: /compare-plans/.json` |
| `ghidra-manager compare --apply PLAN` | 无源或目标参数 | `Applied operations to .` |
| `ghidra-manager instances` | `--base-port PORT` | `MCP port 8089` |
`launch` 和 `bridge` 会刻意将其余参数直接传递,而不是自行解释。环境变量也可以设置 manager 主目录、MCP 基础端口、启动超时和 GitHub 身份验证;这些在下文的详细章节中有所描述。
## 安装
安装 [`uv`](https://docs.astral.sh/uv/) 和 64 位 JDK 21。CLI 使用 uv 来配置 Python 3.13,因此不需要系统安装 Python。
在隔离的工具环境中安装已发布的 CLI:
```
uv tool install ghidra-manager
ghidra-manager help
```
独立于受管理的 Ghidra 安装和插件对其进行升级:
```
uv tool upgrade ghidra-manager
```
从代码检出于开发环境进行安装:
```
uv sync --locked --group dev
uv run ghidra-manager help
```
JDK 发现在每个平台上都会检查 `JAVA_HOME` 和 `PATH`。macOS 还会在可用时使用 `/usr/libexec/java_home` 和 Homebrew。
## 安装、更新和回滚
解析并安装最新的稳定版 Ghidra 版本。全新安装不包含任何插件;随后的 sync 会为新 Ghidra 版本重新构建活动配对中选定的插件:
```
ghidra-manager sync
```
预览发布选择而不更改管理状态:
```
ghidra-manager sync --dry-run
```
显示当前活动的、保留的以及最新的上游版本:
```
ghidra-manager status
```
代表性输出:
```
Active Ghidra:
Active plugin: ghidra-lx-loader (installed)
Active plugin: mcp (installed)
Previous pair: Ghidra ; plugins mcp
Upstream Ghidra:
```
检查本地逆向工程就绪状态,而无需解析上游发布:
```
ghidra-manager doctor
ghidra-manager doctor ripper --program RIPPER.LE
ghidra-manager doctor ripper --program RIPPER.LE --json
```
`doctor` 会验证活动配对、受管理的安装和 MCP 插件、JDK 21、已记录的项目、响应的 MCP 身份和版本、预期的打开程序、endpoint 目录以及分析状态。错误会产生非零退出代码;警告仍然被视为成功,以便可以检查部分环境。
代表性的就绪输出:
```
OK active-pair: Ghidra ; plugins ghidra-lx-loader, mcp
OK project: /projects/ripper.gpr
OK instance: PID on http://127.0.0.1:8089
OK program: RIPPER.EXE is open
OK analysis: RIPPER.EXE analyzed; 847 functions
Doctor result: ready
```
返回到保留的上一个配对:
```
ghidra-manager rollback
```
在执行 sync 或回滚之前,请关闭受管理的 Ghidra 进程。回滚会在更改活动状态之前,重新安装保留配对的完整插件集,包括当两个配对共享同一个 Ghidra 版本时。
`GH_TOKEN` 或 `GITHUB_TOKEN` 可用于对 GitHub API 请求进行身份验证。
## 管理插件
列出从 manager 内置注册表获取的已审查插件:
```
ghidra-manager plugins discover
ghidra-manager plugins discover --json
ghidra-manager plugins list
ghidra-manager plugins list --json
```
内置注册表是 [`src/ghidra_manager/plugin_registry.json`](https://github.com/alexbevi/ghidra-manager/blob/main/src/ghidra_manager/plugin_registry.json),而不是远程市场。其初始审查目录包含 `mcp` 和 `ghidra-lx-loader`。发现是只读的,并且在安装 Ghidra 之前就可以工作。在安装或更新插件时,插件版本是从稳定的 GitHub 发布中解析出来的,而不是在注册表中固定的。
`discover` 显示注册表成员资格以及每个插件是否在活动配对中被选中:
```
mcp | GhidraMCP | selected | bethington/ghidra-mcp
ghidra-lx-loader | Ghidra LX Loader | selected | yetmorecode/ghidra-lx-loader
```
`list` 显示针对活动 Ghidra 版本解析出的制品:
```
Plugins for Ghidra :
ghidra-lx-loader | | |
mcp | | |
```
为活动的 Ghidra 版本安装或更新一个插件:
```
ghidra-manager sync
ghidra-manager plugins install mcp
ghidra-manager plugins install ghidra-lx-loader
ghidra-manager plugins remove ghidra-lx-loader
```
插件安装需要一个活动的 Ghidra 安装,并且在有 manager 拥有的 Ghidra 进程运行时拒绝替换扩展。manager 将最新的稳定插件发布标签解析为其不可变的 commit,使用目标 Ghidra 发行版的 Gradle wrapper,验证生成的扩展 ZIP,然后以事务方式激活完整的选定集。
删除是幂等的,并会创建一个回滚配对,保留被删除的制品直到不再被引用为止。
在使用 `bridge`、`instances`、`open`、`launch-multi` 或 `compare` 之前,请安装 `mcp`。在导入 LE/LX 二进制文件(例如 DOS/4GW 或 OS/2 Linear Executables)之前,请安装 `ghidra-lx-loader`。
## 管理状态
全新安装使用原生的用户数据目录:
- Windows: `%LOCALAPPDATA%\ghidra-manager`
- Linux: `${XDG_DATA_HOME:-~/.local/share}/ghidra-manager`
- macOS: `~/Library/Application Support/ghidra-manager`
设置 `GHIDRA_MANAGER_HOME` 可覆盖此位置。
```
/
├── ghidra//
├── plugins////
├── pairs//metadata.json
├── state.json
├── gradle-cache/
├── launch-logs/
├── compare-plans/
├── python/
└── uv-cache/
```
`state.json` 记录当前和上一个配对 ID,而不需要符号链接。每个配对都记录其确切的 Ghidra 版本和已排序的插件清单。
下载、构建和扩展安装在原子状态替换之前都会进行验证。失败的扩展替换会恢复每个受影响的插件目录。
当首次从包含旧版 `.managed/` 布局的代码检出中运行时,CLI 会原地采用该目录,并将有效的 `current` 和 `previous` 配对元数据转换为版本化的 JSON。此后不再需要旧版符号链接。
现有的 GhidraMCP 配对在迁移时会选中 `mcp`,并保留其旧版制品路径,直到 current 或 previous 都不再引用它们。
## 运行 Ghidra 和 GhidraMCP
如果尚未选中,请先安装 MCP 插件:
```
ghidra-manager plugins install mcp
```
列出已记录的项目以解析确切的项目路径:
```
ghidra-manager projects
```
代表性输出:
```
Projects known to Ghidra :
ripper | ready | last-opened | active MCP port 8089 (PID ) | /projects/ripper.gpr
harvester | ready | recent | inactive | /projects/harvester.gpr
2 recorded projects from /preferences
```
通过名称或 `.gpr` 路径打开一个已记录的项目,并等待其 GhidraMCP endpoint:
```
ghidra-manager open ripper
ghidra-manager open /path/to/ripper.gpr --program RIPPER.LE
```
`open` 会保留一份启动日志,拒绝已处于活动状态的项目,并且仅在新 endpoint 识别出预期的项目和可选程序后才报告成功。使用 `--timeout` 或 `--base-port` 可覆盖发现默认设置。
代表性输出:
```
Opening /projects/ripper.gpr with Ghidra and JDK 21...
Launcher PID | log /launch-logs/.log
Waiting up to 180 seconds for project ripper on ports 8089-8104...
GhidraMCP instance ready:
MCP port 8089 | PID | project ripper | http://127.0.0.1:8089
Open programs: RIPPER.LE
```
启动活动的发行版,可选择通过其 `.gpr` 路径打开一个项目:
```
ghidra-manager launch
ghidra-manager launch /path/to/project.gpr
```
`launch` 将所有剩余参数直接传递给 Ghidra。它不会将记录的名称(例如 `ripper`)解析为其项目路径,因此 `launch --help` 会被转发给 Ghidra,而不是作为 CLI 帮助处理。请使用 `ghidra-manager help` 获取 manager 命令摘要。
在首次启动新的 Ghidra 设置版本时:
1. 打开或创建一个项目并启动 CodeBrowser。
2. 选择 **File > Configure > Configure All Plugins** 并启用 **GhidraMCP**。
3. 选择 **Tools > GhidraMCP > Start MCP Server**。
该插件默认监听 `127.0.0.1:8089`,并可能依次回退到端口 8104。通过列出响应的实例来验证启动;启动器横幅或退出代码本身并不能证明 Ghidra 仍在运行:
```
ghidra-manager instances
```
代表性输出:
```
MCP port 8089 | PID | project ripper | http://127.0.0.1:8089
```
为每个项目启动一个进程并等待新的 MCP endpoint:
```
ghidra-manager launch-multi \
/path/to/first-project.gpr \
/path/to/second-project.gpr
```
不带路径时,`launch-multi` 默认打开两个实例。使用 `--count`、`--timeout` 或 `--base-port` 可覆盖启动行为。项目和项目名称必须不同,并且已处于活动状态的项目会被拒绝。分离的启动日志保留在 `launch-logs/` 下。
向 Codex 注册受管理的 stdio bridge:
```
codex mcp add ghidra -- ghidra-manager bridge
```
bridge 使用由 uv 管理的 Python 3.13 和上游保留的脚本:
```
ghidra-manager bridge --help
```
`GHIDRA_MCP_BASE_PORT` 更改发现基础端口。
`GHIDRA_MCP_LAUNCH_TIMEOUT` 更改多重启动超时。
## 与 Codex 配合使用
内置的 [`ghidra-manager` skill](https://github.com/alexbevi/ghidra-manager/blob/main/skills/ghidra-manager/SKILL.md) 会向 Codex 传授 manager 的命令边界、插件生命周期、启动检查和比较保障措施。仓库目录是事实来源;请安装或链接 `skills/ghidra-manager` 为 `$CODEX_HOME/skills/ghidra-manager`,并启动一个新的 Codex 会话以使 `$ghidra-manager` 可用。一旦该 skill 和 bridge 可用,请求可以显式指定该 skill 的名称:
```
Use $ghidra-manager to inspect the active Ghidra pair, discover the reviewed
plugins, open the ripper project, and confirm its MCP program before making any
changes.
```
CLI 用于识别活动的项目;GhidraMCP 用于识别其中的程序。当打开多个程序时,请在 MCP 调用中使用它们完整的 Ghidra 项目路径,而不是依赖活动的标签页:
```
/RIPPER.LE
/v1.05/RIPPER.EXE
```
`open` 和 `doctor` 上的 `--program` 是可选的。当就绪状态依赖于一个确切打开的程序时,请提供它。在 MCP 调用中,当打开多个程序时,请务必提供 `program`。
## 端到端示例:将 RIPPER 与 v1.05 进行比较
本示例以一个名为 `ripper` 的已记录项目中已分析的 `/RIPPER.LE` 以及位于 `/path/to/Ripper/RIPPER/RIPPER.EXE` 的修补过的 DOS/4GW 可执行文件为起点。
### 1. 安装审查过的运行时
安装 Ghidra,检查内置注册表,并在启动 Ghidra 之前添加这两个插件:
```
ghidra-manager sync
ghidra-manager plugins discover
ghidra-manager plugins install mcp
ghidra-manager plugins install ghidra-lx-loader
ghidra-manager plugins list
```
插件安装会为活动的 Ghidra 版本编译每个稳定版本。在安装或更新插件之前,请关闭 manager 拥有的 Ghidra 进程。
### 2. 注册 bridge 并验证项目
```
codex mcp add ghidra -- ghidra-manager bridge
ghidra-manager projects
ghidra-manager open ripper --program RIPPER.LE
ghidra-manager instances
ghidra-manager doctor ripper --program RIPPER.LE
```
此时,manager 已经证明了正在使用的是哪个 Ghidra、插件集、JDK、项目、进程、端口和程序。
### 3. 通过 MCP 导入修补过的可执行文件
manager 不会复制 Ghidra 的导入 API。在验证启动后,要求 Codex 使用 GhidraMCP:
```
Use $ghidra-manager. In the ripper project, create the virtual folder /v1.05
and import /path/to/Ripper/RIPPER/RIPPER.EXE there with the LX loader. Keep
/RIPPER.LE unchanged. Run analysis, save the new program, and verify its format,
project path, and function count through MCP.
```
重要的验证是 loader 的结果,而不仅仅是一次成功的导入:
```
name: RIPPER.EXE
project path: /v1.05/RIPPER.EXE
executable format: Linear Executable (LE-Style DOS)
language: x86:LE:32:default
analysis: complete
```
### 4. 保守地进行比较和同步
二进制文件可以共享一个 MCP 实例,同时保持明确无误:
```
/RIPPER.LE original documentation source
/v1.05/RIPPER.EXE patched v1.05 target
```
对于一个项目中的程序,要求 Codex 使用这些完整路径查询 GhidraMCP。
仅针对唯一的、完全匹配的标准化代码传输函数文档,保留目标冲突,并分别审查更改过的函数。可移植的数据类型图(如结构体、枚举、数组、指针和函数签名)可以在等效性检查后从源复制到目标;不要在重建的二进制文件之间复制派生自地址的 `switchD_*` 命名空间。
为本教程提供参考的 RIPPER 运行产生了:
```
Original /RIPPER.LE: 1,682 functions, 561 data types
Target /v1.05/RIPPER.EXE: 847 functions, 567 data types
Unique exact matches: 675 functions
Target documentation: 679/847 functions (80.2%)
Copied source data types: 561/561 equivalent
```
这些计数特定于此样本。可重用的价值在于这个受严密保护的工作流:可重现的插件、经过验证的运行时身份、显式的程序路径、精确匹配的传输、冲突保留以及保存后的健康检查。
完成后执行:
```
ghidra-manager doctor ripper --program RIPPER.EXE
ghidra-manager instances
```
## 跨实例比较二进制文件
将第一个响应的项目视为文档源,将第二个视为目标:
```
ghidra-manager compare source-project target-project
```
比较是只读的。它首先汇总清单,然后仅当标准化的 opcode 哈希和指令计数在每个程序中唯一标识一个函数时才匹配函数。它会报告缺失的函数元数据、结构和枚举,而不会覆盖冲突的目标状态。
每次比较都会在 `compare-plans/` 下写入一个私有的版本化计划,并保留最新的十个。显式应用已审查的计划:
```
ghidra-manager compare --apply \
/path/to/compare-plans/-source-to-target.json
```
Apply 会重新检查目标项目、PID、函数哈希、文档和类型状态。它会在第一个被拒绝的操作时停止,并刻意将更改保留在 Ghidra 中不保存,以便进行审查或撤销。
`compare` 需要两个不同的、响应的项目实例。对于一个项目中的两个程序,请使用 RIPPER 示例中的完整路径 MCP 工作流,而不是尝试启动同一个项目两次。
## 验证
```
uv sync --locked --group dev
uv run pytest
uv run ruff check .
uv run mypy
uv build
uv run ghidra-manager sync --dry-run
git diff --check
```
Pull-request CI 在 Ubuntu x64、Windows x64、macOS ARM64 和 macOS x64 上运行。手动触发的工作流会在同一矩阵上执行实际的 sync、幂等 resync、状态检查和 bridge 冒烟测试。
## 故障排除
- **未找到 JDK 21:** 设置 `JAVA_HOME` 或将 Java 21 放入 `PATH`。
- **GitHub 速率限制:** 设置 `GH_TOKEN` 或 `GITHUB_TOKEN`。
- **MCP 连接被拒绝:** 打开 CodeBrowser,启用 GhidraMCP,并从 **Tools > GhidraMCP** 启动其服务器。
- **MCP 插件未安装:** 关闭受管理的 Ghidra 进程,运行 `ghidra-manager plugins install mcp`,然后重新启动 Ghidra。
- **插件构建失败:** 检查报告的 Gradle 输出并继续使用未更改的活动配对;失败的构建永远不会被激活。
- **无效的项目:** 传递 `projects` 命令报告的 `.gpr` 路径,而不仅仅是其显示名称。
- **打开超时:** 完成打开 CodeBrowser,启用 GhidraMCP,并检查 `open` 报告的保留日志路径。
- **Doctor 未就绪:** 解决每个 `ERROR` 检查项,然后在开始写入工作流之前重新运行相同的项目和程序选择。
- **多重启动超时:** 在每个项目中完成打开 CodeBrowser,然后运行 `ghidra-manager instances`。
- **拒绝更新:** 关闭所有从受管理的 Ghidra 组件目录运行的进程。
- **比较目标已更改:** 生成一个新的计划,而不是应用陈旧的操作。
- **无项目注册表:** 启动一次 Ghidra,以便它创建平台设置并记录一个项目。标签:后台面板检测, 逆向工具