如何利用缓冲区溢出来执行堆栈上的指令

How to exploit a buffer overflow to execute instructions on the stack

我开始修补缓冲区溢出,并编写了以下程序:

#include <unistd.h>

void g() {
  execve("/bin/sh", NULL, NULL);
}

void f() {
  long *return_address;
  char instructions[] = "\xb8\x01\x00\x00\x00\xcd\x80"; // exit(1)

  return_address = (long*) (&return_address + 2);
  *return_address = (long)&g; // or (long)instructions
}

int main() {
  f();
}

它做了我期望它做的事情:return_addressg 的地址覆盖 f 的 return 地址,这会打开一个 shell.但是,如果我将 return 地址设置为 instructions,则会出现段错误,并且会执行 instructions 中指令的 none。

我用 GCC 编译,使用 -fno-stack-protector

如何防止发生此分段错误?

至少有一个问题与缓冲区溢出无关。

execve("/bin/sh", NULL, NULL);

第一个 NULL 成为您正在启动的进程的 argv。 argv 必须是 终止 且带有 NULL 的字符串数组。因此,当 /bin/sh 启动、尝试读取 argv[0] 并取消引用 NULL 时,可能会发生段错误。

void g(void) {
    char *argv[] = { "/bin/sh", NULL };
    execve(argv[0], argv, NULL);
}

您还可以将 -z execstack 添加到 gcc 命令行,这将告诉链接器允许可执行堆栈。如果您是从某处的教程中获得的,您还应该验证您所拥有的说明是否是 exit(1) 在您的系统上编译的内容。