现在的位置: 首页 > 综合 > 正文

关于Heap Overflow(堆溢出)

2018年06月10日 ⁄ 综合 ⁄ 共 2383字 ⁄ 字号 评论关闭

Heap overflow是一种系统提升权限的方法。在Linux系统中,入侵者可以针对某些文件属性设置成+rws(也就是传说中的
粘滞位)的漏洞程序进行攻击从而得到root权限。我们在模拟攻击时可以在root权限下使用以下命令来设置粘滞位属性:

                             chown root:root xxx

                             chmod +s xxx

其中xxx代表我们要攻击的文件。

 

Heap Overflow的原理是修改程序中的GOT(Global Offest Table)表来使得程序调用正规函数时(如printf() free()等)跳入我们设计的shellcode。在这一点上它的手段类似于Format String Attack都是利用修改内存来达到攻击的目的。Heap Overflow的优点是一次运行基本搞定,不像stack overflow还可能需要猜多次栈的偏移,

 

如何能够任意修改内存呢?Heap Overflow攻击利用了内存释放函数free的一个特性。利用了我们当调用free释放一个内存空间时,free函数内存将会查看在堆中下一个内存是否也已经释放。如果是的话,那么程序将执行一个Unlink宏将两个内存空间结合起来,这样的话能够减少堆中的内存碎片从而提高程序的效率。

 

Unlink宏的执行方式类似于双向链表中删除其中某一个元素的操作。也就是将前一个元素的后指针指向当前的后指针,后一个元素的前指针指向当前的前指针。我们要注意到,这其实是两个内存赋值操作,本质上就是两个类似于*ptr = data的操作。而如果我们设计的字符串够长到足以能够修改到以上ptr和data的值的话,我们其实就能够修改程序内任意内存地址的值,包括以上提到的GOT表,从而改变让程序跳入我们设计的shellcode。

 

要完成Heap Overflow,有几点需要注意:

1. 计算堆的大小

堆得大小和分配的大小不一样,我们要多分配4byte来保存这个堆的大小,而堆的大小又必须是8的倍数,所以堆得实际大小的计算方法是:

actual_size = floor((memory_size + 4)/8) * 8, 其中floor()是上取整操作。

 

2. 修改使得第二个内存"看起来"已经被释放过

这可以通过首先设置第二个内存大小为-4,然后再将内存上一个byte的值设置为一个偶数来完成

 

3. 修改GOT表

这实际上相当于一个一个内存赋值问题

*(GOT_Table_Addr + 12) = shellcode_address

GOT表中某函数的位置可以通过objdump -R来查看

 

4. 准备邪恶的shellcode

由于我们准备将shellcode放在堆中,而且用空指令NOP来铺路,shellcode的地址其实就可以是堆起始地址后偏移任意位(貌似大于8bytes就可以)。这里我们可以用ltrace命令来查看某内存在堆中的地址。

 

好了,这样我们就成功的准备了一个heap overflow程序。具体代码如下:

exploit.c

testmalloc.c

 

具体细节可以参考Smashing The Heap For Fun And Profit (by Michel "MaXX" Kaempf)

 

抱歉!评论已关闭.