App-Builders-Gang/binexport-ghidra-12
GitHub: App-Builders-Gang/binexport-ghidra-12
修复 Google BinExport 在 Ghidra 12.x 上因 API 变更导致崩溃的问题,恢复 Ghidra 到 BinDiff 的完整分析管线。
Stars: 0 | Forks: 0
# BinExport for Ghidra 12.x (12.1.2) — 修补版构建与预构建扩展
[](https://github.com/App-Builders-Gang/binexport-ghidra-12/releases)
[](https://github.com/NationalSecurityAgency/ghidra)
[](https://github.com/google/bindiff)
[](LICENSE)
**BinExport** 是 Google 的导出器,它将反汇编结果(IDA Pro、Binary Ninja、
Ghidra)转换为 Protocol-Buffers `.BinExport` 文件,随后由 **[BinDiff](https://github.com/google/bindiff)**
进行比对,以用于补丁 / 版本 / 漏洞分析。官方的 BinExport
发行版固定在 **Ghidra 11.0.3**,并且在 Ghidra 12.x 上会崩溃。此仓库修复了这个问题。
## ⭐ 问题描述
在 Ghidra 12.0–12.1.2 上,官方 BinExport 在导出过程中会中止:
```
java.lang.NoSuchFieldError: Class ghidra.program.model.listing.LabelString
does not have member field 'ghidra.program.model.listing.LabelString$LabelType CODE_LABEL'
at com.google.security.binexport.BinExport2Builder.addCommentedExpression(BinExport2Builder.java:224)
```
Ghidra 12.x **彻底移除了 `ghidra.program.model.listing.LabelString` 类**,因此
BinExport 甚至无法运行。上游尚未修复此问题 ([#166](https://github.com/google/binexport/issues/166),
处于打开状态,没有 PR)。结果是:到目前为止,无法在最新的 Ghidra 上将 Ghidra 数据导入到 BinDiff 中。
## 🔧 修复方法(对 `BinExport2Builder.java` 的 2 个补丁)
1. **在 `addCommentedExpression` 中移除了 `LabelString` 分支**。`LabelString`(及其
`LabelType.CODE_LABEL/VARIABLE/EXTERNAL` 枚举)在 Ghidra 12.x 中已不存在。该
分支仅用于为*注释元数据*(全局/局部/外部引用注释)标记类型;而
核心导出功能 —— 指令、基本块、调用图、表达式、助记符 —— 完全
不受影响。BinDiff 的比对依赖于这些结构数据,因此结果是
一致的。
2. **将 `getInstructionBefore()` 更改为 `getInstructionContaining()`**,用于获取基本块的最后一个
指令。Ghidra 12.x 更改了 `CodeBlock.getMaxAddress()` 的语义,因此
`getInstructionBefore()` 现在会返回 `null`(导致 NPE)。`getInstructionContaining()` 能够稳健地
返回基本块(BB)的最后一条指令。
就是这样 —— 两处外科手术式的修改,完全恢复了对 Ghidra 12.1.2 的兼容性,整个
BinExport/BinDiff 分析路径再次正常工作。
## 📦 快速入门 — 安装预构建扩展
1. 从
[最新发行版](https://github.com/App-Builders-Gang/binexport-ghidra-12/releases)下载 **`ghidra_12.1.2_PUBLIC__BinExport.zip`**。
2. 在 Ghidra 12.1.2 中:**File → Install Extensions → `+`** → 选择该 zip → 重启 Ghidra。
3. 在 **File → Configure → Miscellaneous** 下启用它(或者它已经被启用)。
4. 打开一个程序 → **File → Export Program → Format: Binary BinExport (v2)** → 完成。
你现在可以将 `.BinExport` 提交给 BinDiff 8 了。
## 🖥️ 无头 / 脚本化导出(自动化、CI、代理)
包含了一个无头包装脚本 `BinExportHeadless.java`(上游的 `BinExport.java`
脚本使用了交互式的 `askFile`/`askChoices`,这在无头模式下很不方便):
```
# 将 binary 导入 project 并一步将其导出为 .BinExport
analyzeHeadless \
-import \
-postScript BinExportHeadless.java \
-scriptPath /ghidra_scripts
```
然后使用 BinDiff 8 比对两个导出结果:
```
bindiff.exe --output_dir= a.BinExport b.BinExport
```
## 🔨 从源码构建
要求:**JDK 21**,**Gradle 8.5+**(使用 9.6.1 构建),`GHIDRA_INSTALL_DIR` 指向
Ghidra 12.1.2 的安装路径。
```
set GHIDRA_INSTALL_DIR=C:\Tools\ghidra_12.1.2_PUBLIC
set JAVA_HOME=C:\path\to\jdk-21
cd java
gradle buildExtension
# → dist/ghidra_12.1.2_PUBLIC__BinExport.zip
```
按照上述方法安装生成的 zip 文件。(Gradle 构建应用了 Ghidra 自带的
`support/buildExtension.gradle`,并从你的 Ghidra 安装路径中解析 protobuf 版本。)
## 🎯 目的 / 适用人群
- **补丁比对** Windows / 固件更新以寻找安全修复。
- **版本迁移** —— 在不同的二进制文件版本之间定位已知的函数/决策点。
- **恶意软件家族分析** —— 比对样本以聚类变体并查找共享代码。
- **任何使用 Ghidra 12.x** 且需要 BinDiff 并遇到了 `LabelString` 崩溃问题的人。
## 📄 许可证
[Apache License 2.0](LICENSE) —— 继承自上游 `google/binexport`。
## ⚠️ 注意事项 / 警告
- 已在 Ghidra 12.1.2 + BinDiff 8 (Windows) 上进行测试。其他 12.x 的点版本应该也能正常工作;
如果未来的 Ghidra 重命名了其他 API,预计需要扩展这些补丁。
- BinDiff 在比对某些二进制文件时可能会发出非致命的 `Could not find basic block` 警告;
但比对仍会完成并产生有效结果。
- 这里只构建了 **Ghidra** 扩展。上游目录树中的
IDA Pro / Binary Ninja 导出器保持不变。
标签:BinDiff, Ghidra, JS文件枚举, 二进制分析, 云安全运维, 云资产清单, 代码补丁, 后台面板检测, 漏洞分析, 路径探测, 逆向工程