25

我读了一本关于缓冲区溢出的书,它建议下一步处理:

使堆栈(和堆)不可执行为现有程序提供了针对多种类型的缓冲区溢出攻击的高度保护。

但我不明白我们该怎么做 - 如果不在堆上或堆栈上,执行将在哪里发生?

4

7 回答 7

30

如果我正确理解了您的问题,则其他答案均未解决。答案是执行发生在代码部分,既不是堆栈也不是堆。在典型的分页内存系统中,来自程序文件(例如,Windows 中的 .exe)的代码被加载到可执行但只读的页面中。额外的可写(和可执行)页面被分配给堆栈和堆的进程。这里的建议是操作系统和硬件应该合作将这些页面标记为可写但不可执行(rgngl 的答案解释了如何在 Windows 中执行此操作)。

即使使用不可执行的堆和堆栈,仍然有可能使用 Alexey Frunze 的回答中提到的面向返回的编程进行利用,但是有一些保护技术甚至会阻碍这些,例如堆栈粉碎保护和地址空间布局随机化 - 请参阅http://en.wikipedia.org/wiki/Return-to-libc_attack#Protection_from_return-to-libc_attacks

于 2012-07-14T11:54:16.313 回答
11

有所谓的“面向回报的编程”(AKA ROP)类型的漏洞利用。

攻击者找到了如何利用被利用的程序的不同部分制作他的恶意代码。

他在返回指令字节之前找到可用的字节序列(指令),这些字节序列可以对寄存器或内存进行有用的操作,例如将值移动到某个位置、添加值、比较值等。这些是漏洞利用获得的微子程序建造的。

然后通过利用代码错误,攻击者强制程序开始执行那些完成所有邪恶工作的微子程序链。

所以,现在好的代码变成了坏代码。堆栈或堆中没有执行任何操作。

还值得注意的是,在指令跨越多个字节且长度可变的 CPU 上,即使是指令一部分的立即指令操作数(IOW,数字常量)也可以成为代码,因此找到可用字节序列的机会高于在“更简单”的 CPU 上。

通常还可以构建恶意代码来更改内存保护,并且漏洞利用将不再受现有应用程序代码的限制。

于 2012-07-14T07:47:29.287 回答
4

非常具体的例子:安排返回地址指向system和堆栈上的下一个槽(或传递寄存器拱上的第一个参数寄存器)作为指向字符串的指针"/bin/sh"

于 2012-07-14T07:59:16.933 回答
1

这种保护是由操作系统提供的,不能在应用层完成。

请参阅维基百科文章,该文章还讲述了如何在 Windows 下启用它:http ://en.wikipedia.org/wiki/Data_Execution_Prevention

于 2012-07-14T07:43:53.653 回答
1

您的代码在文本段中运行,而不是在堆栈或堆中(两者都用于数据存储)。所以组织是:

<highest addresses>
stack
...
heap
data section (initialized data & bss - uninitialized data) 
code section (text)
<lowest addresses> 

代码部分是可执行但不可变的。这篇维基百科文章有更多详细信息:https ://en.wikipedia.org/wiki/Data_segment

于 2015-10-08T10:47:30.050 回答
0

您可以跳转到任何其他可执行段并运行您的邪恶代码...

毕竟,任何存储、内存上的所有数据都是位和位,都可以指令到cpu去执行。

于 2012-07-14T07:36:01.253 回答
0

您可以使用溢出来覆盖函数的返回地址,该地址可以跳转到带有您的代码的某个已知地址。但是随后操作系统编写者通过随机化地址代码来响应...

于 2012-07-14T07:37:11.063 回答