Windbg漏洞分析之CVE-2013-2551

来源:互联网 发布:网络语香菇是什么意思 编辑:程序博客网 时间:2024/05/22 12:04

第一次写这样的文章,如有不对之处,请批评指正。

1.  漏洞描述

此漏洞是由于负责解析VML的VGX.dll模块,在处理<v:stroke>标签的dashstyle.array.length属性时,没有对传入的参数进行完备验证而导致整数溢出。攻击者利用这个漏洞能够对任意地址进行读写操作——通过读取敏感内存信息、改写对象虚表,就能够完美绕过重重内存防护机制实现任意代码执行。

2.  分析环境

(Win8) + (IE10) +(CVE-2013-2551)

3.  Poc脚本分析


通过分析脚本发现两点比较可疑地方,首先是vml1.dashstyle=”12 3 4 5 6 7…”,其次是vml1.dashstyle.array.length = 0-1。 VML为shape元素实现了一个Stroke子元素,Stroke子元素有一个DashStyle属性。DashStyle可以是一个常数也可以是一个自定义的类型。当通过JS读取dashstyle属性时,其内部会调用"vgx!COAStroke::get_dashstyle()",随后"vgx!COAStroke::get_dashstyle()"调用子函数"vgx!COAShapeProg::GetOALineDashStyle()"并最终返回一个COALineDashStyle对象。

Dashstyle属性的功能是由COALineDashStyle对象实现的,针对dashstyle为常熟或自定义两种情况会调用不同的COALineDashStyle实现方法,如果dashstyle属性是常数则会调用COALineDashStyle的get_value/put_value函数,如果dashstyle属性为自定义类型那么会调用COALineDashStyle的get_array()方法,并在其子函数COAShapeProg::GetOALineDashStyleArray中返回一个GetOALineDashStyleArray对象。

GetOALineDashStyleArray对象管理dashstyle的自定义属性,其方法有GetOALineDashStyleArray::get_item,GetOALineDashStyleArray::put_itemGetOALineDashStyleArray::get_length,GetOALineDashStyleArray::put_length

当脚本中设置dashstyle.array.length属性时get_length和put_length会被调用,如果调用dashstyle.array访问元素的时候get_item与put_item会被调用。

脚本中使用js语句对dashstyle属性赋值,形如vml1.dashstyle=”1 2 3 4 5 67…”

这时候vgx的vgx!ParseDashStyle会被调用,将控制流转向_MsoFCreateArray函数来创建一个ORG数组。在_MsoFCreateArray中调用_MsoFInitPx函数根据数组成员个数来、进行内存分配,每个数组成员占四字节内存,所以ORG数组的缓冲区大小为数组成员个数×4(byte)。在对dashstyle.array.length属性赋值时,数组成员的个数会改变,在put_length函数中会根据新设置的值来重新为ORG数组成分配内存。然而在put_length中存在一个整数溢出漏洞。

 

4.windbg跟踪调试

使用windbg在vgx模块的GetOALineDashStyleArray::put_length函数入口处下断点。

778b125c cc              int     3

0:018> bpvgx!COALineDashStyleArray::put_length (put_length处设断点)

vgx!COALineDashStyleArray::put_length+0x56:

6d01b84d 8b01            mov     eax,dword ptr [ecx]

6d01b84f 51              push    ecx

6d01b850 ff502c          call    dword ptr[eax+2Ch] (callCElements获取当前数组长度)

6d01b853 8b750c          mov     esi,dword ptr [ebp+0Ch] (保存当前新数组长度(new_length)到esi)

6d01b856 8bd0            mov     edx,eax (保存CElements返回值(cur_length)到edx)

6d01b8583bd6            cmp     edx,esi (比较cur_length与 new_length) (new_length为(0-1))所以跳转到

6d01b85a 7d50        jge    vgx!COALineDashStyleArray::put_length+0xb5 (6d01b8ac)

vgx!COALineDashStyleArray::put_length+0xb5:

6d01b8ac 8b4508          mov     eax,dword ptr [ebp+8]

6d01b8af 8b08            mov     ecx,dword ptr [eax]

6d01b8b1 2bd6            sub     edx,esi

6d01b8b3 52              push    edx

6d01b8b4 56              push    esi

6d01b8b5 50              push    eax

6d01b8b6 ff5128          call    dword ptr[ecx+28h] (callORG::DeleteRange)

6d01b8b9 eb08            jmp     vgx!COALineDashStyleArray::put_length+0xcc(6d01b8c3)

 

 

0:006> bl

 0 e6d01b7f7     0001 (0001)  0:**** vgx!COALineDashStyleArray::put_length

0:006> pc (列出put_length一次调用的函数)

Breakpoint 0 hit

