gpt4 book ai didi

c - 堆栈粉碎保护和缓冲区溢出的问题

转载 作者:太空狗 更新时间:2023-10-29 16:09:14 25 4
gpt4 key购买 nike

我正在研究缓冲区溢出,我想知道堆栈粉碎保护是如何工作的

我有这个代码:

int main( )
{
char Buf[16];
printf(“Digite o seu nome: ”);
gets(Buf);
printf(“%s”,Buf);
return 0;
}

我用gcc编译

然后我放入一堆字符来填充缓冲区

首先我放了16个字符

$ ./Exemplo1

Digite o seu nome: AAAAAAAAAAAAAAAA

Ola AAAAAAAAAAAAAAAA

没关系,因为缓冲区大小合适

接下来我尝试 24 个字符

$ ./Exemplo1

Digite o seu nome: AAAAAAAAAAAAAAAAAAAAAAAA

Ola AAAAAAAAAAAAAAAAAAAAAAAA

为什么它仍然有效?

这不应该导致程序终止吗!?

它只会在我输入 25 个或更多字符时终止程序

./Exemplo1

Digite o seu nome: AAAAAAAAAAAAAAAAAAAAAAAAA

Ola AAAAAAAAAAAAAAAAAAAAAAAAA

* 检测到堆栈粉碎 *:./Exemplo1 已终止

为什么?缓冲区后面不是返回地址的是什么?我读到的和我认为理解的是它应该有一个金丝雀值,但是如果那个值已经改变并且有 24 个字符写入缓冲区它应该终止程序它不应该仍然给我检测到堆栈粉碎如果返回地址未更改但金丝雀值更改。

谢谢。

最佳答案

根据我对生成的程序集的简要阅读,这是我认为会发生的情况(64 位 Ubuntu 上的 gcc 4.4.5)。

金丝雀是一个双字(8 字节)。堆栈——包括金丝雀——以 16 字节的增量增长。金丝雀位于堆栈框架的末尾。为了同时满足所有三个要求,gcc 可能需要在您的自动变量和 canary 之间插入填充。

因为在你的代码中 Buf 是 16 个字节长,gccBuf 和金丝雀之间放置了 8 个字节的填充(为了使堆栈帧的大小为 16 字节的倍数)。这解释了为什么您最多可以输入 24 个字符而不会触发堆栈粉碎检测。

如果我将 Buf 更改为 8 个字节长,则不再需要任何填充,并且输入 9 个字符会触发保护:

#include <stdio.h>

int main( )
{
char Buf[8];
printf("Digite o seu nome: ");
gets(Buf);
printf("%s",Buf);
return 0;
}

aix@aix:~$ ./a.out
Digite o seu nome: AAAAAAAA
AAAAAAAA

aix@aix:~$ ./a.out
Digite o seu nome: AAAAAAAAA
*** stack smashing detected ***: ./a.out terminated

显然,这取决于编译器、硬件平台、编译器标志等。

不用说,人们不应该期望这种机制是防弹的。

如果您想进一步试验,请尝试使用不同的缓冲区大小和使用/不使用 -fno-stack-protector 来编译您的代码。如果您使用 -S 生成汇编代码,您将能够看到生成的代码如何在您调整设置时发生变化。

关于c - 堆栈粉碎保护和缓冲区溢出的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6752694/

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