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

标签 c buffer-overflow

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

#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 的返回地址,这会打开一个 shell .但是,如果我将返回地址设置为 instructions,则会出现段错误,instructions 中的所有指令都不会执行。

我用 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) 在您的系统上编译的结果。

关于c - 如何利用缓冲区溢出来执行堆栈上的指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55665109/

相关文章:

c - 写入 char 数组时缓冲区溢出

c++ - 为什么我的代码没有使用类型转换进行编译?

c - 缓冲区溢出不起作用(shellcoders 手册)

sockets - 当内部缓冲区填满时 TCP 会发生什么

c - 带有编译器特定关键字的单元测试 C

ios - PC 寄存器更改提供的值

c - x86_64 上的缓冲区溢出 - 回到 libc 攻击 (linux)

c++ - _IO_wide_data_2 : what's this?

c - 为什么这个循环只执行了 4 次?

c - 函数声明 : K&R vs ANSI