逆向工程实战手册 第 36 章

第 36 章 Ghidra 深度使用(免费 IDA 的完全体)

Ghidra 是 NSA 开源的免费逆向平台,能力与 IDA 对标:多架构反汇编、反编译(Decompiler)、脚本化(Jython/Python 3)、插件生态、无头模式(headless)。预算有限或想自动化时,Ghidra 是第一选择。

📍 知识点地图 | 主题:Ghidra深度 | 前置:第4章 | 后续:— | 核心概念:headless、脚本、结构体恢复、插件

36.1 Ghidra 能力全景(vs IDA 对比)

能力 Ghidra IDA 说明
反编译器 Decompiler(C 风格) Hex-Rays 质量接近,免费
多架构 极广(含 DSP/小众) 广 小众架构 Ghidra 更强
脚本语言 Jython / Python 3 IDAPython 都强
自动化 headless 一流 -A + idalib Ghidra 更方便
协作 团队服务器(免费) 收费 团队项目 Ghidra 完胜
价格 免费开源 商业
调试器 内置(较弱) 内置(较强) 调试还是 IDA/x64dbg
插件生态 丰富 更丰富 D-810 等去混淆工具 IDA 多

36.2 Ghidra 核心操作速览

启动: analyzeHeadless(命令行)或 ghidraRun(GUI)

GUI 主窗口布局:
  Program Tree  文件/段结构
  Listing       反汇编视图(主工作区)
  Decompile     反编译窗口(选中函数按 F5 快捷键/右键 Decompile)
  Symbol Tree   符号/函数列表
  Script Manager 脚本管理器(Window → Script Manager)

常用快捷键:
  F5 或右键 → Decompile    反编译
  X                      交叉引用
  L                      改标签(重命名)
  Ctrl+L                 标签对话框
  Ctrl+Shift+G           去地址
  G                      导航到地址/符号
  F2                     断点(调试器模式)

36.3 反编译与类型恢复(核心能力)

反编译基础

选中函数 → Decompile 窗口显示伪 C
伪代码操作:
  右键变量 → Set Type(设类型)
  右键变量 → Retype Variable
  右键 → Label(重命名变量)
  右键 → 加注释(Inline comment)
  选中数组 → 右键 → Array…(设维度)

结构体恢复(Ghidra 特色:拖拽式)

1. Data Type Manager(数据类型管理器)
2. 右键 → New → Structure
3. 从 Listing 拖拽字段到结构体编辑器
4. 应用到函数/全局 → 伪代码自动展开字段

调用约定识别

右键函数 → Edit Function Signature
常见约定: __cdecl / __stdcall / __fastcall / __thiscall
ARM: AAPCS;64 位: Windows x64 / SysV
类型恢复错误 → 手动改约定 → 反编译输出立刻变清晰

36.4 脚本化(Ghidra Python)

基础

# Ghidra 脚本上下文: 全局变量 currentProgram / state
from ghidra.program.model.symbol import SymbolType

# 列函数
fm = currentProgram.getFunctionManager()
for f in fm.getFunctions(True):
    print(f.getName(), hex(f.getEntryPoint().getOffset()))

# 反编译
from ghidra.app.decompiler import DecompInterface
decomp = DecompInterface()
decomp.openProgram(currentProgram)
func = fm.getFunctionAt(toAddr(0x401000))
res = decomp.decompileFunction(func, 60, monitor)
print(res.getDecompiledFunction().getC())

实用脚本模式

# 1. 提取所有字符串
listing = currentProgram.getListing()
for d in listing.getDefinedData(True):
    if d.getDataType().getName() == "string":
        print(hex(d.getAddress().getOffset()), d.getDefaultValueRepresentation())

# 2. 批量导出反编译(喂 LLM)
# 3. 提取 XREF(谁引用某地址)
from ghidra.program.model.symbol import ReferenceManager
refs = currentProgram.getReferenceManager().getReferencesTo(toAddr(0x405000))
for r in refs:
    print(hex(r.getFromAddress().getOffset()))

运行

GUI: Window → Script Manager → 选中脚本 → Run
命令行: analyzeHeadless 项目目录 项目名 -process target.exe -postScript script.py

36.5 无头模式(headless)——自动化主力

# 基本用法
analyzeHeadless /tmp/proj MyProj -import target.exe -postScript analyze.py -scriptPath /tmp/scripts

# 批量分析目录
analyzeHeadless /tmp/proj MyProj -import /tmp/samples/ -recursive -postScript batch.py

# 关键参数
-import <file/dir>      导入目标
-recursive              递归目录
-postScript <script>    导入后执行脚本
-scriptPath <dir>       脚本路径
-overwrite              覆盖已分析
-process <file>         重跑已导入的文件(不重新导入)

headless 的价值:可以放进 CI/CD 管道、批量恶意软件分析、CTF 自动化。

36.6 批量恶意软件分析管道(Ghidra 实战)

1. analyzeHeadless 批量导入样本目录
2. postScript: 提取(函数数/字符串/导入/可疑模式)
3. 输出 JSON/CSV 报告
4. LLM 批量分类(第 29 章)
5. 可疑样本 → GUI 深挖

36.7 Ghidra 插件与扩展(补强能力)

插件/扩展 用途
GOOMBA OLLVM 去平坦化(Ghidra 版)
ghidra-rust Rust 符号辅助
ghidra-golang Go 符号恢复
Diaphora (Ghidra 版) 二进制对比
ghidriff 命令行 diff(CI 友好)
Sleigh 处理器模块 新增架构支持
LLM 插件(社区) AI 辅助注释/命名
# 安装: 插件 jar 放入 extensions/ 目录 → 重启 Ghidra

36.8 Ghidra 深度工作流

目标: 无头批量分析 + 深挖一个目标

1. analyzeHeadless 导入 → postScript 提取特征
2. 报告驱动: 先看统计数据(可疑字符串/危险导入/高复杂度函数)
3. GUI 打开重点文件 → 反编译 → 类型恢复 → 重命名
4. 去混淆(GOOMBA/D-810 类)→ 再看
5. 动态验证(配合 GDB/Frida,第 5-6 章)
6. 输出 C 代码/报告

动手练习

  1. 用 analyzeHeadless 批量导入 3 个样本,postScript 提取函数数和字符串到 JSON。
  2. 在 Ghidra 中给一个含结构体的函数做结构体恢复(拖拽法),对比前后伪代码。
  3. 写一个 Ghidra 脚本:提取所有引用了某个字符串的函数名。
  4. 用 ghidriff 对比两个版本的二进制,找出变更函数。

深入阅读

  • 仓库:skills/reverse-engineering/tools.md(Ghidra headless 用法)
  • 仓库:skills/reverse-engineering/tools-advanced.md(Ghidra 脚本/去混淆框架)
  • 仓库:skills/reverse-engineering/references/ollvm-deobfuscation.md(GOOMBA 等)
  • 仓库:skills/reverse-engineering/languages-compiled.md(Rust/Ghidra 脚本)
  • 仓库:skills/patch-diff-exploit/references/diff-tools-comparison.md(ghidriff)