Ghidra 开源逆向分析工具详解
本文介绍了逆向工程常用命令(file、strip、nm 等)、平台特定工具及对抗技术,详细解析了 Ghidra 框架的语言 ID 规范、特殊前缀、协作分析及无头模式脚本开发接口。文章涵盖了堆栈机制、函数重载名称修饰等底层知识,并提供了 Ghidra 二次开发的 Java/Python API 参考及命令行参数详解,适合安全研究人员及逆向工程师参考。

本文介绍了逆向工程常用命令(file、strip、nm 等)、平台特定工具及对抗技术,详细解析了 Ghidra 框架的语言 ID 规范、特殊前缀、协作分析及无头模式脚本开发接口。文章涵盖了堆栈机制、函数重载名称修饰等底层知识,并提供了 Ghidra 二次开发的 Java/Python API 参考及命令行参数详解,适合安全研究人员及逆向工程师参考。

作用:检查文件类型的强大工具,不依赖文件扩展名,而是基于文件内容识别。
检查原理:
什么是幻数? 文件格式要求的特殊标签值,通常位于文件头部。
- MS-DOS 可执行文件:
MZ(Mark Zbikowski, MS-DOS 架构设计师姓名缩写)- Java Class 文件:
0xcafebabe(便于记忆的十六进制值)- Windows PE 可执行文件:
4D5A(即 ASCII 的 'MZ')- JPG 图片文件:
FFD8...结尾通常包含4A464946(ASCII 的 'JFIF')幻数定义文件位置:
/usr/share/file/magic、/usr/share/misc/magic、/etc/magic
作用:剥离二进制文件中的符号表(Symbol Table)和调试信息。
作用:列出目标文件(如 ELF 可执行文件、.o 中间文件)中的符号表。
符号字母说明:
U (Undefined):未定义的符号,通常引用自外部库或其他文件。T / t (Text):代码段定义的符号。T 为全局函数,t 为静态函数(本地)。D / d (Data):已初始化的数据段。D 为全局变量,d 为局部静态变量。C (Common):未初始化的数据(通常在全局区)。B / b (BSS):未初始化的数据段。不同平台下查看可执行文件所需动态链接库的命令:
| 平台 | 工具/命令 | 使用示例 | 备注 |
|---|---|---|---|
| Linux | ldd | ldd <可执行文件名> | 最常用 |
| Linux | objdump / readelf | readelf -d <文件名> | 基于 libbfd,提供更底层信息 |
| Windows | dumpbin | dumpbin /dependents <文件名> | 需安装 Visual Studio |
| macOS | otool | otool -L <可执行文件名> | macOS 原生工具 |
作用:将 C++ 编译器生成的修饰名(Mangled Names)还原为可读的函数名。 典型用法:配合 nm 使用,分析重载函数。
nm <文件名> | c++filt
作用:从二进制文件中提取可打印的字符串序列。 典型用法:
strings <文件名>
常用参数:
-t [o|x|d]:打印字符串的偏移量(八进制、十六进制或十进制),便于定位。-e [s|S|l|L|b|B|h|H]:指定字符编码(如 UTF-8, UTF-16 等),用于搜索宽字符。-a:扫描整个文件,而不仅仅是数据段(默认只扫描已加载的数据区)。-n <len>:设置最小字符串长度(默认为 4)。用于增加逆向分析难度的加壳或混淆工具:
UPX (开源,主要压缩体积,易脱壳), ASPack。ASProtect, Themida, TELock, VMProtect (虚拟化保护,难度较高)。pop 操作通常只是移动栈顶指针(ESP/RSP),并不会立即清除内存中的数据。_start -> __libc_start_main -> main)。C++ 支持函数重载,编译器会将函数名、参数类型、命名空间等信息编码成唯一的符号名。
void SubClass::vfunc1()?vfunc1@SubClass@@UAEXXZ
? 开头,@ 分隔符,包含类名、调用约定、返回类型等信息。_ZN8SubClass6vfunc1Ev
_Z 开头,N 表示命名空间/类,数字表示后续标识符长度,E 结束,v 表示 void。c++filt 可相互转换。Ghidra 在反编译窗口中会对变量和地址添加前缀以区分类型:
| 前缀 | 含义 | 说明 |
|---|---|---|
param_ | 参数 | 传递给函数的参数。 |
local_ | 局部变量 | 函数栈帧内的局部变量。 |
undefined4 | 未知类型 | 编译器无法确定具体类型,长度为 4 字节的变量。 |
LAB_address | 代码标签 | 自动生成的代码跳转目标地址。 |
DAT_address | 数据标签 | 全局数据或静态数据地址。 |
FUN_address | 函数标签 | 已识别的函数入口地址。 |
SUB_address | 子程序标签 | 被调用但未被完全确认为标准函数的地址。 |
EXT_address | 外部符号 | 外部导入的函数或变量。 |
OFF_address | 偏移/中断 | 可能指向中断向量、数据偏移或错误处理。 |
UNK_address | 未知 | Ghidra 无法识别其属性或用途的地址。 |
注:
address代表具体的十六进制地址值。
Ghidra 使用特定的字符串标识处理器架构和模式,格式如下:处理器:端序:位宽:变体/模式:编译器
x86, x86_64, ARM, MIPS, AARCH64 等。LE:小端序(Intel x86, ARM 默认)。BE:大端序(部分 MIPS, 旧版 ARM)。16, 32, 64 (指寄存器宽度/地址总线宽度)。real (实模式), protected (保护模式), v86 (虚拟 8086)。v4, v5, v7, v8, thumb (Thumb 指令集模式)。gcc, borlandcpp, borlanddelphi, msvc 等,有助于优化反编译逻辑。示例:x86:LE:32:default:gcc
API:提供丰富的 API 访问反汇编列表、反编译伪代码、符号表等。
| 方法签名 | 功能描述 |
|---|---|
public void popup(final String message) | 弹出提示框:在对话框中显示信息并要求用户选择。 |
public String askString(String title, String message) | 字符串输入框:带标题和提示信息的文本输入对话框。 |
public boolean askYesNo(String title, String message) | 确认对话框:询问是或否的问题。 |
public Address askAddress(String title, String message) | 地址输入框:解析用户输入的地址字符串。 |
public int askInt(String title, String message) | 整数输入框:获取用户输入的整数值。 |
public File askFile(final String title, final String approveButtonText) | 文件选择器:让用户选择文件。 |
public File askDirectory(final String title, ...) | 文件夹选择器:让用户选择目录。 |
public void printf(String message, Object... args) | 格式化输出:类似 C 语言的 printf,将格式化后的内容输出到控制台。 |
public void println(String message) | 普通输出:非入侵式地打印一行信息到控制台。 |
| 接口 | 方法 | 功能描述 |
|---|---|---|
| 地址 | getOffset() | 获取地址的长整型偏移值。 |
| 符号 | getAddress() | 获取该符号所在的内存地址。 |
| 符号 | getName() | 获取符号的名称字符串。 |
| 方法 | 功能描述 |
|---|---|
getFromAddress() | 获取引用的源地址。 |
getToAddress() | 获取引用的目的地址。 |
getReferenceType() | 获取引用的类型。 |
| 变量名 | 类型 | 功能描述 |
|---|---|---|
currentProgram | Program | 当前打开的程序:代表正在分析的二进制文件对象。 |
currentAddress | Address | 当前光标地址:用户在反汇编窗口中光标所在的地址。 |
currentLocation | ProgramLocation | 当前位置详情:包含地址及更具体的上下文信息。 |
currentSelection | ProgramSelection | 当前选中范围:用户在 GUI 中高亮选中的地址区域。 |
| 变量/方法 | 功能描述 |
|---|---|
monitor (TaskMonitor) | 任务监视器:用于更新长时间运行任务的状态进度条。 |
monitor.isCancelled() | 检查取消状态:判断用户是否点击了'取消'按钮。通常在循环中调用此方法以优雅地退出脚本。 |
analyzeHeadless 脚本。常用参数详解
基本命令结构:
analyzeHeadless <项目路径> <项目名称> -import <文件路径> -scriptPath <脚本目录> -postScript <脚本名>.py
| 参数 | 说明 | 示例 |
|---|---|---|
-import | 导入文件,支持通配符 | -import *.dll |
-scriptPath | 添加脚本搜索路径 | -scriptPath /home/user/scripts |
-postScript | 分析后执行的脚本(可多次使用) | -postScript dump_funcs.py |
-scriptArgs | 传递给脚本的参数 | -scriptArgs output.txt |
-deleteProject | 处理完后删除项目目录 | (无参数) |
-projectBackup | 是否备份项目 | -projectBackup false |
-log | 指定日志文件 | -log analysis.log |
-help | 显示帮助信息 | -help |

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online