Ret2libc利用异常输出求助:执行shell时出现命令未找到错误
问题分析与解决方法
我之前在做Ret2libc漏洞利用的时候完全碰到过一模一样的报错!当时折腾了好半天终于搞明白问题出在哪,给你拆解下:
核心原因
你看到的这些sh: 1: 34:ln=01: not found错误,本质是栈上的垃圾二进制数据被shell当成了命令或环境变量解析:
- 当你通过Ret2libc调用
system("/bin/sh")时,shell会继承当前进程的argv/envp指针。如果你的溢出 payload 没有正确清理栈后续的垃圾数据,或者没有给argv数组加上终止的NULL,shell就会把栈里的乱码(比如溢出填充的字节、未覆盖的栈原有数据)当成要执行的命令行参数,或者格式错误的环境变量键值对(比如那些34:ln=01其实是二进制字节被转成ASCII后的无效格式)。 - 另一种可能是你构造的Ret2libc参数有误:比如32位程序中,
system的参数栈位后面没有跟NULL(argv数组必须以NULL结尾),导致shell把后续栈数据当成了额外的命令参数。
解决方法
1. 给/bin/sh参数添加终止NULL
这是最常见的修复方式:
- 32位程序:构造payload时,在
/bin/sh的地址后面,额外添加至少4字节的0x00(因为32位指针是4字节),确保system调用时,argv数组只有/bin/sh一个元素,后面没有垃圾数据。典型payload结构:padding(填充到返回地址) + system地址 + exit地址(可选,防止shell退出后程序崩溃) + /bin/sh地址 + 0x00000000 - 64位程序:除了确保
rdi寄存器正确指向/bin/sh地址外,还要在栈上/bin/sh地址的位置后面覆盖几个0x00字节,避免后续垃圾被解析成环境变量。
2. 清理栈上的垃圾数据
用gdb查看溢出后的栈布局(比如x/20wx $esp或x/20gx $rsp),找到/bin/sh地址后面的垃圾区域,调整payload长度,把这些区域全部覆盖成0x00,而不是用A或其他填充字节。
3. 改用execve代替system
system会启动shell并继承当前进程的环境,容易受栈垃圾影响;而execve("/bin/sh", NULL, NULL)直接替换当前进程,不需要处理额外的argv/envp,更干净:
- 32位:找
execve的地址,依次压入NULL(envp)、NULL(argv)、/bin/sh地址,再跳转到execve。 - 64位:设置
rdi=/bin/sh,rsi=0,rdx=0,然后调用execve。
4. 检查环境变量干扰
如果目标程序的环境变量里有奇怪的内容,也可能被shell解析,但这种情况比较少见。可以用unset清理环境变量后再运行漏洞程序,或者在payload里覆盖掉envp的指针。
内容的提问来源于stack exchange,提问作者alexsius
相关产品推荐
相关产品推荐

