首页 > 解决方案 > 如何利用缓冲区溢出在堆栈上执行指令

问题描述

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

#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_address地址覆盖返回地址,这会打开一个 shell。但是,如果我将返回地址设置为 ,则会出现分段错误,并且不会执行任何指令。fginstructionsinstructions

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

我怎样才能防止发生这种分段错误?

标签: cbuffer-overflow

解决方案


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

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)如果您从某个地方的教程中获得它们,您还应该验证您拥有的指令是否可以在您的系统上编译。


推荐阅读