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

rh0*_*h0x 5 c execve shellcode

我必须填写以下参数:

int execve(const char *filename, char *const argv[], char *const envp[]);
Run Code Online (Sandbox Code Playgroud)

如果我执行这个程序:

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

shell 按预期正确生成。

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

#include <unistd.h>

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

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

syn*_*gma 5

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

第二个参数的要点execve()是将参数传递给您正在生成的命令。假设您只想执行而不是 shell ls,那么您可以传递以下参数:

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

另外,引用man execve

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


zwo*_*wol 5

如果您传递一个空指针作为 的第二个或第三个参数execve,则根据 POSIX,您的程序是不正确的;这两个参数都必须为非空。(这并不是 的规范中明确说明的execve全部内容,但它就在那里。)我当前正在处理传递空指针的操作系统上键入此内容,

execve("executable", 0, 0);
Run Code Online (Sandbox Code Playgroud)

相当于传递空数组,例如

execve("executable", (char *[]){0}, (char *[]){0});
Run Code Online (Sandbox Code Playgroud)

但当我得知其他操作系统会引发分段错误或设置为 或 返回 -1 时,我并不errno感到EFAULT惊讶EINVAL

允许为这些参数传递空数组,但如果第二个参数是空数组,新执行的程序将在argc/中接收零个参数,和/或如果第三个参数是空数组,则/中接收零个环境变量。许多程序在这些条件下都会发生故障。例如,很常见看到类似的事情argvenvpenviron

int main(int argc, char **argv)
{
   if (argc != 4) {
     fprintf(stderr, "usage: %s one two three\n", argv[0]);
     return 2;
   }
   // ...
}
Run Code Online (Sandbox Code Playgroud)

其中程序隐式假设argv[0]始终为非空。

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

execve(program, (char *[]){program, 0}, environ);
Run Code Online (Sandbox Code Playgroud)

它提供程序自己的名称作为argv[0]并且没有其他参数,以及您从自己的父级获得的同一组环境变量。