Module: Msf::Post::Process

Includes:
File
Included in:
Linux::Process, Windows::Process
Defined in:
lib/msf/core/post/process.rb

Instance Method Summary collapse

Methods included from File

#_append_file_powershell, #_append_file_unix_shell, #_can_echo?, #_read_file_meterpreter, #_read_file_powershell, #_read_file_powershell_fragment, #_shell_command_with_success_code, #_shell_process_with_success_code, #_unix_max_line_length, #_win_ansi_append_file, #_win_ansi_write_file, #_win_bin_append_file, #_win_bin_write_file, #_write_file_meterpreter, #_write_file_powershell, #_write_file_powershell_fragment, #_write_file_unix_shell, #append_file, #attributes, #cd, #chmod, #copy_file, #dir, #directory?, #executable?, #exist?, #expand_path, #exploit_data, #exploit_source, #file?, #file_local_write, #file_remote_digestmd5, #file_remote_digestsha1, #file_remote_digestsha2, #immutable?, #mkdir, #pwd, #read_file, #readable?, #rename_file, #rm_f, #rm_rf, #setuid?, #stat, #upload_and_chmodx, #upload_file, #writable?, #write_file

Methods included from Common

#clear_screen, #cmd_exec, #cmd_exec_get_pid, #cmd_exec_with_result, #command_exists?, #create_process, #get_env, #get_envs, #peer, #report_virtualization, #rhost, #rport

Instance Method Details

#get_processesObject

Gets the ‘pid` and `name` of the processes on the remote system

[View source]

39
40
41
42
43
44
45
46
47
# File 'lib/msf/core/post/process.rb', line 39

def get_processes
  if session.type == 'meterpreter'
    meterpreter_get_processes
  elsif session.type == 'powershell'
    shell_get_processes
  else
    shell_get_processes
  end
end

#has_pid?(pid) ⇒ Boolean

Checks if the remote system has a process with ID pid

Returns:

  • (Boolean)
[View source]

31
32
33
34
# File 'lib/msf/core/post/process.rb', line 31

def has_pid?(pid)
  pid_list = get_processes.collect { |e| e['pid'] }
  pid_list.include?(pid)
end

#initialize(info = {}) ⇒ Object

[View source]

7
8
9
10
11
12
13
14
15
# File 'lib/msf/core/post/process.rb', line 7

def initialize(info = {})
  super(update_info(
    info,
    'Compat' => { 'Meterpreter' => { 'Commands' => %w{
      stdapi_sys_process_get_processes
      stdapi_sys_process_kill
    } } }
  ))
end

#kill_process(pid) ⇒ Boolean

Forcefully terminate process with ID ‘pid` on the remote system

Returns:

  • (Boolean)

    True upon success

[View source]

54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/msf/core/post/process.rb', line 54

def kill_process(pid)
  if session.type == 'meterpreter' && session.commands.include?(Rex::Post::Meterpreter::Extensions::Stdapi::COMMAND_ID_STDAPI_SYS_PROCESS_KILL)
    session.sys.process.kill(pid)
    return true
  end

  if session.platform == 'windows'
    return !cmd_exec("taskkill /F /PID #{pid}").to_s.starts_with?('ERROR')
  end

  cmd_exec("kill -9 #{pid} && echo true").to_s.include?('true')
rescue Rex::Post::Meterpreter::RequestError
  false
end

#meterpreter_get_processesObject

[View source]

69
70
71
72
73
74
75
# File 'lib/msf/core/post/process.rb', line 69

def meterpreter_get_processes
  begin
    return session.sys.process.get_processes.map { |p| p.slice('name', 'pid') }
  rescue Rex::Post::Meterpreter::RequestError
    shell_get_processes
  end
end

#pidof(program) ⇒ Object

Gets the ‘pid`(s) of a specified program

[View source]

20
21
22
23
24
25
26
# File 'lib/msf/core/post/process.rb', line 20

def pidof(program)
  pids = []
  get_processes.each do |p|
     pids << p["pid"] if p['name'] =~ /(^|[\\\/])#{::Regexp.escape(program)}$/
  end
  pids
end

#shell_get_processesObject

[View source]

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
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/process.rb', line 77

def shell_get_processes
  processes = []
  if session.platform == 'windows'
    tasklist = cmd_exec('tasklist').split("\n")
    4.times { tasklist.delete_at(0) }
    tasklist.each do |p|
      properties = p.split
      process = {}
      process['name'] = properties[0]
      process['pid'] = properties[1].to_i
      processes.push(process)
    end
    # adding manually because this is common for all windows I think and splitting for this was causing problem for other processes.
    processes.prepend({ 'name' => '[System Process]', 'pid' => 0 })
  else
    if command_exists?('ps')
      ps_aux = cmd_exec('ps aux').split("\n")
      ps_aux.delete_at(0)
      ps_aux.each do |p|
        properties = p.split
        process = {}
        process['name'] = properties[10].gsub(/\[|\]/,"")
        process['pid'] = properties[1].to_i
        processes.push(process)
      end
    elsif directory?('/proc')
      directories_proc = dir('/proc/')
      directories_proc.each do |elem|
        elem.to_s.gsub(/ *\n+/, '')
        next unless elem[-1].match? /\d/

        process = {}
        process['pid'] = elem.to_i
        status = read_file("/proc/#{elem}/status") # will return nil if the process `elem` PID got vanished
        next unless status

        process['name'] = status.split(/\n|\t/)[1]
        processes.push(process)
      end
    else
      raise "Can't enumerate processes because `ps' command and `/proc' directory doesn't exist."
    end
  end
  return processes
end