eax=0000000a ebx=6cfc0e90 ecx=6d01b7f7edx=00e2e9ba esi=0292b5b0 edi=00e2e974

eip=6d01b7f7 esp=0292b088 ebp=0292b0a0iopl=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:

6d01b7f7 8bff            mov     edi,edi

0:006>

eax=6cfc0b5c ebx=0616df98 ecx=0617c6b0edx=00e2e9ba esi=0617c6b0 edi=00e2e974

eip=6d01b80c esp=0292b068 ebp=0292b084iopl=0         nv up ei pl nz na pe nc

cs=001b ss=0023  ds=0023  es=0023 fs=003b  gs=0000             efl=00000206

vgx!COALineDashStyleArray::put_length+0x15:

6d01b80c ff5020          call    dword ptr [eax+20h]  ds:0023:6cfc0b7c={vgx!COAProg::CheckProg(6cffe728)}

0:006>

eax=0617c6b0 ebx=0616df98 ecx=02ac6198edx=00e2e9ba esi=0617c6b0 edi=00000000

eip=6d01b831 esp=0292b068 ebp=0292b084iopl=0         nv up ei pl zr na pe nc

cs=001b ss=0023  ds=0023  es=0023 fs=003b  gs=0000             efl=00000246

vgx!COALineDashStyleArray::put_length+0x3a:

6d01b831 e8a219ffff      call   vgx!COAShapeProg::GetShape (6d00d1d8)

0:006>

eax=6cfbfbc0 ebx=0616df98 ecx=02ac6190edx=0292b08c esi=0617c6b0 edi=00000000

eip=6d01b844 esp=0292b060 ebp=0292b084iopl=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+0x4d:

6d01b844 ff10            call    dword ptr [eax]      ds:0023:6cfbfbc0={vgx!CVMLShape::FetchProp (6d028845)}

0:006>

eax=6cfbca10 ebx=0616df98 ecx=06181920edx=02b1daf8 esi=0617c6b0 edi=00000000

eip=6d01b850 esp=0292b064 ebp=0292b084iopl=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+0x59:

6d01b850 ff502c          call    dword ptr [eax+2Ch]  ds:0023:6cfbca3c={vgx!ORG::CElements (6cfcc560)}

0:006> pc

eax=05aa7890 ebx=024730b8 ecx=6d79ca10edx=0000002d esi=ffffffff edi=00000000

eip=6d7fb8b6 esp=022badec ebp=022bae14iopl=0         nv up ei pl nz ac pe cy

cs=001b ss=0023  ds=0023  es=0023 fs=003b  gs=0000             efl=00000217

vgx!COALineDashStyleArray::put_length+0xbf:

6d7fb8b6 ff5128          call    dword ptr[ecx+28h]  ds:0023:6d79ca38={vgx!ORG::DeleteRange(6d7ac449)}

 

0:006> bp vgx!ORG::CElements (CElements函数处设断点,调用celement目的是为了重新分配数组)

0:006> g

Breakpoint 1 hit

eax=6cfbca10 ebx=0616df98 ecx=06181920edx=02b1daf8 esi=0617c6b0 edi=00000000

eip=6cfcc560 esp=0292b060 ebp=0292b084iopl=0         nv up ei pl nz na po nc

cs=001b ss=0023  ds=0023  es=0023 fs=003b  gs=0000             efl=00000202

vgx!ORG::CElements:

6cfcc560 8bff            mov     edi,edi

0:006> uf .

vgx!ORG:: CElements  (CElements函数反汇编)

6cfcc560 8bff            mov     edi,edi

6cfcc562 55              push    ebp

6cfcc563 8bec            mov     ebp,esp

6cfcc565 8b4508          mov     eax,dword ptr [ebp+8]

6cfcc568 0fb74004        movzx   eax,word ptr[eax+4]    (movzx为无符号整数操作,猜想是为了获取数组长度,作为返回值)

6cfcc56c 5d              pop     ebp

6cfcc56d c20400          ret     4

 

eax=058d9690 ebx=05897eb8 ecx=6d79ca10edx=0000002d esi=ffffffff edi=00000000

eip=6d7ac449 esp=01fbadf8 ebp=01fbae24iopl=0         nv up ei pl nz ac pe cy

cs=001b ss=0023  ds=0023  es=0023 fs=003b  gs=0000             efl=00000217

vgx!ORG::DeleteRange:

6d7ac449 8bff            mov     edi,edi

0:006> uf .

vgx!ORG::DeleteRange: (ORG::DeleteRange反汇编函数)

6d7ac449 8bff            mov     edi,edi

6d7ac44b 55              push    ebp

6d7ac44c 8bec            mov     ebp,esp

6d7ac44e ff7510          push    dword ptr [ebp+10h]

6d7ac451 8b4508          mov     eax,dword ptr [ebp+8]

