class Rex::Post::Meterpreter::Extensions::Stdapi::Sys::ProcessSubsystem::Memory

Provides an interface to allocate, free, read, write, query, protect, lock, and unlock memory in the context of a given process.

Public Class Methods

new(process) click to toggle source

Initializes a memory modification instance with the supplied process instance.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb, line 49
def initialize(process)
  self.process = process
end

Public Instance Methods

_allocate(base, length, allocation_type, protection) click to toggle source

Low-level memory allocation.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb, line 78
def _allocate(base, length, allocation_type, protection)
  request = Packet.create_request('stdapi_sys_process_memory_allocate')

  # Populate the request
  if (base != nil)
    request.add_tlv(TLV_TYPE_BASE_ADDRESS, base)
  end

  request.add_tlv(TLV_TYPE_HANDLE, process.handle)
  request.add_tlv(TLV_TYPE_LENGTH, length)
  request.add_tlv(TLV_TYPE_ALLOCATION_TYPE, allocation_type)
  request.add_tlv(TLV_TYPE_PROTECTION, protection)

  # Transmit the request
  response = process.client.send_request(request);

  return response.get_tlv_value(TLV_TYPE_BASE_ADDRESS)
end
_free(base, length) click to toggle source

Low-level memory deallocation.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb, line 107
def _free(base, length)
  request = Packet.create_request('stdapi_sys_process_memory_free')

  request.add_tlv(TLV_TYPE_HANDLE, process.handle)
  request.add_tlv(TLV_TYPE_BASE_ADDRESS, base)
  request.add_tlv(TLV_TYPE_LENGTH, length)

  response = process.client.send_request(request)

  return true
end
allocate(length, protection = nil, base = nil) click to toggle source

Allocate storage of the supplied length and returns the address at which the memory was allocated.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb, line 57
def allocate(length, protection = nil, base = nil)
  allocation_type = MEM_COMMIT

  # If no protection was supplied, default to the most flexible
  if (protection == nil)
    protection = PAGE_EXECUTE_READWRITE
  else
    protection = gen_prot_to_specific(protection)
  end

  # If the preferred base is non-nil, set the reserve flag
  if (base != nil)
    allocation_type |= MEM_RESERVE
  end

  return _allocate(base, length, allocation_type, protection)
end
free(base, length = 0) click to toggle source

Deallocate a region of memory in the context of a process.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb, line 100
def free(base, length = 0)
  return _free(base, length)
end
lock(base, length) click to toggle source

Lock a region of memory into physical memory so that it can't be swapped to disk. This can only be done in the context of the process that is running the meterpreter server. The instance's handle is ignored.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb, line 232
def lock(base, length)
  request = Packet.create_request('stdapi_sys_process_memory_lock')

  request.add_tlv(TLV_TYPE_BASE_ADDRESS, base)
  request.add_tlv(TLV_TYPE_LENGTH, length)

  response = process.client.send_request(request)

  return true
end
protect(base, length = nil, protection = nil) click to toggle source

Change the protection masks on the region supplied in base.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb, line 200
def protect(base, length = nil, protection = nil)
  request = Packet.create_request('stdapi_sys_process_memory_protect')

  if (length == nil)
    length = 4096
  end

  # If no protection was supplied, default to the most flexible
  if (protection == nil)
    protection = PAGE_EXECUTE_READWRITE
  else
    protection = gen_prot_to_specific(protection)
  end

  request.add_tlv(TLV_TYPE_HANDLE, process.handle)
  request.add_tlv(TLV_TYPE_BASE_ADDRESS, base)
  request.add_tlv(TLV_TYPE_LENGTH, length)
  request.add_tlv(TLV_TYPE_PROTECTION, protection)

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

  # Return the old protection to the caller
  return specific_prot_to_gen(response.get_tlv_value(TLV_TYPE_PROTECTION))
end
query(base) click to toggle source

