尝试说明一般堆溢出利用的原理
因为堆的操作都是对双向链表的操作
这个dword shoot利用的是当一个结点要从当前双向链表“卸下”的时候,因为要更新前一个结点的后向指针和后一个结点的前向指针,所以当我们可以控制当前结点储存的前一个结点和后一个结点的地址的时候,我们就获得了一次写内存的机会,32位系统的话地址是4字节,就是dword,所以这名字也容易理解。
先看程序源码
#include <windows.h> main() { HLOCAL h1, h2,h3,h4,h5,h6; HANDLE hp; hp = HeapCreate(0,0x1000,0x10000); h1 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8); h2 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8); h3 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8); h4 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8); h5 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8); h6 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8); _asm int 3//used to break the process //free the odd blocks to prevent coalesing HeapFree(hp,0,h1); HeapFree(hp,0,h3); HeapFree(hp,0,h5); //now freelist[2] got 3 entries //will allocate from freelist[2] which means unlink the last entry (h5) h1 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8); return 0; }
就是向系统申请了0x1000大小,最大是0x10000的堆对象,
之后申请了6次8字节的堆(加上块首实际上是16字节),释放了3次,间隔地释放的,最后再次申请8字节,那么就会从空表中卸载h5分配给这一次的分配,作者应该是想让我们手动改一下前向指针和后向指针,体验体验
尝试实验
这次巩固了一下,他分配的话是拿freelist[0]去分配的,一般是堆区的起始地址+0x688
下图为刚分配完6内存申请的情况
接下来就是三次内存释放后的情形了
现在除了freelist[0]和freelist[2],所有的空表索引都为空
加入我们现在申请8个字节的内存,那么最后释放的h5就是我们的目标了
先看一下现在的h5
我们将原来h5的地址的前向指针改为0x44444444,后向指针改为0x00000000
f9运行后就出现访问违例了,但跟作者的结果不一样
我们想想,当那个快从空闲链表中卸下时,应该差不多是这样(我们学双向链表的时候学过的)
// blink:back link // flink:forward link int remove(ListNode* node){ // 将后一个结点的前向指针更新为自己的前向指针 node->blink->flink = node->flink; // 将前一个结点的后向指针更新为自己的后向指针 node->flink->blink = node->blink; }
那么我们更改成上图那样后,我们带入这两句代码
写入flink相当于写入那个地址的前四个字节
写入blink相当于写入那个地址开始数4个字节后的四个字节
那么实验结果应该是将0x44444444写入0x00000000地址的访问违例才对
接下来我们先跟着程序调试一波吧,首先是获取flink带edi
接下来就是获取后向指针
继续单步
他这里是将前向指针读取出来,跟后向指针相比看看相等不
继续
难道是xp sp3加了防护,好像是的,请看下面
他这里是0x00000000的前向指针放到edx,
[edi+4]就是将0x44444444 + 4的值取出来,就是取后向指针
之后就比较前向指针和后向指针的值是否一致,如果没被攻击,值是一样的,都是指向释放的那个块
xp下就不能利用了,试试win2000咯
后来装完win2000,vmtools都装不了,很多东西拖不进去,浏览器又…,先放弃了,还是懒….