You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

x64架构栈溢出测试中无法控制RIP寄存器的原因排查

x64环境下栈溢出无法覆盖RIP的问题排查

可能的原因及解决方法

1. 编译选项未关闭栈保护/PIE

默认GCC编译会启用栈金丝雀(Stack Canary)和位置无关可执行文件(PIE):

  • 栈金丝雀会在栈帧中插入随机值,溢出覆盖到该值时,程序会直接触发__stack_chk_fail崩溃,根本无法触及返回地址(RIP)。
  • PIE会随机化程序内存地址,但你的问题是RIP未被覆盖,所以核心问题是栈保护。

解决:用以下命令重新编译程序,关闭栈保护和PIE,禁用优化:

gcc -fno-stack-protector -no-pie -O0 vuln.c -o vuln

2. 偏移量计算错误

你计算的偏移量15不符合x64栈帧的基本布局:
x64栈帧中,局部变量s[8]之后是旧RBP(8字节),再往上才是返回地址(RIP的目标值,8字节)。理论上,要覆盖返回地址,至少需要填满s的8字节 + 旧RBP的8字节,共16字节填充,第17-24字节才会覆盖RIP。

错误的偏移量可能来自:

  • 使用pattern_create时生成的字符串长度不足,未覆盖到返回地址区域;
  • 崩溃时错误读取了RSP而非RBP/返回地址的内容来计算偏移。

解决:

  1. 生成足够长的pattern(比如32字节):pattern_create 32;
  2. 在GDB中运行程序,输入该pattern触发崩溃;
  3. 查看崩溃时rip寄存器的值,或查看rbp+8位置的内存(返回地址存在这里);
  4. 用pattern_offset <获取到的pattern片段>重新计算偏移。

3. 栈对齐导致的填充字节

x64要求栈指针RSP保持16字节对齐,编译器可能会在局部变量和旧RBP之间插入填充字节,导致实际偏移量大于理论值。

解决:手动查看栈布局确认偏移:

  1. 在vgetstr(s);处设置断点:b main:10(对应代码行号);
  2. 运行到断点后,执行p &s获取s的地址,p $rbp获取当前RBP值;
  3. 计算$rbp - &s得到s到旧RBP的字节数,再加上8(旧RBP的长度)就是到返回地址的偏移;
  4. 也可以用x/20x $rbp-0x20查看栈内存,直观确认各区域的位置。

4. 代码逻辑的隐性问题

你的vgetstr函数中,for循环的写法虽然语法正确,但要确认字符写入逻辑无问题:

for(p = s; (c = getchar()) != EOF && c != '\n'; p++)                                                                                          
*p = c;

这段代码会正确将每个输入字符写入s及后续栈区域,溢出逻辑是成立的,无需修改。

内容的提问来源于stack exchange,提问作者KmerPadreDiPdor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 23:30:57