C execve()参数[生成shell示例]

时间:2015-05-10 09:27:57

标签: c shellcode execve

我必须填写以下参数:

int execve(const char *filename, char *const argv[], char *const envp[]);

如果我执行此程序:

#include <unistd.h>
int main() {
        char *args[2];
        args[0] = "/bin/sh";
        args[1] = NULL;
        execve(args[0], args, NULL);
}

按预期正确生成shell。

我的问题是,如果我将NULL作为第二个参数传递,那么shell也会正确生成:

#include <unistd.h>

int main() {
        char *args[2];
        args[0] = "/bin/sh";
        args[1] = NULL;
        execve(args[0], NULL, NULL);
}

那么使用args向量(使用“/ bin / sh”+ NULL)作为第二个参数而不是NULL的目的是什么?

2 个答案:

答案 0 :(得分:2)

在这一行中:execve(args[0], NULL, NULL);您只是使用args数组的第一个元素。你也可以使用像char* command="/bin/sh"这样的东西。您必须传递某些内容,因为这是execve()的定义方式。在您的情况下,您传递NULL,因为您不需要传递任何内容。

execve()的第二个参数的要点是将参数传递给您正在生成的命令。假设您只需要执行ls而不是shell,则可以传递f.e.这些论点:

#include <unistd.h>
int main() {
        char *args[2];
        args[0] = "/bin/ls";
        args[1] = "-lh";
        execve(args[0], args, NULL);
}

另外,引用man execve

  

argv是传递给新程序的参数字符串数组。 按   约定,这些字符串中的第一个应该包含文件名   与正在执行的文件相关联。 envp是一个数组   通常为key = value形式的字符串,它们被传递为   新计划的环境。

答案 1 :(得分:2)

如果将空指针作为execve的第二个或第三个参数传递,则根据POSIX,您的程序是不正确的;这两个参数都必须是非null。 (the specification of execve中没有明确说明这一点,但它就在那里。)我目前正在一个处理空指针的操作系统上输入它,

execve("executable", 0, 0);

等同于传递空数组,例如

execve("executable", (char *[]){0}, (char *[]){0});

但要了解其他操作系统会触发分段错误或在errno设置为EFAULTEINVAL时返回-1并不会让我感到惊讶。

允许为这些参数传递空数组,但如果第二个参数是空数组,则argc / argv中新执行的程序将接收零参数,和/或{ {1}} / envp如果第三个参数是一个空数组。许多程序在这些条件下会出现故障。例如,看到像

这样的东西是很常见的
environ

程序隐含地假设int main(int argc, char **argv) { if (argc != 4) { fprintf(stderr, "usage: %s one two three\n", argv[0]); return 2; } // ... } 始终为非空。

因此,您应该始终为这两个参数提供非空数组。通常的惯例是,如果你没有别的事可做,你可以使用

argv[0]

提供程序自己的名称execve(program, (char *[]){program, 0}, environ); ,没有其他参数,以及您从父母那里得到的同一组环境变量。