lib/msf/core/post/process.rb
# -*- coding: binary -*-
module Msf::Post::Process
include Msf::Post::File
def initialize(info = {})
super(update_info(
info,
'Compat' => { 'Meterpreter' => { 'Commands' => %w{
stdapi_sys_process_get_processes
stdapi_sys_process_kill
} } }
))
end
#
# Gets the `pid`(s) of a specified program
#
def pidof(program)
pids = []
get_processes.each do |p|
pids << p["pid"] if p['name'] =~ /(^|[\\\/])#{::Regexp.escape(program)}$/
end
pids
end
#
# Checks if the remote system has a process with ID +pid+
#
def has_pid?(pid)
pid_list = get_processes.collect { |e| e['pid'] }
pid_list.include?(pid)
end
#
# Gets the `pid` and `name` of the processes on the remote system
#
def get_processes
if session.type == 'meterpreter'
meterpreter_get_processes
elsif session.type == 'powershell'
shell_get_processes
else
shell_get_processes
end
end
#
# Forcefully terminate process with ID `pid` on the remote system
#
# @return [Boolean] True upon success
#
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
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
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
end