温馨提示×

linux反汇编如何看栈帧

小樊
38
2026-10-20 23:42:04
栏目: 智能运维

在 Linux 下进行反汇编(如用 objdump、gdb、IDA、Ghidra 等)时,**“看栈帧”**通常是指理解:

  • 函数调用时栈是如何布局的
  • 局部变量、参数、返回地址在哪里
  • 如何通过 ebp/rbp 和 esp/rsp 还原栈结构

下面从原理 + 实际反汇编示例两个层面讲。


一、栈帧的基本原理(x86 / x86-64)

1. 什么是栈帧(Stack Frame)

每次函数调用,都会在栈上分配一块空间,称为栈帧,一般包括:

高地址
|------------------|
| 参数(如有)     |
|------------------|
| 返回地址         |
|------------------|
| 旧 rbp/ebp       |  <- 当前函数 rbp 指向这里
|------------------|
| 局部变量         |
|------------------|
| 临时数据         |
低地址

2. x86(32 位)栈帧

典型函数开头(prologue):

push ebp
mov  ebp, esp
sub  esp, 0x10   ; 分配局部变量空间

函数结束(epilogue):

mov esp, ebp
pop ebp
ret

访问方式:

  • [ebp+8]:第 1 个参数
  • [ebp+12]:第 2 个参数
  • [ebp-4]:第 1 个局部变量

3. x86-64(64 位)栈帧

  • 前 6 个参数:rdi, rsi, rdx, rcx, r8, r9
  • 多余参数才入栈
  • 常用 rbp 作为帧指针(可被优化掉)

典型代码:

push rbp
mov  rbp, rsp
sub  rsp, 0x20

访问:

  • [rbp-0x8]:局部变量
  • [rbp+0x10]:栈上传参

二、用 objdump 看栈帧

示例 C 代码:

int add(int a, int b) {
    int c = a + b;
    return c;
}

反汇编:

gcc -O0 -g -o test test.c
objdump -d -M intel test

看到:

push rbp
mov  rbp, rsp
mov  DWORD PTR [rbp-4], edi
mov  DWORD PTR [rbp-8], esi
mov  eax, [rbp-4]
add  eax, [rbp-8]
mov  [rbp-12], eax
mov  eax, [rbp-12]
pop  rbp
ret

分析:

  • rbp-4:参数 a
  • rbp-8:参数 b
  • rbp-12:局部变量 c

三、用 GDB 动态看栈帧

1. 查看栈帧

(gdb) break add
(gdb) run
(gdb) info frame

输出示例:

Stack frame at 0x7fffffffe1a0:
 rip = 0x401126 in add
 saved rip = 0x40115a
 called by frame at 0x7fffffffe1c0

2. 查看寄存器

info registers

重点看:

  • rsp / rbp
  • rip

3. 查看栈内存

x/10x $rbp-0x20

或:

x/8xw $rsp

四、栈帧分析技巧

1. 找 prologue / epilogue

看到:

push rbp
mov  rbp, rsp

→ 这是一个标准栈帧

2. 看 sub rsp, xxx

sub rsp, 0x40

→ 分配了 64 字节局部变量

3. 看访问偏移

  • rbp - x:局部变量
  • rbp + x:参数 / 返回地址

4. 注意优化

  • -O2 可能 没有 rbp
  • 直接用 rsp 偏移访问

五、常见栈帧布局速查表(x86-64)

位置 含义
rbp+8 返回地址
rbp+16 第 7 个参数
rbp 旧 rbp
rbp-8 局部变量
rsp 栈顶

六、推荐工具组合

  • 静态分析:objdump / IDA / Ghidra
  • 动态分析:gdb + pwndbg
  • 可视化栈:pwndbg 的 stack 命令

如果你愿意,可以:

  • 贴一段 具体反汇编代码
  • 或说明你是 pwn / 逆向 / 调试 crash

我可以直接帮你“手拆栈帧”。

0 踩