2017-08-01 37 views
0

考虑下面的C码(x86_64的)将空程序参数向量传递给execve()是否合法?

#include <unistd.h> 
int main() 
{ 
    execve("/bin/ls", 0, 0); 
} 

予编译为gcc a.c和执行;我得到了SIGABRT错误

A NULL argv[0] was passed through an exec system call. 
Aborted 

下一页上gdb下运行,起初我也得到了SIGABRT,但是我做了第二次运行和它的工作!

Starting program: /bin/ls 
[Thread debugging using libthread_db enabled] 
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". 

为什么?


我测试了/bin/sh,发现它总是以* argv的[] = NULL工作...
我又写了一些可执行文件(不包括所需要的任何参数)来测试,发现所有这些工作。

所以我猜只有/bin/sh或其他shell可以将* argv []设置为NULL,其他文件(如/bin/ls)会失败或意外行为。

+0

阅读[未定义行为](https://en.wikipedia.org/wiki/Undefined_behavior)。 –

+0

阅读https://linux.die.net/man/2/execve并查看它期望的参数。 –

+0

是的,我知道这是UB,execve()期望的是什么参数,但有什么方法可以找出它为什么工作,或者只是运气。 我正在解决一些安全挑战,如果我能找出它的工作原理,这对我的shellcode可能是一个很大的改进。 – poming

回答

3

execve()系统调用的手册页说

argvenvp阵列必须各自包括在所述阵列的端部的空指针。

如果您的程序不符合这些要求,那么从这一点开始事情将不会如何。如果它对某些程序“起作用”,那只是运气不好。


手册页还表示

按照惯例,第一这些字符串(即argv[0])应包含与正在执行的文件关联的文件名。

该约定相当强大(由POSIX授权),所以不能这样做的程序可以被认为是越野车。如果你要依靠argv[0],你的main()测试它被正确调用是个好主意,所以你可以通过一个很好的错误消息而不是错误来失败,但并不是所有的程序都会这样做。

相关问题