VulnHub Venus缓冲区溢出:自定义/bin/sh触发system()失败求助
问题分析与解决思路
这种差异的核心原因在于你传入payload中的/bin/sh字符串的有效性、地址准确性,或是栈内存的可访问属性问题,具体拆解如下:
1. 栈地址计算错误,rdi指向的不是/bin/sh的起始位置
当你把/bin/sh放在payload里时,必须精准计算它在栈上的偏移地址。如果地址算错(比如溢出后的栈偏移和预期不符,或是没考虑栈帧变化),rdi寄存器就会指向栈上的垃圾数据,而非完整的/bin/sh字符串:
- 比如你误以为
/bin/sh在偏移+24的位置,但实际溢出覆盖ebp/rip后,栈的实际起始位置比预期多了8字节,此时rdi指向的是/bin/sh的中间字符(比如n/sh),甚至是后续的gadget地址,system()调用的就是无效命令,自然会报sh: 1: : not found,后续还会因栈结构混乱触发段错误。 - 验证方法:用gdb调试,在
system()调用前断下,查看rdi寄存器的值,再用x/s <rdi地址>查看内存中是否是完整的/bin/sh\x00。
2. payload中的/bin/sh缺少终止符\x00
C语言字符串以\x00(null字节)作为终止标志。如果payload里只写了/bin/sh而没加\x00,system()会从rdi指向的地址开始读取,直到遇到内存中的第一个null字节,期间会把后续的payload内容(比如system地址、gadget地址)也当成命令的一部分,导致sh解析出无效的长命令从而报错。
3. 输入处理函数截断或修改了payload中的字符串
有些程序会用fgets、scanf这类函数处理输入,可能截断换行符、空格,或是对特殊字符做转义。比如用echo传payload时没加-n,导致多了一个换行符,/bin/sh变成/bin/sh\n,部分shell解析时会把换行当成命令的一部分,从而引发错误。
4. 栈内存权限问题(少见但可能)
极少数情况下,程序栈内存被设置了不可读(虽几乎不可能,因为栈必须可读),或是payload所在的栈区域在system()调用时已被覆盖、释放。不过这种情况通常直接触发段错误,而非先报sh的错误,优先级较低。
验证与修复步骤
- 用gdb调试,在
pop rdi指令后断下,查看rdi的值,再用x/s <rdi地址>确认字符串完整性。 - 确保payload中的
/bin/sh后面加上\x00终止符。 - 重新计算栈上
/bin/sh的准确地址:可在payload中插入独特标记(比如AAAA),溢出后查看栈内存中标记的位置,以此推算偏移。 - 用
printf代替echo传payload,避免自动添加换行符,示例:printf '填充字节\xxx\xxx\xxx\xxx\xxx\xxx\xxx\xxx/bin/sh\x00' | ./venus
内容的提问来源于stack exchange,提问作者DeceptiveRat
相关产品推荐
相关产品推荐

