我开始修补缓冲区溢出,并编写了以下程序:
#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
用 g
的地址覆盖 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/