6d7ac454 ff750c          push    dword ptr [ebp+0Ch]

6d7ac457 83c004          add     eax,4

6d7ac45a 50              push    eax

6d7ac45be8549c0300      call    vgx!MsoDeletePx (6d7e60b4) (ORG::DeleteRange调用MsoDeletePx进行delete)

6d7ac460 5d              pop     ebp

6d7ac461 c20c00          ret     0Ch

 

 

0:006> bp vgx!MsoDeletePx

0:006> g

Breakpoint 1 hit

eax=058d9694 ebx=05897eb8 ecx=6d79ca10edx=0000002d esi=ffffffff edi=00000000

eip=6d7e60b4 esp=01fbade4 ebp=01fbadf4iopl=0         nv up ei pl nz na po nc

cs=001b ss=0023  ds=0023  es=0023 fs=003b  gs=0000             efl=00000202

vgx!MsoDeletePx:

6d7e60b4 8bff            mov     edi,edi

0:006> uf .

vgx!MsoDeletePx:

6d7e60b4 8bff            mov     edi,edi

6d7e60b6 55              push    ebp

6d7e60b7 8bec            mov     ebp,esp

6d7e60b9 56              push    esi

6d7e60ba ff7510          push    dword ptr [ebp+10h]

6d7e60bd 8b7508          mov     esi,dword ptr [ebp+8]

6d7e60c0 ff750c          push    dword ptr [ebp+0Ch]

6d7e60c3 56              push    esi

6d7e60c4 e819000000      call    vgx!MsoFRemovePx (6d7e60e2)

6d7e60c9 33c0            xor     eax,eax

6d7e60cb 663906          cmp     word ptr [esi],ax

6d7e60ce 0f94c0          sete    al

6d7e60d1 50              push    eax

6d7e60d2 56              push    esi

6d7e60d3 e8c7000000      call   vgx!MsoFCompactPx (6d7e619f)

6d7e60d8 5e              pop     esi

6d7e60d9 5d              pop     ebp

6d7e60da c20c00          ret    0Ch

 

0:006> uf .

vgx!MsoFRemovePx:

6d7e60e2 8bff            mov    edi,edi

6d7e60e4 55              push     ebp                                              <-------------

6d7e60e5 8bec            mov     ebp,esp                                         .

6d7e60e7 8b450c          mov     eax,dword ptr [ebp+0Ch]               .(eax为new_length)

6d7e60ea 53              push     ebx                                               .

6d7e60eb 8b5d08          mov     ebx,dword ptr [ebp+8]                  .

6d7e60ee 8b4b04          mov     ecx,dword ptr [ebx+4]                   .

...

vgx!MsoFRemovePx+0x83:

6d7e6165 8b7510          mov     esi,dword ptr [ebp+10h]      <------(esi为cur_length-new_length)

vgx!MsoFRemovePx+0x86:

6d7e6168 0fb713          movzx  edx,word ptr [ebx]                          <-------(edx为cur_length)-

6d7e616b 03c6            add     eax,esi                                            .

6d7e616d 3bc2            cmp     eax,edx                                         .

6d7e616f 741d            je      vgx!MsoFRemovePx+0xac(6d7e618e)<-------------

...

vgx!MsoFRemovePx+0xac:

6d7e618e 662933          sub     word ptr[ebx],si <------cur_length=cur_length-(cur_length-new_length)

6d7e6191 5f              pop     edi                                           .

6d7e6192 8bc6            mov     eax,esi                                    .

6d7e6194 5e              pop     esi                                          .

6d7e6195 5b              pop     ebx                                         .

6d7e6196 5d              pop     ebp                                        .

6d7e6197 c20c00          ret     0Ch                                          <-------------

 

因此当传入new_length的值为有符号数0xFFFFFFFF时,会导致整数溢出,数组的长度被改写为0xFFFF=65535,但对应的内存却没有被分配。那么就掌握了对内存的控制。

 

 

5.此CVE漏洞攻击的主线

(1)使用vml语言

(2)设置stroke.dashstyle=”1 2 3 4 5 6….”转移控制流

(3)对dashstyle.array.length属性进行赋值

(4)步骤3会导致put_length根据新的数组长度对ORG数组重新分配内存

(5)如果步骤3传入的是0xffffffff那么在put_length中会跳转至ORG::DeleteRange,接下来的流程为ORG::DeleteRange-->MsoDeletePx-->MsoFRemovePx。

(6)在MsoFRemovePx函数内部,最终将新赋值的数组长度设置成了current_length,使得在没有重新分配内存的情况下将ORG数组长度current_length改写成0xFFFF。因此,可以通过此时的ORG数组获得越界访问。

(要成功exploitdashstyle.array.length不能直接设置为0xffffffff,会报错,需要设置为0-1)

 

 

 

0 0