温馨提示×

linux反汇编怎样看栈帧

小樊
44
2026-09-30 14:04:39
栏目: 智能运维

在 Linux 下进行反汇编(如用 objdump、gdb、IDA、radare2 等)时,“看栈帧”本质上就是理解函数调用时栈是怎么布局的,以及当前指令如何使用 %rsp/%rbp(x86-64)或 %esp/%ebp(x86-32)。下面按实用角度讲。


一、先明确:栈帧是什么

栈帧(stack frame)通常包含:

  • 返回地址(caller 的下一行)
  • 保存的旧 %rbp
  • 局部变量
  • 函数参数(超出寄存器部分)
  • 对齐填充

在 x86-64 上常见布局:

高地址
| 调用者栈帧 |
| 参数(n)    |
| 返回地址   |  <- %rsp 在 call 后指向这里
| 旧 %rbp    |  <- 被 callee 压入
| 局部变量   |  <- %rbp - 0x8 等
低地址

二、从反汇编看栈帧(典型模式)

1. 函数开头(prologue)

push   %rbp
mov    %rsp,%rbp
sub    $0x20,%rsp

含义:

  • 保存调用者 %rbp
  • 建立自己的栈帧基址
  • 分配局部变量空间

此时:

  • %rbp:当前函数栈帧基址
  • %rbp+8:返回地址
  • %rbp+16:第 1 个栈上传参
  • %rbp-8 等:局部变量

2. 访问局部变量

mov    -0x4(%rbp),%eax

说明:

  • 局部 int 在 %rbp-4
lea    -0x20(%rbp),%rdi

说明:

  • 把局部变量地址传给函数

3. 访问参数

mov    %rdi,-0x8(%rbp)

说明:

  • 第 1 个参数(%rdi)存到局部变量

若参数多:

mov    0x10(%rbp),%rax

说明:

  • 第 2 个栈上传参(%rbp+16)

三、用 GDB 实际看栈帧(最推荐)

1. 反汇编 + 断点

gdb ./a.out
(gdb) disas main
(gdb) b main
(gdb) run

2. 查看寄存器

info registers rsp rbp rip

3. 查看栈内容

x/10gx $rsp
x/20x $rsp

4. 查看栈帧

bt
frame 0
info frame

5. 单步看栈变化

stepi
x/10x $rsp

四、没有 %rbp 的栈帧(优化代码)

编译器常省略:

sub $0x18,%rsp

此时:

  • 没有 push %rbp
  • 所有变量用 %rsp 偏移

例如:

mov %edi,0xc(%rsp)

看这种代码要:

  • 盯 %rsp
  • 结合 sub $N,%rsp 估算变量位置

五、用 radare2 / objdump 辅助

objdump -d -M intel ./a.out

或

r2 -d ./a.out
pdf
af
afv

afv 会直接列出:

  • 局部变量
  • 参数
  • 栈偏移

六、快速判断技巧

  • 看到 push %rbp → 有栈帧
  • 看到 mov %rsp,%rbp → %rbp 是基准
  • 看到 sub $N,%rsp → 局部变量大小
  • 看到 call → 返回地址入栈
  • 看到 -0x?(%rbp) → 局部变量
  • 看到 +0x?(%rbp) → 参数 / 返回地址

如果你愿意,可以:

  • 贴一段 具体反汇编代码
  • 或说明你是 x86 / x64 / ARM
  • 或你是看 漏洞利用 / 逆向 / 调试崩溃

我可以直接帮你“逐行读栈帧”。

0 踩