【发布时间】:2016-08-08 23:56:49
【问题描述】:
我对@987654322@ 的系统调用感到困惑。当我学习linux系统调用时。我知道使用execve 的正确方法是这样的:
char *sc[2];
sc[0]="/bin/sh";
sc[1]= NULL;
execve(sc[0],sc,NULL);
然后函数execve将调用syscall()进入系统内核,并将参数放在寄存器EAX、EBX、ECX和EDX上。但是,如果我使用它仍然会成功
execve("/bin/sh",NULL,NULL);
但是如果我用"/bin/ls"替换"/bin/sh",它会失败:
A NULL argv[0] was passed through an exec system call.
我想知道为什么"/bin/sh"可以在没有足够参数的情况下成功执行而"/bin/ls"却失败了?
【问题讨论】:
-
我完全不依赖
NULL在那里工作;execve手册页说argv是一个参数字符串数组;NULL指针不是指向数组的有效指针。 (将NULL用于env看起来都不好看;相反,使用execv或execvp,或传递指向char *p = NULL的指针。) -
当作为函数参数传递时,数组是指向其第一个元素的指针,因此 NULL 在这里肯定是有效的。
-
@AnttiHaapala: Linux's
execve(2)does accept a NULL pointer,并将其视为指向空列表的指针。这是不鼓励且不可移植的,但特别是在 Linux 上是面向未来的。我见过的主要用例是利用 shellcode 在系统调用(x86int 0x80或syscall)之前将几个寄存器归零,而不是推送0并将指向它的指针放入两个寄存器。即它节省了几个字节的漏洞利用负载大小,并且如果"/bin/sh"字符串已经在负载中,则不需要写入内存。 -
@petercordes 很好,hellcodez 保持兼容
-
但是,手册页确实提到了这个例外
标签: c linux system-calls glibc shellcode