Queries an address for information about its state.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb, line 153
def query(base)
  request = Packet.create_request('stdapi_sys_process_memory_query')

  request.add_tlv(TLV_TYPE_HANDLE, process.handle)
  request.add_tlv(TLV_TYPE_BASE_ADDRESS, base)

  response = process.client.send_request(request)

  # Build out the hash from the response information
  info = {}

  info['BaseAddress']       = response.get_tlv_value(TLV_TYPE_BASE_ADDRESS)
  info['AllocationBase']    = response.get_tlv_value(TLV_TYPE_ALLOC_BASE_ADDRESS)
  info['AllocationProtect'] = specific_prot_to_gen(response.get_tlv_value(TLV_TYPE_ALLOC_PROTECTION))
  info['RegionSize']        = response.get_tlv_value(TLV_TYPE_LENGTH)

  # Translate the memory state
  state = response.get_tlv_value(TLV_TYPE_MEMORY_STATE)

  if (state == MEM_FREE)
    info['Available'] = true
  elsif (state == MEM_COMMIT)
    info['Available'] = false
  elsif (state == MEM_RESERVE)
    info['Reserved'] = true
  end

  # Translate the region protections
  info['Protect'] = specific_prot_to_gen(response.get_tlv_value(TLV_TYPE_PROTECTION))

  # Translate the memory type
  type = response.get_tlv_value(TLV_TYPE_MEMORY_TYPE)

  if (type == MEM_IMAGE)
    info['ImageMapping'] = true
  elsif (type == MEM_MAPPED)
    info['MemoryMapping'] = true
  elsif (type == MEM_PRIVATE)
    info['PrivateMapping'] = true
  end

  return info
end
read(base, length) click to toggle source

Read memory from the context of a process and return the buffer.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb, line 122
def read(base, length)
  request = Packet.create_request('stdapi_sys_process_memory_read')

  request.add_tlv(TLV_TYPE_HANDLE, process.handle)
  request.add_tlv(TLV_TYPE_BASE_ADDRESS, base)
  request.add_tlv(TLV_TYPE_LENGTH, length)

  response = process.client.send_request(request)

  return response.get_tlv_value(TLV_TYPE_PROCESS_MEMORY)
end
readable?(base) click to toggle source

Check to see if an address is readable.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb, line 270
def readable?(base)
  info = nil

  begin
    info = query(base)
  rescue
  end

  if ((info != nil) &&
      (info['Available'] == false) &&
      (info['Protect'] & PROT_READ == PROT_READ))
    return true
  end

  return false
end
unlock(base, length) click to toggle source

Unloock a region of memory into physical memory so that it can be swapped to disk. This can only be done in the context of the process that is running the meterpreter server. The instance's handle is ignored.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb, line 249
def unlock(base, length)
  request = Packet.create_request('stdapi_sys_process_memory_unlock')

  request.add_tlv(TLV_TYPE_BASE_ADDRESS, base)
  request.add_tlv(TLV_TYPE_LENGTH, length)

  response = process.client.send_request(request)

  return true
end
writable?(base) click to toggle source

Check to see if an address is writable.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb, line 290
def writable?(base)
  info = nil

  begin
    info = query(base)
  rescue
  end

  if ((info != nil) &&
      (info['Available'] == false) &&
      (info['Protect'] & PROT_WRITE == PROT_WRITE))
    return true
  end

  return false
end
write(base, data) click to toggle source

Write memory to the context of a process and return the number of bytes actually written.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb, line 138
def write(base, data)
  request = Packet.create_request('stdapi_sys_process_memory_write')

  request.add_tlv(TLV_TYPE_HANDLE, process.handle)
  request.add_tlv(TLV_TYPE_BASE_ADDRESS, base)
  request.add_tlv(TLV_TYPE_PROCESS_MEMORY, data)

  response = process.client.send_request(request)

  return response.get_tlv_value(TLV_TYPE_LENGTH)
end

Protected Instance Methods

gen_prot_to_specific(prot) click to toggle source

Translates general protection flags to specific protection flags.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb, line 312
def gen_prot_to_specific(prot)
  if (prot == nil)
    return PAGE_READ
  end

  return @@page_protection_map[prot]
end
specific_prot_to_gen(prot) click to toggle source

Translates specific protection flags to general protection flags.

# File lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb, line 323
def specific_prot_to_gen(prot)

  if (prot == nil)
    return PAGE_READONLY
  end

  return @@page_protection_map.invert[prot]
end