MS07-004通用溢出方法补完
本文以ms07-004为例子,探讨了此类漏洞的通用方法,恢复ie方法,以及heap spray的技术。
抛砖引玉!
by axis
Date: 2007-02-13
Email: axis_at_ph4nt0m.org
MS07-004出来也有段时间了,我之前写过一个分析的paper,并且针对此发布了一个POC。
事实上,因为我们可以控制指向内存中的地址为0x00xxxxxx,除了第一个字节是00无法控制外,后面三个字节都是可以控制的,这样其实我们就有了一个很大范围的选择。
很多人为了通用而头疼,这里我针对这个exp给出一个通用地址。
因为这个漏洞比较特殊,所以可能这个地址只能适用于这一个地址。
0x00420001
00420000 00 00 00 00 00 00 00 00 00 00 01 00 48 1B DD BB ………..H莼
00420010 00 00 00 00 0C 00 01 00 C8 9A F2 E1 08 EA A4 E1 …….葰蜥辘
注意0x00420011的地方是0c
而在漏洞中利用的指针是 call [ecx+10h]
所以覆盖的地址需要减去10h
而这个0x00420011的地址,是和ie有关的,在目前所有的windows平台,不论语言和版本,以及所有的ie版本中,都是固定不变的为0c
所以我们利用了这个地址,就变成了call 0x00420011
就跑去0x0c000000去执行代码去了
而这个时候,堆里已经被我们heap spray过了,所以代码就会一直执行到我们的shellcode去。
这里选用0c的好处是因为双字节指令,非常方便用来做heap spray。
其实这类ie漏洞,主要的问题有几个
1.通用性 (上面已经解决了)
2.稳定性 (触发漏洞概率) ms07-004这个的稳定性我觉得还是不错的
3.不挂ie
关于这点可能要详细说一下, 之前以为只要单纯的恢复栈平衡就可以了,事实上恢复了栈平衡是没用的,因为这是个堆溢出,覆盖了堆内的指针,而堆已经被我们破坏干净了,所以后面总会在某个dll里出错。而栈本来就是平衡的,也不需要恢复。
所以这类漏洞,要达到不挂ie的效果(我说的是不挂ie,不是让ie僵死),就需要恢复堆。与牛人讨论后,得到两种方法:一个是hook RtlCreateHeap, hook RtlAllocHeap 重新分配个堆;另一个方法是:hook RtlFreeHeap不让挂掉就可以了。或者大家还有什么别的好方法,欢迎补充。
4.健壮性
由于是堆溢出,所以对于访问了多网页,内存中0x0c0c0c0c处已经被别的东西占用了,所以运行不到shellcode去,也是这个漏洞为什么不好的原因。
这个问题属于这类漏洞的先天缺陷。swan曾经提出用内存空洞的办法把堆地址推到内存高位去,可是我试过发现行不通。luoluo提出来用java分配内存,做heap spray。这个是个可行的方法,并且也已经poc实现了,分配的内存在0x21xxxxxx附近,而0x24这个指令又非常好,可以做heap spray。
ms07-004除了最后一点多网页的我问题没解决,其他都已经解决了,包括bypass firewall。poc代码不方便给出来,本文就到此为止。