--- name: re-ghidra description: > Ghidra 工作流:导入→自动分析→反编译→脚本化。 触发词:Ghidra、反编译、headless capabilities: [decompilation, debugging] --- # Ghidra 逆向工作流 ## 何时使用 / 何时不用 - 用:需要反编译与深度静态分析;headless 批量处理;脚本化自动标注/解密循环;PE/ELF/Mach-O 全支持 - 不用:内存 <4GB(启动即卡顿,换 [[re-radare2]]);只需快速初勘(走 [[re-triage]]) - 不用:已有 IDA 工作流且目标明确(按 `RE_DECOMPILER` 会话变量选择) ## 工具准备 参考 [[re-analyze/platform-tips]]——Ghidra 为静态分析主力(免沙箱);低内存环境按平台经验换 [[re-radare2]],headless 批处理适合远程环境。 ### Ghidra(官方安装,Java 21 要求) - 下载: GitHub `NationalSecurityAgency/ghidra` releases,解压即用(无需安装) - JDK 21(Ghidra 11.3+ 要求): - Linux: `apt install openjdk-21-jdk` / `dnf install java-21-openjdk` / `pacman -S jdk21-openjdk` - macOS: `brew install openjdk@21` 或 `brew install --cask temurin` - Windows: `choco install temurin21`(或 Oracle JDK 21) - 启动: `./ghidraRun`(GUI)/ `./support/analyzeHeadless`(无头) - 验证: `java -version`(须 21+);`./support/analyzeHeadless -help` 正常输出 - 版本: 12.x 为当前主线(核验基线 12.1.4);安装时以官方 Releases 的 Latest 为准;运行官方 release 只需 JDK 21,从源码构建 Ghidra 自身需 JDK 25 + Gradle 9.1+;11.x → 12.x 有破坏性脚本 API 变更,写脚本先查目标版本 javadoc,细节见 [[gotchas]] ### ghidra-bridge(Python 远程控制) - 全平台: `pip install ghidra-bridge` - 前置: Ghidra GUI 中 Script Manager 运行 `ghidra_bridge_server.py` - 验证: `python3 -c "import ghidra_bridge; print(ghidra_bridge.__version__)"` ## 操作步骤 1. **analyzeHeadless 无头导入+分析**: ```sh $GHIDRA/support/analyzeHeadless /tmp/proj sample_proj \ -import ./sample.bin -deleteProject -log /tmp/ghidra.log ``` 只建工程不交互时加 `-overwrite`;批处理多个样本循环调用。日志看 `-log`,分析完成标志: 无异常且工程可重新导入。 - `-process` 模式(对已导入工程内文件重跑脚本/分析,与 `-import` 二选一): ```sh $GHIDRA/support/analyzeHeadless /tmp/proj sample_proj \ -process -postScript MyScript.java -scriptPath /tmp/scripts ``` - 只做符号/字符串/单函数反编译时加 `-noanalysis`(跳过自动分析,秒级完成);只读复查加 `-readOnly`;全套参数族见 [[commands]] 2. **GUI:导航/交叉引用/反编译**: - `File > Import File` → 选择样本 → `Analyze`(等左下角进度完成) - 跳转: `Go To`(G)输入地址;入口点已在 Program Trees 标记 `entry` - 交叉引用: 光标在函数/变量上按 `R`(References 窗口),或右键 > References > Show References To - 反编译: 在 Listing 中按 `Ctrl+E`(Decompiler 窗口,默认快捷键可能随版本/keymap 不同,以 Help > Key Bindings 为准)或右键 > Decompile Function,反编译视图可 copy - 函数图: 函数上按 `F`(Function Graph)看分支/循环结构,与 Decompiler 同步导航 - 下划线地址差异: Listing 显示 VA(含 ImageBase),脚本中常用 `getAddressFactory().getDefaultAddressSpace().getAddress("0x401000")` 3. **重命名+类型传播标记**: - 函数重命名: Listing 中 `L`;变量重命名: Decompiler 中 `L` - 设置类型: 右键变量 > Set Data Type(`y`),如 `char *`、`DWORD`、`int (*)(int)` - 定义结构体: Data Type Manager > 新建 Structure,Decompiler 中引用后类型传播自动改善反编译质量 - 标记已知库函数: 右键 > Set Data Type + `f`(Function signature),提升后续调用点参数语义 4. **Python 脚本(自动标注、解密循环仿真)**: ```python # @category Analysis — 放 GhidraScripts 目录,Script Manager 中 Run from ghidra.program.model.listing import CodeUnit fm = currentProgram.getFunctionManager() for f in fm.getFunctions(True): body = f.getBody() if body.getNumAddresses() > 10000: print("large:", f.getName(), hex(body.getMaxAddress().getOffset())) ``` 解密循环: 定位 XOR 循环后脚本 patch 或直接计算: ```python from ghidra.program.model.mem import * fm = currentProgram.getFunctionManager() f = fm.getFunctionAt(currentAddress) # 示例: 从 0x403000 起 0x100 字节异或 0x55 addr = currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress("0x403000") for i in range(0x100): b = getByte(addr.add(i)) ^ 0x55 setByte(addr.add(i), b) ``` - **改字节前先副本**:`setByte` 直接写当前 Program(保存后即改原始文件)——分析恶意样本必须先复制 Program(`File > Save As` 另存副本)或对临时副本操作,禁止直接 patch 原始样本,否则破坏证据链 无头批量: `analyzeHeadless ... -postScript MyScript.java -scriptPath