class Rex::Post::Meterpreter::Extensions::Stdapi::Sys::Process

This class implements the Rex::Post::Process interface.

Attributes

client[RW]

Public Class Methods

[](key) click to toggle source

Returns the process identifier of the process supplied in key if it's valid.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb, line 43
def Process.[](key)
  each_process { |p|
    if (p['name'].downcase == key.downcase)
      return p['pid']
    end
  }

  return nil
end
_open(pid, perms, inherit = false) click to toggle source

Low-level process open.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb, line 81
def Process._open(pid, perms, inherit = false)
  request = Packet.create_request('stdapi_sys_process_attach')

  if (pid == nil)
    pid = 0
  end

  # Populate the request
  request.add_tlv(TLV_TYPE_PID, pid)
  request.add_tlv(TLV_TYPE_PROCESS_PERMS, perms)
  request.add_tlv(TLV_TYPE_INHERIT, inherit)

  # Transmit the request
  response = self.client.send_request(request)
  handle   = response.get_tlv_value(TLV_TYPE_HANDLE)

  # If the handle is valid, allocate a process instance and return it
  if (handle != nil)
    return self.new(pid, handle)
  end

  return nil
end
close(client, handle) click to toggle source

Closes the handle to the process that was opened.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb, line 312
def self.close(client, handle)
  request = Packet.create_request('stdapi_sys_process_close')
  request.add_tlv(TLV_TYPE_HANDLE, handle)
  response = client.send_request(request, nil)
  handle = nil;
  return true
end
each_process(&block) click to toggle source

Enumerates all of the elements in the array returned by get_processes.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb, line 209
def Process.each_process(&block)
  self.get_processes.each(&block)
end
execute(path, arguments = nil, opts = nil) click to toggle source

Executes an application using the arguments provided

Hash arguments supported:

Hidden      => true/false
Channelized => true/false
Suspended   => true/false
InMemory    => true/false
# File lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb, line 115
def Process.execute(path, arguments = nil, opts = nil)
  request = Packet.create_request('stdapi_sys_process_execute')
  flags   = 0

  # If we were supplied optional arguments...
  if (opts != nil)
    if (opts['Hidden'])
      flags |= PROCESS_EXECUTE_FLAG_HIDDEN
    end
    if (opts['Channelized'])
      flags |= PROCESS_EXECUTE_FLAG_CHANNELIZED
    end
    if (opts['Suspended'])
      flags |= PROCESS_EXECUTE_FLAG_SUSPENDED
    end
    if (opts['UseThreadToken'])
      flags |= PROCESS_EXECUTE_FLAG_USE_THREAD_TOKEN
    end
    if (opts['Desktop'])
      flags |= PROCESS_EXECUTE_FLAG_DESKTOP
    end
    if (opts['Session'])
      flags |= PROCESS_EXECUTE_FLAG_SESSION
      request.add_tlv( TLV_TYPE_PROCESS_SESSION, opts['Session'] )
    end
    inmem = opts['InMemory']
    if inmem

      # add the file contents into the tlv
      f = ::File.new(path, 'rb')
      request.add_tlv(TLV_TYPE_VALUE_DATA, f.read(f.stat.size))
      f.close

      # replace the path with the "dummy"
      path = inmem.kind_of?(String) ? inmem : 'cmd'
    end
  end

  request.add_tlv(TLV_TYPE_PROCESS_PATH, client.unicode_filter_decode( path ));

  # If process arguments were supplied
  if (arguments != nil)
    request.add_tlv(TLV_TYPE_PROCESS_ARGUMENTS, arguments);
  end

  request.add_tlv(TLV_TYPE_PROCESS_FLAGS, flags);

  response = client.send_request(request)

  # Get the response parameters
  pid        = response.get_tlv_value(TLV_TYPE_PID)
  handle     = response.get_tlv_value(TLV_TYPE_PROCESS_HANDLE)
  channel_id = response.get_tlv_value(TLV_TYPE_CHANNEL_ID)
  channel    = nil

  # If we were creating a channel out of this
  if (channel_id != nil)
    channel = Rex::Post::Meterpreter::Channels::Pools::StreamPool.new(client,
        channel_id, "stdapi_process", CHANNEL_FLAG_SYNCHRONOUS)
  end

  # Return a process instance
  return self.new(pid, handle, channel)
end
finalize(client, handle) click to toggle source
# File lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb, line 291
def self.finalize(client, handle)
  proc { self.close(client, handle) }
end
get_processes() click to toggle source

