Windows下的HEAP溢出及其利用

作者在 2007-01-14 00:39:00 发布以下内容

一、概述 
前一段时间ASP的溢出闹的沸沸扬扬,这个漏洞并不是普通的堆栈溢出,而是发生在HEAP中的溢出,这使大家重新认识到了Windows下的HEAP溢出的可利用性。其实WIN下的HEAP溢出比Linux和SOLARIS下面的还要简单得多,大家肯定搞明白了,我来做一个总结,以免自己将来忘了。由于缺乏这方面的资料及源代码,所有的分析结果都来自于反汇编和调试的分析,所以错误之处在所难免,敬请各位指正。
程序的测试环境为:中文版Windows 2000 + SP2    VC++ 6.0 
二、Windows的HEAP管理机制简述 
同LINUX一样,Windows的HEAP区是程序动态分配一块内存区域。程序员一般调用C函数malloc/free或者C++的new/delete或者WIN32 API函数HeapAlloc/HeapFree来动态分配内存,这些函数最终都将调用ntdll.dll中的RtlAllocateHeap/RtlFreeHeap来进行实际的内存分配工作,所以我们只需要分析RtlAllocateHeap/RtlFreeHeap就行了。 
对于一个进程来说可以有多个HEAP区,每一个HEAP的首地址以句柄来表示:hHeap,这也就是RtlAllocateHeap的第一个参数。每个HEAP区的整体结构如下: 
+-------------------------------------------------------------------+ 
| HEAP总体管理结构区 | 双指针区 | 用户分配内存区 | 
+-------------------------------------------------------------------+ 
|_hHeap |_hHeap+0x178 
heap总体管理结构区存放着一些用于HEAP总体管理的结构,这不是我们所关心的。双指针区存放着一些成对出现的指针,用于定位分配内存以及释放内存的位置,这可能是某种树结构,我还没完全搞清楚。用户分配内存区是用户动态分配内存时实际用到区域,也这是HEAP的主体。 
当我们调用RtlAllocateHeap(HANDLE hHeap,DWORD dwFlags,SIZE_T dwBytes)来分配内存时将进行以下操作: 
对参数检查,如果dwBytes过大或小于0都按照出错处理,根据dwFlags来设置一些管理结构; 
检查是否为DEBUG程序,对于DEBUG的程序与实际运行的程序每个内存块之间的结构是不同的,所以我们下面说到的都是以RELEASE版编译的实际运行的程序(不是在MSDEV中调试的程序); 
根据要分配的内存的大小(dwBytes)决定不同的内存分配算法,我们只分析小于1024 bytes的情况; 
从双指针区找到用户内存区的末尾位置,如果有足够的空间分配所需的内存,就在末尾+dwBytes+8的位置放置一对指针来指向双指针区的指向用户内存区末尾位置的地方; 
在后面同时设置双指针区的指向用户内存区末尾位置的指针指向进行完分配之后的用户内存区末尾位置。这么说可能有点绕,不过这跟HEAP溢出没有太大的关系,所以我们就不细究了。 
两块连续分配的内存块之间并不是紧挨着的,而是有8字节的管理结构,最末尾的一块内存后面还另外多了8字节的指针指向双指针区,就是上面提到过的。 
假设有以下程序: 
buf1 = HeapAlloc(hHeap, 0, 16); 
buf2 = HeapAlloc(hHeap, 0, 16); 
连续分配了两块16字节内存,实际在内存中(用户分配区)的情况是这样的: 
第一次分配后: 
+-----------------------------------------------+ 
| buf1 | 8 byte |4 byte|4 byte| 
+-----------------------------------------------+ 
| 用户内存 | 管理结构 | 两个指针 | 
第二次分配后: 
+-----------------------------------------------------------------------------+ 
| buf1 | 8 byte | buf2 | 8 byte |4 byte|4 byte| 
+-----------------------------------------------------------------------------+ 
| 用户内存 | 管理结构 | 用户内存 | 管理结构 | 两个指针 | 
在第二次分配内存的时候会利用第一块内存管理结构后面那两个指针进行一些操作,其中会有一次写内存的操作: 
77FCB397 mov [ecx], eax 
77FCB399 mov [eax+4], ecx 
这时的eax和ecx分别指向: 
+-----------------------------------------------+ 
| buf1 | 8 byte |4 byte|4 byte| 
+---------------------------------^------^------+ 
| 用户内存 | 管理结构 |_eax |_ecx | 
写到这里大家一定就明白HEAP溢出如何利用了吧?假设我们分配完buf1之后向其中拷贝内容,拷贝的内容大小超过buf1的大小,即16字节,就会发生

转移技术贴 | 阅读 1386 次
文章评论,共0条
游客请输入验证码