看懂 Linux 下的反汇编,核心不是“背指令”,而是建立一套从“程序 → 汇编 → 你在看什么”的认知框架。下面我按由浅入深 + 实战角度来讲,适合初学者到进阶。
Linux 下常见的反汇编来源有 3 种:
| 类型 | 常见工具 | 说明 |
|---|---|---|
| ELF 可执行文件 | objdump |
静态反汇编 |
| 正在运行的程序 | GDB | 动态反汇编 |
| 二进制流 | ndisasm / capstone |
裸机器码 |
最常见的是:
objdump -d ./a.out
或:
gdb ./a.out
(gdb) disassemble main
Linux 反汇编 90% 是 x86-64(AMD64)。
你需要知道:
mov -0x4(%rbp),%eax
特点:
%$()mov eax, [rbp-4]
✅ 强烈建议初学用 Intel 语法
objdump -M intel -d ./a.out
或 GDB:
set disassembly-flavor intel
| 寄存器 | 作用 |
|---|---|
rax |
返回值 |
rsp |
栈顶 |
rbp |
栈底(帧指针) |
rdi rsi rdx rcx r8 r9 |
函数参数 |
rip |
当前指令地址 |
int add(int a, int b) {
return a + b;
}
编译:
gcc -O0 -fno-pic -o test test.c
反汇编(Intel 语法):
add:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], edi
mov DWORD PTR [rbp-8], esi
mov eax, DWORD PTR [rbp-4]
add eax, DWORD PTR [rbp-8]
pop rbp
ret
push rbp ; 保存调用者栈帧
mov rbp, rsp ; 建立新栈帧
mov [rbp-4], edi ; 参数 a
mov [rbp-8], esi ; 参数 b
mov eax, [rbp-4]
add eax, [rbp-8] ; a + b
pop rbp
ret ; 返回
✅ 返回值一定在 rax
Linux 程序不是“直接跑”,而是:
用户态 → syscall → 内核
mov rax, 60 ; syscall 号
mov rdi, 0 ; 参数
syscall
常见 syscall 号(x86-64):
| syscall | 号 |
|---|---|
| read | 0 |
| write | 1 |
| open | 2 |
| exit | 60 |
if (a > b) return 1;
cmp edi, esi
jle .L1
mov eax, 1
ret
.L1:
关键指令:
cmp:比较jxx:条件跳转| 指令 | 含义 |
|---|---|
| je | 相等 |
| jne | 不相等 |
| jg | 有符号大于 |
| jl | 有符号小于 |
高地址
...
rbp
局部变量
rsp
低地址
常见模式:
sub rsp, 16 ; 开栈
mov [rbp-4], 5
先找函数边界
push rbp / mov rbp, rspret找参数
rdi, rsi, rdx...找返回值
rax找逻辑
忽略噪音
| 工具 | 用途 |
|---|---|
objdump -M intel |
静态反汇编 |
gdb |
动态调试 |
radare2 / r2 |
逆向 |
IDA Free |
图形化 |
Compiler Explorer |
看 C → 汇编 |
✅ 第 1 阶段(1 周)
✅ 第 2 阶段(2 周)
✅ 第 3 阶段
✅ 第 4 阶段
你可以直接说一句:
“用这个 C 程序,帮我逐行讲反汇编”