Returns a ProcessList of processes as Hash objects with keys for 'pid', 'ppid', 'name', 'path', 'user', 'session' and 'arch'.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb, line 217
def Process.get_processes
  request   = Packet.create_request('stdapi_sys_process_get_processes')
  processes = ProcessList.new

  response = client.send_request(request)

  response.each(TLV_TYPE_PROCESS_GROUP) { |p|
  arch = ""

  pa = p.get_tlv_value( TLV_TYPE_PROCESS_ARCH )
  if( pa != nil )
    if pa == 1 # PROCESS_ARCH_X86
      arch = ARCH_X86
    elsif pa == 2 # PROCESS_ARCH_X64
      arch = ARCH_X86_64
    end
  end

  processes <<
      {
        'pid'      => p.get_tlv_value(TLV_TYPE_PID),
        'ppid'     => p.get_tlv_value(TLV_TYPE_PARENT_PID),
        'name'     => client.unicode_filter_encode( p.get_tlv_value(TLV_TYPE_PROCESS_NAME) ),
        'path'     => client.unicode_filter_encode( p.get_tlv_value(TLV_TYPE_PROCESS_PATH) ),
        'session'  => p.get_tlv_value(TLV_TYPE_PROCESS_SESSION),
        'user'     => client.unicode_filter_encode( p.get_tlv_value(TLV_TYPE_USER_NAME) ),
        'arch'     => arch
      }
  }

  return processes
end
getpid() click to toggle source

Gets the process id that the remote side is executing under.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb, line 198
def Process.getpid
  request = Packet.create_request('stdapi_sys_process_getpid')

  response = client.send_request(request)

  return response.get_tlv_value(TLV_TYPE_PID)
end
kill(*args) click to toggle source

Kills one or more processes.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb, line 183
def Process.kill(*args)
  request = Packet.create_request('stdapi_sys_process_kill')

  args.each { |id|
    request.add_tlv(TLV_TYPE_PID, id)
  }

  client.send_request(request)

  return true
end
new(pid, handle, channel = nil) click to toggle source

Initializes the process instance and its aliases.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb, line 266
def initialize(pid, handle, channel = nil)
  self.client  = self.class.client
  self.handle  = handle
  self.channel = channel

  # If the process identifier is zero, then we must lookup the current
  # process identifier
  if (pid == 0)
    self.pid = client.sys.process.getpid
  else
    self.pid = pid
  end

  initialize_aliases(
    {
      'image'  => Rex::Post::Meterpreter::Extensions::Stdapi::Sys::ProcessSubsystem::Image.new(self),
      'io'     => Rex::Post::Meterpreter::Extensions::Stdapi::Sys::ProcessSubsystem::IO.new(self),
      'memory' => Rex::Post::Meterpreter::Extensions::Stdapi::Sys::ProcessSubsystem::Memory.new(self),
      'thread' => Rex::Post::Meterpreter::Extensions::Stdapi::Sys::ProcessSubsystem::Thread.new(self),
    })

  # Ensure the remote object is closed when all references are removed
  ObjectSpace.define_finalizer(self, self.class.finalize(client, handle))
end
open(pid = nil, perms = nil) click to toggle source

Attachs to the supplied process with a given set of permissions.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb, line 56
def Process.open(pid = nil, perms = nil)
  real_perms = 0

  if (perms == nil)
    perms = PROCESS_ALL
  end

  if (perms & PROCESS_READ)
    real_perms |= PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_QUERY_INFORMATION
  end

  if (perms & PROCESS_WRITE)
    real_perms |= PROCESS_SET_SESSIONID | PROCESS_VM_WRITE | PROCESS_DUP_HANDLE | PROCESS_SET_QUOTA | PROCESS_SET_INFORMATION
  end

  if (perms & PROCESS_EXECUTE)
    real_perms |= PROCESS_TERMINATE | PROCESS_CREATE_THREAD | PROCESS_CREATE_PROCESS | PROCESS_SUSPEND_RESUME
  end

  return _open(pid, real_perms)
end
processes() click to toggle source

An alias for get_processes.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb, line 253
def Process.processes
  self.get_processes
end

Public Instance Methods

close(handle = self.handle) click to toggle source

Instance method

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb, line 323
def close(handle = self.handle)
  unless self.pid.nil?
    ObjectSpace.undefine_finalizer(self)
    self.class.close(self.client, handle)
    self.pid = nil
  end
end
name() click to toggle source

Returns the executable name of the process.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb, line 298
def name
  return get_info()['name']
end
path() click to toggle source

Returns the path to the process' executable.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb, line 305
def path
  return get_info()['path']
end
wait( timeout = -1 ) click to toggle source

Block until this process terminates on the remote side. By default we choose not to allow a packet responce timeout to occur as we may be waiting indefinatly for the process to terminate.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb, line 336
def wait( timeout = -1 )
  request = Packet.create_request('stdapi_sys_process_wait')

  request.add_tlv(TLV_TYPE_HANDLE, self.handle)

  response = self.client.send_request(request, timeout)

  self.handle = nil

  return true
end

Protected Instance Methods

get_info() click to toggle source

Gathers information about the process and returns a hash.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb, line 355
def get_info
  request = Packet.create_request('stdapi_sys_process_get_info')
  info    = {}

  request.add_tlv(TLV_TYPE_HANDLE, handle)

  # Send the request
  response = client.send_request(request)

  # Populate the hash
  info['name'] = client.unicode_filter_encode( response.get_tlv_value(TLV_TYPE_PROCESS_NAME) )
  info['path'] = client.unicode_filter_encode( response.get_tlv_value(TLV_TYPE_PROCESS_PATH) )

  return info
end