GDB的<<<与Shell的|有何差异?缓冲区溢出攻击结果为何不同
缓冲区溢出:GDB与Shell执行差异的核心原因
以下是导致你在GDB中攻击成功但普通Shell中失败的关键因素:
1. ASLR(地址空间布局随机化)的状态差异
GDB默认会自动禁用ASLR,所以你在GDB中查到的re_in函数地址0x5555559884是固定不变的。但Termux的普通Shell环境默认开启ASLR,每次启动程序时,程序的基地址都会随机偏移,导致re_in函数的实际运行地址和你在GDB中记录的地址完全不匹配,硬编码的跳转地址自然无法命中目标。
2. 栈布局的环境差异
GDB启动程序时,会向进程注入额外的调试相关环境变量,同时调试上下文也会改变进程的栈起始位置。这导致你在GDB中测试出的缓冲区溢出偏移量(即前面的aaaaaaaaaaaaaaaaaa长度),在普通Shell环境中不再适用——栈的整体位置变了,覆盖返回地址的偏移也就错了,哪怕关闭ASLR,也可能因为栈偏移不对导致跳转失败。
3. 输入传递的细微区别
- 使用
run <<< $(printf ...)时,Shell会把printf的输出作为here-string传递给程序,输入会被包裹在临时文件中,程序读取时的EOF处理逻辑和管道略有不同。 - 而
printf ... | ./overflow是通过管道传递标准输入,部分程序在读取管道输入时,可能会因为输入流的结束方式(管道EOF是关闭文件描述符,here-string是文件自然结束)导致缓冲区填充的细节差异,但这个因素通常是次要的,核心还是前两点。
验证与解决方向
- 临时关闭ASLR:执行
echo 0 > /proc/sys/kernel/randomize_va_space(需root权限),再重新测试地址是否匹配。 - 重新计算Shell环境下的偏移:关闭ASLR后,在Shell中重新测试缓冲区边界,找到正确的偏移量和函数地址。
- 用更稳定的方式生成攻击串:比如
python -c 'print("a"*20 + "\x84\x98\x55\x55\x55")' | ~/temp/overflow,避免Shell命令替换可能带来的字符转义问题。
内容的提问来源于stack exchange,提问作者ho tian
相关产品推荐
相关产品推荐

