5.4 堆溢出利用(上)——dword shoot_sliver呀的博客-爱代码爱编程
目录
一、预备知识
堆管理系统的三类操作:堆块分配、堆块释放和堆快合并归根结底都是对链表的修改。堆溢出利用的精髓就是用精心构造的数据溢出下一个堆块的块首,改写块首中的前向指针(flink)和后向指针(blink),然后在分配、释放、合并等操作发生时伺机获得一次向内存任意地址写入任意数据的机会。这种能够向内存任意地址写入任意数据的机会称之为“DWORD SHOOT”。
通过DWORD SHOOT,攻击者可以劫持进程,运行shellcode,主要有如下情形:
点射目标(target) | 子弹(payload) | 改写后的结果 |
栈帧中的函数返回地址 | shellcode的起始地址 | 函数返回时,跳去执行shellcode |
栈帧中S.E.H句柄 | shellcode的起始地址 | 异常发生时,跳去执行shellcode |
重要函数调用地址 | shellcode的起始地址 | 函数调用时,跳去执行shellcode |
举一个例子说明DWORD SHOOT究竟时如何发生的。将一个结点从双向链表中“卸下”的函数很可能是这样的:(参考数据结构)
int remove (ListNode * node)
{
node -> blink -> flink = node -> flink;
node -> flink -> blink = node -> blink;
return 0;
}
!!!另外,请特别注意实际内存中的前向指针和后向指针示意图:(与数据结构中有一点点不一样,图中释放顺序为h1、h3、h4)
二、实验环境
操作系统:Windows 2000 professional
软件版本:原版OD(实时调试状态)、VC++6.0(release)
三、实验代码
#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;
}
四、实验步骤
2、F8释放三次内存,手动更改H5的前向指针为0x44444444,后向指针为0x00000000.
3、执行内存申请的指令,会发现编译器运行错误。
根据:
node->blink->flink=node->flink