gpt4 book ai didi

在雪豹中创建缓冲区溢出

转载 作者:太空狗 更新时间:2023-10-29 16:56:06 27 4
gpt4 key购买 nike

作为大学计算机安全类(class)的一部分,我即将学习缓冲区溢出以及如何将其用作漏洞利用。我正在尝试使用以下代码进行一些简单的缓冲区溢出:

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
char buffer_one[4], buffer_two[16];

strcpy(buffer_one, "one");
strcpy(buffer_two, "two");

strcpy(buffer_one, argv[1]);

printf("buffer_two is at %p and contains \'%s\'\n", buffer_two, buffer_two);
printf("buffer_one is at %p and contains \'%s\'\n", buffer_one, buffer_one);
}

如果我运行,我可以用空终止符覆盖buffer_one的内容
$./overflow 1234567890123456
buffer_two is at 0x7fff5fbff8d0 and contains '1234567890123456'
buffer_one is at 0x7fff5fbff8e0 and contains ''

但是,如果我发送的参数超过16个字符,则程序将发送Abort陷阱。我以为这是Snow Leopard上的某种缓冲区保护(也许是ASLR?)。如果将buffer_two的大小设置为<16,则地址仍然相隔16位

我正在运行 gcc -o overflow overflow.c -fno-stack-protector删除堆栈保护

除了安装运行linux dist的VM以外,是否有解决此问题的方法?

最佳答案

发生这种情况的关键是buffer_one位于内存中的buffer_two之后。这意味着当您溢出buffer_one时,您不会溢出到buffer_two中。取而代之的是,您溢出到用于保存其他内容的堆栈内存中,例如保存的ebp指针,最重要的是返回地址。
而这正是您尝试缓冲区溢出攻击时想要发生的事情!当程序执行strcpy(buffer_one, argv[1]);时,argv[1]的前四个字节进入分配给buffer_one的内存中。但是随后的12个内存开始溢出,用于其他用途,最终覆盖了返回地址。如果没有看到机器代码,我无法确定哪个字节恰好溢出了返回地址。但是我猜测SIGABRT时EIP的值为0x31323334或类似的值(“1234”的十六进制表示)。关键是要意识到,通过能够覆盖返回地址,您可以控制EIP。当您控制EIP时,可以控制系统。 (有些过分夸张,但在大多数情况下相差不远)当您控制EIP时,您可以控制处理器下一步执行的指令(暂时不考虑OS/内核实际上位于两者之间的事实)。
现在,如果您确切找到哪个八个字节覆盖了返回地址,则可以将这些字节替换为缓冲区的地址(0x00007fff5fbff8e0),而不是返回到原始调用方(在这种情况下为libc),程序将开始执行您提供的指令(又称shellcode)。请注意,您必须在最重要的位置填写隐含的0,并将地址提供为实际的不可打印ASCII字符(0x00 0x00 0x7f 0xff 0x5f等),而不是实际的数字/字符7ff5等。如果使用的是x86-64架构,您还必须考虑低字节序并向后提供它-0xe0 0xf8 0xbf等。使用反引号和使用简短的Python或Perl脚本的命令替换最容易实现提供这些不可打印的字符:

./overflow `python -c 'print "AAAAAAAAAAAAAAAA\xe0\xf8\xbf\x5f\xff\x7f"'`
(A填充以使缓冲区溢出。)不幸的是,您将无法提供该地址所需的其他2个 \x00。这些NULL之一将由 strcpy放置在此处,但您必须对最后一个NULL感到幸运,并希望您覆盖的地址已经以 0x00开头(实际上很有可能)。现在,当您使用正确数量的A执行此操作时,您可能仍会遇到段错误甚至可能是非法指令,因为您现在将跳转到大写A并将其作为实际的机器指令执行( 0x41 => inc ecx) 。
最后,最后一部分是放入实际的shellcode。给定有限的缓冲区大小,很难在12个字节左右的时间内提供任何有用的东西。由于您是在这种情况下编写代码的,因此最简单的方法可能是增大缓冲区的大小。如果不是这种选择,那么您可以A)也可以使用 buffer_two多16个字节,因为它在 buffer_one之前出现,或者B)在环境变量中提供shellcode并跳转到该位置。
如果您希望自己编写实际的Shellcode,则必须知道如何执行系统调用,调用约定是什么以及如何使用它们,以及如何避免Shellcode中的NULL字节。另一种选择是使用有效负载生成器,例如Metasploit附带的有效负载生成器,它将使它变得更加简单(尽管您不会学到太多)。
从技术上讲,这是您唯一需要的部分,尤其是因为您对地址将是一个好主意。但是,很多时候(尤其是在不知道shellcode地址的情况下),会在shellcode的前面放置一个所谓的NOP底座,这样您就不必完全正确地获取地址。 NOP底座(“无操作”的缩写)只是几百至数千个NOP指令(0x90),您可以跳转到其中,直到执行继续到shellcode为止才起作用。
如果您跟踪GDB中的所有内容,并且执行正确地跳到了shellcode,但是仍然出现访问冲突,则可能是因为NX位已在堆栈页面上设置,这意味着处理器将拒绝执行指令中的堆栈数据。我不确定OSX是否包含 execstack,但如果包含,则可以将其用于测试目的以禁用NX位( execstack -s overflow)。
抱歉,我不知道您是否想研究缓冲区溢出。您还可以查看其他指南,例如Aleph One的原型(prototype)指南 "Smashing the Stack for Fun and Profit"The Shellcoder's Handbook也是一本不错的书,我相信其他人也可以添加建议。
TL; DR:简而言之,您正在溢出缓冲区,并覆盖保存的指针并使用垃圾返回地址。

关于在雪豹中创建缓冲区溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5654893/

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