这个漏洞好多地方都说是UAF,但我调了一下感觉应该是一个整数溢出类型漏洞。下面是我的分析结果,贴出来和大家一起研究,欢迎拍砖。
POC来自于:
http://www.binvul.com/viewthread.php?tid=311&extra=page%3D1
感谢4B5F5F4B大牛,已经附在了附件中,解压密码为lvbluesky。
IE 漏洞 CVE-2013-2551 分析
By lvbluesky
这个漏洞好多地方都说是 UAF,但我调了一下感觉应该是一个整数溢出类型漏洞。下面是我的分析结果,贴出来和大家一起研究。POC 已经附在了附件中。
1. 调试环境
Windows xp sp2+IE8+Windbg
2. 漏洞综述
vgx.dll 在重设 COALineDashStyleArray length 大小时如果输入负数,会产生整数溢出,
该值被改写为一个很大的数,导致向 COALineDashStyleArray 的越界写入。可控制越界写
入的大小和内容,覆盖 COALineDashStyleArray 后面的函数指针。
3. 漏洞细节
程序在此处为 ID 为“shape”的 stroke 元素建立 dashstyle array:
021ad39c 0332c3c0 021ad3c8 00000020 00000101 vgx!GelHost::FAllocMemCore+0x8
021ad3c0 0332c545 00000004 00000008 ffffffff vgx!MsoFResizePx+0x69
021ad3dc 032ed0bb 00987de4 00000005 021ad494 vgx!MsoFGrowPx+0x18
021ad3f8 0335a068 00987de0 021ad42c 00000001 vgx!ORG::FAppendRange+0x39
021ad414 0335a0e2 021ad42c 00000004 0023dd34 vgx!VGPIE5array::FAddElement+0x42
021ad47c 0332cdfd 0023dd34 0000000f 009860a0 vgx!VGPIE5DwordArray::Text+0x60
021ad4a0 0332d379 0023dd34 00000000 0023dd34 vgx!GetArrayVal+0x86
021ad4b4 03332c51 00986080 0023dd34 000001cf vgx!ParseDashStyle+0x21
021ad4e8 033327be 00000001 ffffff88 021ad620 vgx!CVMLStroke::InternalLoad+0x100
021ad504 032e33b1 021ad618 021ad5a0 00000003 vgx!CVMLShapeIOProxy::Load+0x22
021ada5c 032e4331 02d44664 00000000 021ada98 vgx!CSimpleTag::Load+0x5e9
021ada6c 63800468 00986470 02d44664 00000000 vgx!CPTPropBag2<CSimpleTag>::Load+0x16
021ada98 635c1326 00206ac8 00000000 027e1790 mshtml!CPeerHolder::InitAttributes+0xa9
021adabc 635c120b 00000000 027e1790 00000000 mshtml!CPeerHolder::AttachPeer+0xb7
021adae4 637800d6 027e1790 00000000 00206ac8 mshtml!CPeerHolder::Create+0x59
021adafc 6377d8ca 00000000 027e1738 021afb80 mshtml!CPeerFactoryUrl::AttachPeer+0x29
021adb0c 6377dad2 00203c34 00000003 0020e7a8 mshtml!CDoc::AttachPeerUrl+0x31
021afb80 6376f580 0020e7a8 021afba8 00000000 mshtml!CDoc::AttachPeersCss+0x1d4
021afbcc 6376f4df 00000004 7c8092ac 0073fd3c mshtml!CElement::ProcessPeerTask+0x181
021afbe8 635c075d 0020bab0 00000000 021a0013 mshtml!CMarkup::ProcessPeerTasks+0xe9
vgx!GelHost::FAllocMemCore:
032e56d8 8bff mov edi,edi
032e56da 55 push ebp
032e56db 8bec mov ebp,esp
032e56dd ff750c push dword ptr [ebp+0Ch]
032e56e0 ff1534102c03 call dword ptr [vgx!_imp__malloc (032c1034)]
vgx!GelHost::FAllocMemCore+0x8:
032e56e0 call dword ptr [vgx!_imp__malloc (032c1034)] ds:0023:032c1034={msvcrt!malloc
(77bfc407)}
0:001> dd esp
021ad398 00000020 021ad3c0 0332c3c0 021ad3c8
0:001> p
eax=00987d90 ebx=00000005 ecx=00000000 edx=77c31aa0 esi=00987de4 edi=0000ffff
eip=032e56e6 esp=021ad398 ebp=021ad39c iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
vgx!GelHost::FAllocMemCore+0xe:
032e56e6 59 pop ecx
由于 poc 中“<v:stroke dashstyle="2 2 2 0 2 2 2 0" id="shape"/>”,dashstyle array 的元素个数为 8,每个元素大小为 4Byte,所以此处申请的空间大小为 20h。申请到的空间从 00987d90开始。
然后将此位置记录到 vgx!ORG 对象中:
eax=00987d90 ebx=00000005 ecx=00987dc0 edx=77c31aa0 esi=00987de4 edi=0000ffff
eip=0332c485 esp=021ad3b0 ebp=021ad3c0 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
vgx!MsoFResizePx+0x12e:
0332c485 89460c mov dword ptr [esi+0Ch],eax ds:0023:00987df0=00987dc0
0:001> u poi(esi-4)
vgx!ORG::`vftable':
分析得到 vgx!ORG 的结构:
vgx!ORG
+4:dashstyle array 元素个数,
+10h:dashstyle array 指针
然后递增 vgx!ORG+4 处的值,最终修改为 8。
然后程序创建 0x400 个 vgx!CVMLShape 对象,在初始化每个对象时还会创建一个
vgx!CSafePtr 对象,最后通过该对象找到 vgx!CVMLShape 对象。
ChildEBP RetAddr Args to Child
021a9e1c 0332a5be 00988108 021a9e5c 0332a609 vgx!CSafePtr::CSafePtr+0x14
021a9e28 0332a609 021a9e5c 021a9e44 03325f1e vgx!CObjectSafe::GetSafePtr+0x2e
021a9e34 03325f1e 00988108 00988360 021a9e54 vgx!CSafeRef::CSafeRef+0x17
021a9e44 03326852 009880d0 00988360 021a9e74
vgx!CTreeRefTo<CVMLShape>::CTreeRefTo<CVMLShape>+0x1e
021a9e54 033272b5 00000000 00000000 00000000 vgx!CVMLShape::SetSibling+0x13
021a9e74 033284be 009880d0 00000000 00986550 vgx!CVMLPage::AddToplevel+0x36
021a9e9c 03329c45 00986550 00000000 0000003d vgx!CVMLShape::Init+0x319
021a9ebc 033321ae 0000003d 00000000 00988170 vgx!CVMLPage::FAddShape+0xd2
021a9f00 032e2f63 021a9f44 0000003d 00988170 vgx!CVMLPage::CreateContainer+0x203
021aa454 032e5481 02d0a0ec 00000000 00000000 vgx!CSimpleTag::Load+0x19c
021aa46c 032e5540 02d0a0ec 00000000 021aa4a8 vgx!CParserTag::Load+0x14
021aa47c 63800468 00988bb0 02d0a0ec 00000000 vgx!CPTPropBag2<CParserTag>::Load+0x16
021aa4a8 635c1326 00207128 00000000 027e1790 mshtml!CPeerHolder::InitAttributes+0xa9
021aa4cc 635c120b 00000000 027e1790 00000000 mshtml!CPeerHolder::AttachPeer+0xb7
021aa4f4 637800d6 027e1790 00000000 00207128 mshtml!CPeerHolder::Create+0x59
021aa50c 6377d8ca 00000000 027e1738 021ac590 mshtml!CPeerFactoryUrl::AttachPeer+0x29
021aa51c 6377dad2 0023d544 00000003 0020e6e8 mshtml!CDoc::AttachPeerUrl+0x31
021ac590 6376f580 0020e6e8 021ac5b8 00000000 mshtml!CDoc::AttachPeersCss+0x1d4
021ac5dc 6376f4df 00000004 02d79d10 0020e568 mshtml!CElement::ProcessPeerTask+0x181
021ac5f8 63664103 0020bab0 00000000 02d79d10 mshtml!CMarkup::ProcessPeerTasks+0xe9
eax=00988090 ebx=00986568 ecx=00988108 edx=77c31aa0 esi=00988108 edi=00986550
eip=0332a519 esp=021a9e1c ebp=021a9e1c iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
vgx!CSafePtr::CSafePtr+0xe:
0332a519 c7004ccd2d03 mov dword ptr [eax],offset vgx!CSafePtr::`vftable' (032dcd4c)
ds:0023:00988090=????????
注意这里在 00988090 位置创建了一个 CSafePtr 对象。
然后 poc 中改变了 dashstyle.array 的长度:
“shape.dashstyle.array.length = 0 - 1”
其实从 0 – 1 这一运算中可以猜到溢出就发生在这里。代码中是在这里执行的:
ChildEBP RetAddr Args to Child
021ac298 770f73d0 00987de0 ffffffff 021ac2e8 vgx!COALineDashStyleArray::put_length+0x71
021ac2b4 770f79e0 0378b6c0 00000030 00000004 oleaut32!DispCallFunc+0x16a
021ac344 033246a1 02cc89c4 0378b6c0 00000000 oleaut32!CTypeInfo2::Invoke+0x234
021ac4d0 03344a92 0378b6c4 0378b6c0 03362244 vgx!COADispatch::Invoke+0x89
021ac504 633a9003 0378b6c0 00000002 633a7224
vgx!COADispatchImpl<IVgDashStyleArray,&IID_IVgDashStyleArray,COAShapeProg>::Invoke+0x2f
021ac548 633a8f4a 00985ae0 00000002 00000409 jscript!IDispatchInvoke2+0xe5
021ac584 633a8ebd 00985ae0 00000409 00000004 jscript!IDispatchInvoke+0x6a
021ac644 633aa53f 00985ae0 00000002 00000004 jscript!InvokeDispatch+0xa6
021ac670 633a77ff 00985ae0 021ac6a4 0000000c jscript!VAR::InvokeByName+0x90
021ac6b8 633a75bf 00985ae0 0000000c 00000000 jscript!VAR::InvokeDispName+0x7a
021ac894 63682dd5 02848dc0 00984580 021af780 jscript!CScriptRuntime::Run+0x1f27
00000000 00000000 00000000 00000000 00000000 mshtml!CFlowLayout::Draw+0x1d
0333db50 3bc6 cmp eax,esi
0333db52 7d55 jge vgx!COALineDashStyleArray::put_length+0xca (0333dba9)
0333dba9 8b4d08 mov ecx,dword ptr [ebp+8] ss:0023:021ac2a0=00987de0
0333dbac 8b11 mov edx,dword ptr [ecx]
0333dbae 2bc6 sub eax,esi
0333dbb0 50 push eax
0333dbb1 56 push esi
0333dbb2 51 push ecx
0333dbb3 ff5228 call dword ptr [edx+28h] // vgx!ORG::DeleteRange
具体执行过程为:
eax=00000008 ebx=03344988 ecx=032d72c8 edx=021ac26c esi=ffffffff edi=00000000
eip=0333db50 esp=021ac280 ebp=021ac298 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
vgx!COALineDashStyleArray::put_length+0x71:
0333db50 3bc6 cmp eax,esi
此处 eax 值为 vgx!ORG+4 处的值,此时为 8,esi 为函数传入的参数,也就是 0-1 的结果。
判断逻辑是:如果传入的值大于原有值,就执行增加 dashstyle.array 长度的函数;如果反之
则执行减小 dashstyle.array 长度的函数。由于 ffffffffh 为一负数,判断后程序执行减小
dashstyle.array 长度的函数:
vgx!COALineDashStyleArray::put_length+0xd4:
0333dbb3 call dword ptr [edx+28h] ds:0023:032d72f0={vgx!ORG::DeleteRange (032ecfd6)}
0:001> dd esp
021ac274 00987de0 ffffffff 00000009 00000000
[\CODE]
此函数的参数 1 为 vgx!ORG 位置,参数 2 为需要设定的值,参数 3 为需要减少的大小,
也就是原有值-需设定值,程序中是由 sub eax,esi 得到的,此处 8-(-1)=9。
进入此函数后发现,函数会用原有长度的低两位减去需要减少的值,将结果截断为 2
字节后保存在 vgx!ORG+4 处,最终结果为 0000ffff,在此处发生溢出。执行过程如下:
[CODE]
eax=00000008 ebx=00000009 ecx=00987d8c edx=00000008 esi=00987de4 edi=00000004
eip=0332c2f9 esp=021ac234 ebp=021ac240 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
vgx!MsoFRemovePx+0xa7:
0332c2f9 66291e sub word ptr [esi],bx ds:0023:00987de4=0008
0:001> p
0:001> dd esi
00987de4 0000ffff 00040004 00000000 00987d90
[\CODE]
然后 poc 循环修改 dashstyle.array.item 的值
[CENTER]“shape.dashstyle.array.item(0x2E+0x16+i) = 0x4b5f5f4b”[/CENTER]
程序中对应于此处:
[CODE]
ChildEBP RetAddr Args to Child
021ac25c 770f73d0 00987de0 000000c0 4b5f5f4b vgx!COALineDashStyleArray::put_item+0x81
021ac27c 770f79e0 0378b6c0 00000028 00000004 oleaut32!DispCallFunc+0x16a
021ac30c 033246a1 02cc89c4 0378b6c0 00000000 oleaut32!CTypeInfo2::Invoke+0x234
021ac498 03344a92 0378b6c4 0378b6c0 03362244 vgx!COADispatch::Invoke+0x89
021ac4cc 633a9003 0378b6c0 00000000 633a7224
vgx!COADispatchImpl<IVgDashStyleArray,&IID_IVgDashStyleArray,COAShapeProg>::Invoke+0x2f
021ac510 633a8f4a 00985ae0 00000000 00000409 jscript!IDispatchInvoke2+0xe5
021ac54c 633a8ebd 00985ae0 00000409 00000004 jscript!IDispatchInvoke+0x6a
021ac60c 633aa53f 00985ae0 00000000 00000004 jscript!InvokeDispatch+0xa6
021ac638 633a77ff 00985ae0 021ac66c 0000000c jscript!VAR::InvokeByName+0x90
021ac684 633a85c7 00985ae0 0000000c 00000000 jscript!VAR::InvokeDispName+0x7a
021ac6b0 633a481b 00985ae0 00000000 0000000c jscript!VAR::InvokeByDispID+0xce
021ac894 63682dd5 02848dc0 00984580 00984900 jscript!CScriptRuntime::Run+0x2a0c
00000000 00000000 00000000 00000000 00000000 mshtml!CFlowLayout::Draw+0x1d
0333dab0 cmp dword ptr [ebp+0Ch],eax ss:0023:021ac268=000000c0 //000000c0 为 item key,eax=0000ffff 为 array length
0333dab3 jge vgx!COALineDashStyleArray::put_item+0x8b (0333dac8) //越界判断
0333dab5 mov eax,dword ptr [ebp+8]
0333dab8 push dword ptr [ebp+0Ch]
0333dabb mov ecx,dword ptr [eax]
0333dabd push eax
0333dabe call dword ptr [ecx+20h] ds:0023:032d72e8={vgx!ORG::PGet (032ed029)} //Get dashstyle.array.item Addr
0333dac1 mov ecx,dword ptr [ebp+10h] //Get 4b5f5f4b
0333dac4 mov dword ptr [eax],ecx //eax= 00988090
=====================================
vgx!ORG::PGet:
.text:032ED029 mov edi, edi
.text:032ED02B push ebp
.text:032ED02C mov ebp, esp
.text:032ED02E mov ecx, [ebp+arg_0]
.text:032ED031 mov eax, [ecx+8]
.text:032ED034 and eax, 0FFFFh
.text:032ED039 imul eax, [ebp+arg_4] //eax=4,size*key= 00000300
.text:032ED03D add eax, [ecx+10h] // ds:0023:00987df0=00987d90, dashstyle.array 地址
.text:032ED040 pop ebp
.text:032ED041 retn 8
由于 array length 被修改为 0000ffff,所以越界检查失败,越界写入覆盖了 dashstyle.array
后面 00988090 位置的 CSafePtr 对象,写入了 POC 中的地址 4b5f5f4b,也由此导致了最后程序崩溃:
ChildEBP RetAddr Args to Child
021ac0d8 03326596 00986bd4 03327c6e 07eab604 vgx!CSafeRef::State+0x8
021ac0e0 03327c6e 07eab604 00986bd4 0332c076 vgx!CVMLUpdate::GetVMLShape+0xd
021ac0ec 0332c076 00986bd4 00986bd4 021ac1d8 vgx!SgnCompareRTSUpdate+0xb
021ac100 0332c62f 00986bd4 021ac1d8 021ac12c vgx!MsoFLookupPx+0x65
021ac11c 03327d6a 00986bd4 021ac1d8 03327c63 vgx!MsoPLookupPx+0x19
021ac1bc 0332944b 021ac1d8 03327c63 00000000
vgx!CVMLUpdateQueue<CVMLRTSUpdate>::AppendUnique+0x34
021ac258 03329f16 0099c310 00000141 00000000 vgx!CVMLRTSUpdate::AddKey+0x69
021ac26c 03340328 00000141 00000000 00000000 vgx!CVMLShape::RefreshStyle+0x11
021ac298 770f73d0 0378c4c0 07e800dc 021ac2e8 vgx!COARuntimeStyle::put_marginLeft+0x97
021ac2b4 770f79e0 0378c4c0 00000048 00000004 oleaut32!DispCallFunc+0x16a
021ac344 033246a1 02cc88bc 0378c4c0 00000000 oleaut32!CTypeInfo2::Invoke+0x234
021ac4d0 033454b2 0378c4c4 0378c4c0 033622ec vgx!COADispatch::Invoke+0x89
021ac504 633a9003 0378c4c0 00000069 633a7224
vgx!COADispatchImpl<IVgRuntimeStyle,&IID_IVgRuntimeStyle,COAShapeProg>::Invoke+0x2f
021ac548 633a8f4a 00985ae0 00000069 00000409 jscript!IDispatchInvoke2+0xe5
021ac584 633a8ebd 00985ae0 00000409 00000004 jscript!IDispatchInvoke+0x6a
021ac644 633aa53f 00985ae0 00000069 00000004 jscript!InvokeDispatch+0xa6
021ac670 633a77ff 00985ae0 021ac6a4 0000000c jscript!VAR::InvokeByName+0x90
021ac6b8 633a75bf 00985ae0 0000000c 00000000 jscript!VAR::InvokeDispName+0x7a
021ac894 63682dd5 02848dc0 00984580 00984900 jscript!CScriptRuntime::Run+0x1f27
00000000 00000000 00000000 00000000 00000000 mshtml!CFlowLayout::Draw+0x1d
.text:0332A4C9 mov ecx, [ecx] // ds:0023:07eab610=00988090
.text:0332A4CB test ecx, ecx
.text:0332A4CD jz short loc_332A4D3
.text:0332A4CF mov eax, [ecx]
.text:0332A4D1 jmp dword ptr [eax]
(908.a20): Access violation - code c0000005 (first/second chance not available)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=4b5f5f4b ebx=00000005 ecx=00988090 edx=021ac1d8 esi=07eab604 edi=021ac1d8
eip=0332a4d1 esp=021ac0dc ebp=021ac100 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
vgx!CSafeRef::State+0x8:
0332a4d1 ff20 jmp dword ptr [eax] ds:0023:4b5f5f4b=????????
注:本帖由看雪论坛志愿者PEstone 重新将PDF整理排版,若和原文有出入,以原作者附件为准
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法