如何构造输入触发缓冲区溢出将num从-200改为400并绕过栈保护?
栈溢出修改变量并绕过Stack Smashing保护的方法
一、当前输入无效的原因
你的测试代码里,letters[20]是20字节数组,后续跟着long num变量。当前输入的"aaaabbbbccccdddd600"长度不足20字节,连letters数组都没填满,更不可能覆盖到栈上的num。另外,GCC默认启用Stack Smashing Protector(SSP/栈金丝雀),一旦栈上的金丝雀值被非法覆盖,程序就会触发栈溢出检测并终止。
二、测试环境下关闭栈保护(最直接方案)
如果仅用于测试栈溢出修改变量的逻辑,编译时可以关闭SSP保护,同时关闭位置无关执行(PIE)方便调试:
gcc -fno-stack-protector -no-pie -O0 your_code.c -o test_overflow
-fno-stack-protector:禁用栈金丝雀保护-no-pie:关闭位置无关执行,固定栈变量地址-O0:禁用编译器优化,确保num变量存储在栈上而非寄存器
三、构造正确的溢出输入
1. 确定栈填充长度
栈上letters数组占20字节,假设无额外对齐填充(可通过GDB调试确认),需要先输入20个任意字符填满letters,再覆盖后续的num变量。
2. 转换目标值为字节序
目标值400的十六进制是0x00000190,x86架构默认是小端字节序,所以需要将字节按0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00的顺序写入(long类型占8字节)。
3. 生成输入并测试
用Python生成符合要求的输入,通过管道传递给程序:
python3 -c "print('a'*20 + b'\x90\x01\x00\x00\x00\x00\x00\x00'.decode('latin-1'), end='')" | ./test_overflow
执行后就能看到num的值被修改为400。
四、不关闭栈保护的绕过思路(进阶)
如果必须保留SSP保护,绕过难度会大幅提升:
- 栈金丝雀是随机生成的,且最后一个字节固定为
0x00(用于截断gets的读取),无法通过gets直接泄漏完整金丝雀值 - 若要覆盖
num,必须先精准覆盖金丝雀值,但金丝雀的随机性导致每次运行都需要重新获取,而常规手段无法在这个场景下实现泄漏
因此,测试栈溢出修改变量的场景,关闭SSP是最实用的方案。
内容的提问来源于stack exchange,提问作者Bryan Mak
相关产品推荐
相关产品推荐

