缓冲区溢出获取/bin/sh失败求助:已找到返回地址但触发段错误
缓冲区溢出触发段错误的排查思路
你已经找到了返回地址但还是触发SIGSEGV,说明溢出的payload或者跳转逻辑还有问题,结合你给出的gdb回溯信息,我整理了几个常见的排查方向:
1. 返回地址的准确性存疑
你认为“正确”的返回地址可能存在计算偏差:
- ASLR干扰:如果系统开启了地址空间随机化(ASLR),每次运行程序时栈、libc的地址都会变化。可以先查看ASLR状态:
输出为cat /proc/sys/kernel/randomize_va_space2表示完全开启,临时关闭需要root权限:
关闭后重新计算返回地址,确保是固定的目标位置。echo 0 > /proc/sys/kernel/randomize_va_space - 偏移量计算错误:栈布局可能因环境变量、程序参数不同而变化。可以用pattern工具验证:
- 生成溢出模式:
pattern_create 200(假设缓冲区大小约200) - 发送模式触发崩溃,用
pattern_offset $eip(崩溃时的eip值)得到准确的覆盖偏移。
- 生成溢出模式:
2. 栈保护机制阻止了溢出
程序可能编译时开启了栈金丝雀(Stack Canary),溢出时覆盖了金丝雀值会直接触发崩溃:
- 用
checksec ./your_program查看保护机制,若显示Stack Canary: Enabled,需要先在调试中泄露金丝雀值,再在payload中精准覆盖(不能破坏金丝雀的校验逻辑)。
3. 目标内存不可执行(NX保护)
如果程序开启了NX(No eXecute)保护,栈上的shellcode无法执行,直接跳栈地址会触发段错误:
- 同样用
checksec确认NX状态,若开启,需要改用ret2libc或ROP链:- 找到
system函数的地址(在gdb中执行p system) - 找到
/bin/sh字符串的地址(在gdb中执行find &system,+9999999,"/bin/sh") - 构造payload:
padding + system_addr + 垃圾填充(占位返回地址) + bin_sh_addr
- 找到
4. 溢出长度不足,未真正覆盖返回地址
从你的gdb回溯看,程序还在原函数调用链(msg→my_function)中崩溃,说明返回地址可能没被覆盖,或者覆盖后跳转到了无效的代码区域:
- 在gdb中给
my_function的返回点设断点:b *my_function+912 - 发送payload后查看栈帧:
x/20x $ebp+8(32位程序中,返回地址存在ebp+8位置) - 确认返回地址是否被替换成你预设的值,若没有,说明padding长度不够,需要调整payload的填充字节数。
调试小技巧
先不要直接跳shellcode,先构造payload跳转到一个已知的断点地址(比如先在gdb中设b *0xdeadbeef,然后把返回地址设为0xdeadbeef),确认溢出能成功劫持程序流程,再替换成shellcode或ret2libc的地址。
内容的提问来源于stack exchange,提问作者Soatl
相关产品推荐
相关产品推荐

