Ghidra Processor创建教程——从二进制到汇编代码
字数 1951 2025-08-24 07:48:33
Ghidra Processor 创建教程——从二进制到汇编代码
1. 前言
Ghidra 提供了创建自定义 Processor 的功能,允许用户将特定的二进制代码翻译为汇编指令。本教程以强网杯 2020 年初赛的 QWBLogin 为例,详细介绍如何创建一个 Processor。
2. 准备工作
2.1 安装 Eclipse
- 下载并安装 Eclipse IDE。
- 确保 Eclipse 版本与 Ghidra 兼容。
2.2 安装 GhidraDev 插件
- 插件路径:
<ghidra_install_dir>/Extensions/Eclipse/GhidraDev/GhidraDev-2.1.1.zip。 - 安装步骤:
- 打开 Eclipse,点击
Help → Install New Software...。 - 点击
Add...,然后选择Archive...。 - 浏览并选择
GhidraDev-2.1.1.zip。 - 勾选
Ghidra或GhidraDev条目,点击Next。 - 接受许可协议,完成安装并重启 Eclipse。
- 打开 Eclipse,点击
2.3 创建 Ghidra Module Project
- 在 Eclipse 中,选择
File → New → Project。 - 选择
Ghidra Module Project。 - 输入项目名称(如
qwbvm)。 - 在下一步中,仅勾选
Processor。 - 指定 Ghidra 安装目录。
- 重命名模板文件(将
skel改为qwbvm)。
3. Processor 定义
3.1 指令结构
指令格式如下:
+-opcode | inst_switch | length | x1 | x2
1byte | 4bit | 4bit | |
opcode:操作码。inst_switch:指令类型标识。length:数据长度(1-4 字节)。x1,x2:操作数(可选,长度不定)。
3.2 指令表
部分指令示例:
| 指令 | opcode | inst_switch | length | x1 | x2 |
|---|---|---|---|---|---|
| halt | 0 | 0 | - | - | - |
| mov x1, x2 | 1 | 0 | [1-4] | reg | reg |
| mov x1, bss[x2] | 1 | 1 | [1-4] | reg | imm64 |
| mov bss[x1], x2 | 1 | 2 | [1-4] | imm64 | reg |
| call x1 | 16 | 6 | - | reg | - |
| syscall | 32 | - | - | - | - |
3.3 寄存器
- 通用寄存器:
r0-r15。 - 特殊寄存器:
sp:栈指针。pc:程序计数器。
4. 配置文件详解
4.1 qwbvm.pspec
定义寄存器和处理器特性:
<processor_spec>
<programcounter register="pc"/>
<register_data>
<register name="r0" group="Alt"/>
<!-- 其他寄存器 r1-r15 -->
</register_data>
</processor_spec>
4.2 qwbvm.cspec
定义调用约定和编译器行为:
<compiler_spec>
<stackpointer register="SP" space="ram"/>
<default_proto>
<prototype name="__asmA" extrapop="2" stackshift="2" strategy="register">
<input>
<pentry minsize="1" maxsize="8"><register name="r0"/></pentry>
<!-- 其他输入寄存器 -->
</input>
<output><pentry minsize="1" maxsize="1"><register name="r0"/></pentry></output>
</prototype>
</default_proto>
</compiler_spec>
4.3 qwbvm.ldefs
定义语言和处理器属性:
<language_definitions>
<language processor="qwbvm" endian="little" size="64" variant="default"
slafile="qwbvm.sla" processorspec="qwbvm.pspec" id="qwbvm:LE:64:default">
<description>QWB VM Language Module</description>
<compiler name="default" spec="qwbvm.cspec" id="default"/>
</language>
</language_definitions>
4.4 qwbvm.slaspec
定义内存空间和寄存器:
define space ram type=ram_space size=8 default;
define space bss type=ram_space size=8;
define space register type=register_space size=8;
define register offset=0x00 size=8 [r0 r1 ... r15];
define register offset=0x100 size=8 [sp pc];
define register offset=0x200 size=8 contextreg;
@include "qwbvm.sinc"
4.5 qwbvm.sinc
定义指令解析逻辑:
define token opbyte(8) op = (0,5) rn = (0,3) rm = (0,3);
define token oplength(8) inst_switch = (0,3) data_length = (4,6);
define context contextreg addrmode = (0,2);
dl: "" is data_length=0 [addrmode=1;] {}
dl: "byte" is data_length=1 [addrmode=1;] {}
dl: "qword" is data_length=4 [addrmode=4;] {}
:mov dl rn, rm is op=1; dl & inst_switch=0; rn; rm {}
:mov dl rn, "bss"[imm64] is op=1; dl & inst_switch=1; rn; imm64 {}
5. 关键概念
5.1 Token
- 组成指令的基本单元。
- 示例:
define token data8(8) imm8 = (0,7) simm8 = (0,7) signed;
5.2 Symbol
- 用于简化指令定义。
- 示例(
dl符号):dl: "byte" is data_length=1 [addrmode=1;] {}
5.3 Context
- 根据处理器状态动态解析指令。
- 示例:
define context contextreg addrmode = (0,2);
5.4 相对地址计算
- 用于
call和跳转指令:rel: reloc is simm8 [reloc = inst_next + simm8;] {}
6. 完整指令定义示例
:halt is op=0; inst_switch & data_length {}
:mov dl rn, rm is op=1; dl & inst_switch=0; rn; rm {}
:call rel is op=0x10; inst_switch=7; rel {}
:syscall is op=0x20; inst_switch {}
7. 测试与验证
- 在 Eclipse 中运行 Processor 模块。
- 将二进制文件(如
test.bin)拖入 Ghidra。 - 选择
qwbvm作为 Processor。 - 检查反汇编结果是否符合预期。
8. 总结
通过本教程,你可以:
- 创建自定义 Processor。
- 定义指令集和寄存器。
- 使用 Token 和 Symbol 简化指令解析。
- 实现动态上下文和相对地址计算。
最终生成的 Processor 可将二进制代码准确翻译为汇编指令,适用于逆向工程和二进制分析。