在 Linux 下进行反汇编(disassembly)后,看懂结果是学习逆向和底层的重要一步。下面从常用工具 → 反汇编输出结构 → 如何读懂汇编 → 实战例子逐步说明。
objdump(最常用)objdump -d ./a.out
常用参数:
-d:反汇编可执行代码-M intel:使用 Intel 语法(默认是 AT&T)-S:源码+汇编混合objdump -d -M intel -S ./a.out
gdb(动态调试看反汇编)gdb ./a.out
(gdb) disass main
或:
(gdb) set disassembly-flavor intel
(gdb) disassemble main
objdump vs gdb| 工具 | 特点 |
|---|---|
| objdump | 静态分析,看完整函数 |
| gdb | 动态调试,可看运行时寄存器 |
以 Intel 语法为例:
0000000000400526 <main>:
400526: 55 push rbp
400527: 48 89 e5 mov rbp, rsp
40052a: 48 83 ec 10 sub rsp, 0x10
40052e: c7 45 fc 0a 00 00 00 mov DWORD PTR [rbp-0x4], 0xa
400535: b8 00 00 00 00 mov eax, 0x0
40053a: c9 leave
40053b: c3 ret
400526:
b *0x400526 下断点55
48 89 e5
push rbp
mov rbp, rsp
这才是重点
几乎每个函数都长这样:
push rbp
mov rbp, rsp
sub rsp, 0x10
含义:
结束:
leave
ret
int main() {
int a = 10;
return 0;
}
mov DWORD PTR [rbp-0x4], 0xa
解读:
rbp-0x4 → 局部变量 a0xa → 十进制 10DWORD → 4 字节(int)call 0x400430 <printf@plt>
调用前通常:
mov edi, 0x4005c0 ; 第一个参数
x86-64 调用约定(System V):
| 寄存器 | 用途 |
|---|---|
| rdi | 第1参数 |
| rsi | 第2参数 |
| rdx | 第3参数 |
| rax | 返回值 |
| 指令 | 含义 |
|---|---|
mov |
赋值 |
push/pop |
栈操作 |
call |
函数调用 |
ret |
返回 |
cmp |
比较 |
je/jne |
条件跳转 |
lea |
取地址 |
if (a == 5) {
b = 1;
}
cmp DWORD PTR [rbp-4], 0x5
jne 400560
mov DWORD PTR [rbp-8], 0x1
解读:
cmp 比较jne 不相等就跳走✅ 先写 C → 再反汇编
✅ 对比看(源码 vs 汇编)
✅ 用 gdb 单步执行
✅ 熟悉 调用约定
如果你愿意,可以:
我可以直接帮你逐行解释。