[CNNVD]Microsoft Windows Media Player ‘winmm.dll’ MIDI檔案解析遠端程式碼執行漏洞(CNNVD-201201-110)
Microsoft Windows是微軟釋出的非常流行的作業系統。Windows Media Player是系統的多媒體播放元件。
WMP在處理畸形結構的MIDI資料時存在記憶體破壞漏洞。遠端攻擊者可利用該漏洞透過誘使使用者訪問惡意網頁控制使用者系統。
注意這個漏洞是ie程式在呼叫多媒體的dll時觸發的,也就是要去掛載ie程式。載入poc後數秒內ie程式crash,異常資訊如下:
(aa0.aa4): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=002261c4 ebx=00000000 ecx=0c0c0c0c edx=0000003d esi=00225dc8 edi=0039d910
eip=7e390581 esp=0012e198 ebp=0012e1a8 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!CAttrValue::GetIntoVariant+0x4d:
7e390581 ff5104 call dword ptr [ecx+4] ds:0023:0c0c0c10=????????
由於是ie的漏洞我們對這種call [ecx+4]的形式比較敏感(因為ie存在大量的物件虛表訪問),來具體看一下,ub mshtml!CAttrValue::GetIntoVariant+0x4d,如下
0:000> ub mshtml!CAttrValue::GetIntoVariant+0x4d
mshtml!CAttrValue::GetIntoVariant+0x3a:
7e39056e e8f93ef0ff call mshtml!VariantCopy (7e29446c)
7e390573 8bd8 mov ebx,eax
7e390575 eb35 jmp mshtml!CAttrValue::GetIntoVariant+0x78 (7e3905ac)
7e390577 8b460c mov eax,dword ptr [esi+0Ch]
7e39057a 3bc3 cmp eax,ebx
7e39057c 7406 je mshtml!CAttrValue::GetIntoVariant+0x50 (7e390584)
7e39057e 8b08 mov ecx,dword ptr [eax]
7e390580 50 push eax
我們一看就知道這個就是虛表訪問,這個套路在ie裡真是見過太多了,eax是物件指標,ecx是虛表指標,那麼call [ecx+4]就是呼叫虛擬函式了。我們繼續看下這個物件中的內容
0:000> dc eax
002261c4 0c0c0c0c 0c0c0c0c 0c0c0c0c 00000000 ................
002261d4 00000000 00000000 00000000 00050081 ................
002261e4 00080187 00008103 80000000 00000000 ................
002261f4 06f72ed0 00000802 002dc72b 00000000 ........+.-.....
00226204 002265f4 00000902 002dc72c 00000000 .e".....,.-.....
00226214 06f59bb0 00000902 002dc72d 00000000 ........-.-.....
00226224 09318a68 00000b02 002dc72e 00000000 h.1.......-.....
00226234 0000ffff 00000302 002dc72f 00000000 ......../.-.....
喜聞樂見的堆噴,看來作者的思路就是偽造一個物件的虛表為0c0c0c0c,然後堆噴到0c0c0c0c偽造虛擬函式佈置shellcode,這也是很常規的做法,那為啥會crash呢?我們來看一下,
0:000> dd 0c0c0c0c
0c0c0c0c ???????? ???????? ???????? ????????
0c0c0c1c ???????? ???????? ???????? ????????
0c0c0c2c ???????? ???????? ???????? ????????
0c0c0c3c ???????? ???????? ???????? ????????
0c0c0c4c ???????? ???????? ???????? ????????
0c0c0c5c ???????? ???????? ???????? ????????
0c0c0c6c ???????? ???????? ???????? ????????
0c0c0c7c ???????? ???????? ???????? ????????
0:000> !address 0c0c0c0c
0ac0c000 : 0ac0c000 - 053f4000
Type 00000000
Protect 00000001 PAGE_NOACCESS
State 00010000 MEM_FREE
Usage RegionUsageFree
顯示這塊記憶體未分配,看來並沒能噴到0c0c0c0c,估計作者是翻車了,或者是我的環境有問題。那麼我們再去找找作者用哪裡的漏洞搞的大新聞。
首先要開hpa了,因為我們已知是堆漏洞了。斷在如下位置
(eec.b40): 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=0000007d ecx=007db29f edx=00000000 esi=126ef019 edi=126b6f60
eip=76b2d224 esp=12dffe80 ebp=12dffea0 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:
76b2d224 8a06 mov al,byte ptr [esi] ds:0023:126ef019=??
我們不知道esi是什麼地址,但是我們可以猜一下,!heap -p -a esi ,結果如下果真是頁堆的導致的異常。我們計算一下:126eec00+0x400=126EF000 ,而126ef019>126ef000。又我們可以知道堆只有分配的記錄並沒有釋放的記錄說明肯定不是UAF漏洞了,那麼肯定是堆溢位或是基於堆的陣列訪問越界了。
v0:028> !heap -p -a esi
address 126ef019 found in
_DPH_HEAP_ROOT @ 141000
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)
11fc4058: 126eec00 400 - 126ee000 2000
7c938f01 ntdll!RtlAllocateHeap+0x00000e64
76b2b2b3 WINMM!winmmAlloc+0x00000016
76b2cdee WINMM!mseOpen+0x00000044
76b2d97e WINMM!mseMessage+0x00000029
76b2a17f WINMM!midiStreamOpen+0x00000207
77ba1f7c midimap!modOpen+0x000000f8
77ba29f3 midimap!modMessage+0x0000005e
76b2a15e WINMM!midiStreamOpen+0x000001e6
7d03567d quartz!CMidiOutDevice::DoOpen+0x00000026
7d035727 quartz!CMidiOutDevice::amsndOutOpen+0x00000059
7cfabc7a quartz!CWaveOutFilter::amsndOutOpen+0x0000002e
7cfabc05 quartz!CWaveOutFilter::DoOpenWaveDevice+0x0000007a
7cfabe12 quartz!CWaveOutFilter::OpenWaveDevice+0x00000019
7cfabcda quartz!CWaveOutFilter::Pause+0x00000049
7cf8cf61 quartz!CFilterGraph::Pause+0x00000107
重新執行程式,對WINMM!midiOutPlayNextPolyEvent+0x1ec下斷,看下回溯
0:028> kp
ChildEBP RetAddr
1243fea0 76b2d2e5 WINMM!midiOutPlayNextPolyEvent+0x1ec
1243feb4 76b154e3 WINMM!midiOutTimerTick+0x4f
1243fedc 76b2adfe WINMM!DriverCallback+0x5c
1243ff18 76b2af02 WINMM!TimerCompletion+0xf4
1243ffb4 7c80b729 WINMM!timeThread+0x53
1243ffec 00000000 kernel32!BaseThreadStart+0x37
看下在哪個模組中,如下,抓出來用IDA開啟
0:028> lmm winmm v
start end module name
76b10000 76b3a000 WINMM (pdb symbols) C:\symbols\winmm.pdb\90FC96D5AD8440A2B14855895BD92ED62\winmm.pdb
Loaded symbol image file: C:\WINDOWS\system32\WINMM.dll
Image path: C:\WINDOWS\system32\WINMM.dll
Image name: WINMM.dll
Timestamp: Mon Apr 14 10:13:53 2008 (4802BDE1)
CheckSum: 0002C65D
ImageSize: 0002A000
File version: 5.1.2600.5512
Product version: 5.1.2600.5512
File flags: 0 (Mask 3F)
File OS: 40004 NT Win32
File type: 2.0 Dll
File date: 00000000.00000000
Translations: 0804.04b0
CompanyName: Microsoft Corporation
ProductName: Microsoft(R) Windows(R) Operating System
InternalName: winmm.dll
OriginalFilename: WINMM.DLL
ProductVersion: 5.1.2600.5512
FileVersion: 5.1.2600.5512 (xpsp.080413-0845)
FileDescription: MCI API DLL
LegalCopyright: (C) Microsoft Corporation. All rights reserved.