mirror of
https://github.com/rapid7/metasploit-framework
synced 2024-11-05 14:57:30 +01:00
moved registry/process around to be under sys, implemented process.memory and process attaching
git-svn-id: file:///home/svn/incoming/trunk@2377 4d416f70-5f16-0410-b530-b9f4589650da
This commit is contained in:
parent
3338ebb82c
commit
f4264ed7d5
3
lib/rex/post/meterpreter.rb
Normal file
3
lib/rex/post/meterpreter.rb
Normal file
@ -0,0 +1,3 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
require 'Rex/Post/Meterpreter/Client'
|
@ -105,6 +105,9 @@ class Channel
|
||||
response = client.send_request(request)
|
||||
cid = response.get_tlv(TLV_TYPE_CHANNEL_ID).value
|
||||
|
||||
# FIXME: race condition where data could be sent to the channel
|
||||
# before it's added to the list.
|
||||
|
||||
# Create the channel instance
|
||||
channel = klass.new(client, cid, type, flags)
|
||||
|
||||
|
@ -34,6 +34,8 @@ class Stream
|
||||
# Passes the initialization information up to the base class
|
||||
def initialize(client, cid, type, flags)
|
||||
super(client, cid, type, flags)
|
||||
|
||||
initialize_abstraction
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -1,6 +1,7 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
require 'Rex/Post/Meterpreter/Channels/Stream'
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/Tlv'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
@ -24,12 +25,18 @@ class Tcp < Rex::Post::Meterpreter::Channels::Stream
|
||||
##
|
||||
|
||||
def Tcp.open(client, host, port)
|
||||
return Channel.create(client, 'net_stream_tcp',
|
||||
return Channel.create(client, 'stdapi_net_tcp_client',
|
||||
self, CHANNEL_FLAG_SYNCHRONOUS,
|
||||
[
|
||||
{ 'type' =>
|
||||
|
||||
]
|
||||
{
|
||||
'type' => TLV_TYPE_HOST_NAME,
|
||||
'value' => host
|
||||
},
|
||||
{
|
||||
'type' => TLV_TYPE_PORT,
|
||||
'value' => port
|
||||
}
|
||||
])
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -4,6 +4,7 @@ require 'socket'
|
||||
require 'Rex/Post/Meterpreter/ClientCore'
|
||||
require 'Rex/Post/Meterpreter/Channel'
|
||||
require 'Rex/Post/Meterpreter/ChannelContainer'
|
||||
require 'Rex/Post/Meterpreter/Dependencies'
|
||||
require 'Rex/Post/Meterpreter/ObjectAliases'
|
||||
require 'Rex/Post/Meterpreter/Packet'
|
||||
require 'Rex/Post/Meterpreter/PacketParser'
|
||||
@ -106,11 +107,27 @@ class Client
|
||||
self.ext_aliases.aliases[name] = ext
|
||||
end
|
||||
|
||||
# Registers zero or more aliases that are provided in an array
|
||||
def register_extension_aliases(aliases)
|
||||
aliases.each { |a|
|
||||
register_extension_alias(a['name'], a['ext'])
|
||||
}
|
||||
end
|
||||
|
||||
# Deregisters a previously registered extension alias
|
||||
def deregister_extension_alias(name)
|
||||
self.ext_aliases.aliases.delete(name)
|
||||
end
|
||||
|
||||
# Dumps the extension tree
|
||||
def dump_extension_tree()
|
||||
items = []
|
||||
items.concat(self.ext.dump_alias_tree('client.ext'))
|
||||
items.concat(self.ext_aliases.dump_alias_tree('client'))
|
||||
|
||||
return items.sort
|
||||
end
|
||||
|
||||
attr_reader :ext
|
||||
protected
|
||||
attr_accessor :sock, :parser, :ext_aliases
|
||||
|
@ -81,7 +81,7 @@ class ClientCore < Extension
|
||||
|
||||
# If we must upload the library, do so now
|
||||
if ((load_flags & LOAD_LIBRARY_FLAG_LOCAL) != LOAD_LIBRARY_FLAG_LOCAL)
|
||||
image = IO.readlines(library_path).join
|
||||
image = ::IO.readlines(library_path).join
|
||||
|
||||
if (image != nil)
|
||||
request.add_tlv(TLV_TYPE_DATA, image)
|
||||
|
3
lib/rex/post/meterpreter/dependencies.rb
Normal file
3
lib/rex/post/meterpreter/dependencies.rb
Normal file
@ -0,0 +1,3 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
require 'Rex/Post/Permission'
|
@ -1,39 +0,0 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
require 'Rex/Post/Process'
|
||||
require 'Rex/Post/Meterpreter/Packet'
|
||||
require 'Rex/Post/Meterpreter/Client'
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/Stdapi'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Extensions
|
||||
module Stdapi
|
||||
|
||||
##
|
||||
#
|
||||
# Process
|
||||
# -------
|
||||
#
|
||||
# This class implements the Rex::Post::Process interface.
|
||||
#
|
||||
##
|
||||
class Process < Rex::Post::Process
|
||||
|
||||
class <<self
|
||||
attr_accessor :client
|
||||
end
|
||||
|
||||
# Gets the process id that the remote side is executing under
|
||||
def Process.getpid
|
||||
request = Packet.create_request('stdapi_process_getpid')
|
||||
|
||||
response = client.send_request(request)
|
||||
|
||||
return response.get_tlv_value(TLV_TYPE_PID)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end; end; end; end; end
|
@ -2,8 +2,11 @@
|
||||
|
||||
###
|
||||
#
|
||||
# Windows Specific Constants
|
||||
# --------------------------
|
||||
#
|
||||
# These are put into the global namespace for now
|
||||
# so that they can be referenced globally
|
||||
# so that they can be referenced globally.
|
||||
#
|
||||
###
|
||||
|
||||
@ -29,6 +32,42 @@ GENERIC_WRITE = 0x40000000
|
||||
GENERIC_EXECUTE = 0x20000000
|
||||
GENERIC_ALL = 0x10000000
|
||||
|
||||
##
|
||||
#
|
||||
# Page Protections
|
||||
#
|
||||
##
|
||||
PAGE_NOACCESS = 0x00000001
|
||||
PAGE_READONLY = 0x00000002
|
||||
PAGE_READWRITE = 0x00000004
|
||||
PAGE_WRITECOPY = 0x00000008
|
||||
PAGE_EXECUTE = 0x00000010
|
||||
PAGE_EXECUTE_READ = 0x00000020
|
||||
PAGE_EXECUTE_READWRITE = 0x00000040
|
||||
PAGE_EXECUTE_WRITECOPY = 0x00000080
|
||||
PAGE_GUARD = 0x00000100
|
||||
PAGE_NOCACHE = 0x00000200
|
||||
PAGE_WRITECOMBINE = 0x00000400
|
||||
MEM_COMMIT = 0x00001000
|
||||
MEM_RESERVE = 0x00002000
|
||||
MEM_DECOMMIT = 0x00004000
|
||||
MEM_RELEASE = 0x00008000
|
||||
MEM_FREE = 0x00010000
|
||||
MEM_PRIVATE = 0x00020000
|
||||
MEM_MAPPED = 0x00040000
|
||||
MEM_RESET = 0x00080000
|
||||
MEM_TOP_DOWN = 0x00100000
|
||||
MEM_WRITE_WATCH = 0x00200000
|
||||
MEM_PHYSICAL = 0x00400000
|
||||
MEM_LARGE_PAGES = 0x20000000
|
||||
MEM_4MB_PAGES = 0x80000000
|
||||
SEC_FILE = 0x00800000
|
||||
SEC_IMAGE = 0x01000000
|
||||
SEC_RESERVE = 0x04000000
|
||||
SEC_COMMIT = 0x08000000
|
||||
SEC_NOCACHE = 0x10000000
|
||||
MEM_IMAGE = SEC_IMAGE
|
||||
|
||||
##
|
||||
#
|
||||
# Registry Permissions
|
||||
@ -72,3 +111,22 @@ REG_DWORD_LITTLE_ENDIAN = 4
|
||||
REG_DWORD_BIG_ENDIAN = 5
|
||||
REG_LINK = 6
|
||||
REG_MULTI_SZ = 7
|
||||
|
||||
##
|
||||
#
|
||||
# Process Permissions
|
||||
#
|
||||
##
|
||||
PROCESS_TERMINATE = 0x00000001
|
||||
PROCESS_CREATE_THREAD = 0x00000002
|
||||
PROCESS_SET_SESSIONID = 0x00000004
|
||||
PROCESS_VM_OPERATION = 0x00000008
|
||||
PROCESS_VM_READ = 0x00000010
|
||||
PROCESS_VM_WRITE = 0x00000020
|
||||
PROCESS_DUP_HANDLE = 0x00000040
|
||||
PROCESS_CREATE_PROCESS = 0x00000080
|
||||
PROCESS_SET_QUOTA = 0x00000100
|
||||
PROCESS_SET_INFORMATION = 0x00000200
|
||||
PROCESS_QUERY_INFORMATION= 0x00000400
|
||||
PROCESS_SUSPEND_RESUME = 0x00000800
|
||||
PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF
|
||||
|
@ -1,12 +1,14 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
require 'Rex/Post/Meterpreter/ObjectAliases'
|
||||
require 'Rex/Post/Meterpreter/Extension'
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/Constants'
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/Tlv'
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/Dir'
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/File'
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/FileStat'
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/Process'
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/Registry'
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/Sys/Process'
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/Sys/Registry'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
@ -28,11 +30,26 @@ class Stdapi < Extension
|
||||
|
||||
# Alias the following things on the client object so that they
|
||||
# can be directly referenced
|
||||
client.register_extension_alias('dir', self.dir)
|
||||
client.register_extension_alias('file', self.file)
|
||||
client.register_extension_alias('filestat', self.filestat)
|
||||
client.register_extension_alias('process', self.process)
|
||||
client.register_extension_alias('registry', self.registry)
|
||||
client.register_extension_aliases(
|
||||
[
|
||||
{
|
||||
'name' => 'fs',
|
||||
'ext' => ObjectAliases.new(
|
||||
{
|
||||
'dir' => self.dir,
|
||||
'file' => self.file,
|
||||
'filestat' => self.filestat
|
||||
})
|
||||
},
|
||||
{
|
||||
'name' => 'sys',
|
||||
'ext' => ObjectAliases.new(
|
||||
{
|
||||
'process' => self.process,
|
||||
'registry' => self.registry
|
||||
})
|
||||
}
|
||||
])
|
||||
end
|
||||
|
||||
# Sets the client instance on a duplicated copy of the supplied class
|
||||
@ -59,12 +76,12 @@ class Stdapi < Extension
|
||||
|
||||
# Returns a copy of the Process class
|
||||
def process
|
||||
brand(Rex::Post::Meterpreter::Extensions::Stdapi::Process)
|
||||
brand(Rex::Post::Meterpreter::Extensions::Stdapi::Sys::Process)
|
||||
end
|
||||
|
||||
# Returns a copy of the Registry class
|
||||
def registry
|
||||
brand(Rex::Post::Meterpreter::Extensions::Stdapi::Registry)
|
||||
brand(Rex::Post::Meterpreter::Extensions::Stdapi::Sys::Registry)
|
||||
end
|
||||
end
|
||||
|
||||
|
125
lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb
Normal file
125
lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb
Normal file
@ -0,0 +1,125 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
require 'Rex/Post/Process'
|
||||
require 'Rex/Post/Meterpreter/Packet'
|
||||
require 'Rex/Post/Meterpreter/Client'
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/Stdapi'
|
||||
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/Sys/ProcessSubsystem/Memory'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Extensions
|
||||
module Stdapi
|
||||
module Sys
|
||||
|
||||
##
|
||||
#
|
||||
# Process
|
||||
# -------
|
||||
#
|
||||
# This class implements the Rex::Post::Process interface.
|
||||
#
|
||||
##
|
||||
class Process < Rex::Post::Process
|
||||
|
||||
include Rex::Post::Meterpreter::ObjectAliasesContainer
|
||||
|
||||
##
|
||||
#
|
||||
# Class methods
|
||||
#
|
||||
##
|
||||
|
||||
class <<self
|
||||
attr_accessor :client
|
||||
end
|
||||
|
||||
# Attachs to the supplied process with a given set of permissions
|
||||
def Process.attach(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 _attach(pid, real_perms)
|
||||
end
|
||||
|
||||
# Low-level process attach
|
||||
def Process._attach(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(handle)
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
# Executes an application using the arguments provided
|
||||
def Process.execute(opts)
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# Gets the process id that the remote side is executing under
|
||||
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
|
||||
|
||||
|
||||
##
|
||||
#
|
||||
# Instance methods
|
||||
#
|
||||
##
|
||||
|
||||
def initialize(handle)
|
||||
self.client = self.class.client
|
||||
self.handle = handle
|
||||
|
||||
initialize_aliases(
|
||||
{
|
||||
'memory' => Rex::Post::Meterpreter::Extensions::Stdapi::Sys::ProcessSubsystem::Memory.new(self),
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
attr_reader :client, :handle
|
||||
protected
|
||||
attr_writer :client, :handle
|
||||
|
||||
end
|
||||
|
||||
end; end; end; end; end; end
|
@ -0,0 +1,292 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
require 'Rex/Post/Meterpreter/Client'
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/Constants'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Extensions
|
||||
module Stdapi
|
||||
module Sys
|
||||
module ProcessSubsystem
|
||||
|
||||
class Memory
|
||||
|
||||
# Page protection translation hash
|
||||
@@page_protection_map =
|
||||
{
|
||||
PROT_NONE => PAGE_NOACCESS,
|
||||
PROT_EXEC => PAGE_EXECUTE,
|
||||
PROT_EXEC | PROT_READ => PAGE_EXECUTE_READ,
|
||||
PROT_EXEC | PROT_READ |
|
||||
PROT_WRITE => PAGE_EXECUTE_READWRITE,
|
||||
PROT_EXEC | PROT_READ |
|
||||
PROT_WRITE | PROT_COW => PAGE_EXECUTE_WRITECOPY,
|
||||
PROT_READ => PAGE_READONLY,
|
||||
PROT_READ | PROT_WRITE => PAGE_READWRITE,
|
||||
PROT_READ | PROT_WRITE |
|
||||
PROT_COW => PAGE_WRITECOPY,
|
||||
PROT_WRITE => PAGE_READWRITE
|
||||
}
|
||||
|
||||
def initialize(process)
|
||||
self.process = process
|
||||
end
|
||||
|
||||
# Allocate storage of the supplied length and returns the
|
||||
# address at which the memory was allocated
|
||||
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
|
||||
|
||||
# Low-level memory allocation
|
||||
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
|
||||
|
||||
# Deallocate a region of memory in the context of a process
|
||||
def free(base, length = 0)
|
||||
return _free(base, length)
|
||||
end
|
||||
|
||||
# Low-level memory deallocation
|
||||
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
|
||||
|
||||
# Read memory from the context of a process and return the buffer
|
||||
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
|
||||
|
||||
# Write memory to the context of a process and return the number of bytes
|
||||
# actually written
|
||||
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
|
||||
|
||||
# Queries an address for information about its state
|
||||
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_RESERVED)
|
||||
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
|
||||
|
||||
# Change the protection masks on the region supplied in base
|
||||
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
|
||||
|
||||
# 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.
|
||||
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
|
||||
|
||||
# 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.
|
||||
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
|
||||
|
||||
|
||||
##
|
||||
#
|
||||
# Conditionals
|
||||
#
|
||||
##
|
||||
|
||||
# Check to see if an address is readable
|
||||
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
|
||||
|
||||
# Check to see if an address is writable
|
||||
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
|
||||
|
||||
protected
|
||||
|
||||
# Translates general protection flags to specific protection flags
|
||||
def gen_prot_to_specific(prot)
|
||||
if (prot == nil)
|
||||
return PAGE_READ
|
||||
end
|
||||
|
||||
return @@page_protection_map[prot]
|
||||
end
|
||||
|
||||
# Translates specific protection flags to general protection flags
|
||||
def specific_prot_to_gen(prot)
|
||||
|
||||
if (prot == nil)
|
||||
return PAGE_READONLY
|
||||
end
|
||||
|
||||
return @@page_protection_map.invert[prot]
|
||||
end
|
||||
|
||||
attr_accessor :process
|
||||
end
|
||||
|
||||
end; end; end; end; end; end; end
|
||||
|
@ -5,14 +5,15 @@ require 'Rex/Post/Meterpreter/Packet'
|
||||
require 'Rex/Post/Meterpreter/Client'
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/Constants'
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/Stdapi'
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/RegistryKey'
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/RegistryValue'
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/Sys/RegistrySubsystem/RegistryKey'
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/Sys/RegistrySubsystem/RegistryValue'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Extensions
|
||||
module Stdapi
|
||||
module Sys
|
||||
|
||||
###
|
||||
#
|
||||
@ -52,8 +53,8 @@ class Registry
|
||||
|
||||
response = client.send_request(request)
|
||||
|
||||
return RegistryKey.new(client, root_key, base_key, perm,
|
||||
response.get_tlv(TLV_TYPE_HKEY).value)
|
||||
return Rex::Post::Meterpreter::Extensions::Stdapi::Sys::RegistrySubsystem::RegistryKey.new(
|
||||
client, root_key, base_key, perm, response.get_tlv(TLV_TYPE_HKEY).value)
|
||||
end
|
||||
|
||||
# Deletes the supplied registry key.
|
||||
@ -150,7 +151,8 @@ class Registry
|
||||
data = data.unpack("N")[0]
|
||||
end
|
||||
|
||||
return RegistryValue.new(client, hkey, name, type, data)
|
||||
return Rex::Post::Meterpreter::Extensions::Stdapi::Sys::RegistrySubsystem::RegistryValue.new(
|
||||
client, hkey, name, type, data)
|
||||
end
|
||||
|
||||
# Deletes the registry value supplied in name from the supplied
|
||||
@ -179,7 +181,8 @@ class Registry
|
||||
response = client.send_request(request)
|
||||
|
||||
response.each(TLV_TYPE_VALUE_NAME) { |value_name|
|
||||
values << RegistryValue.new(client, hkey, value_name.value)
|
||||
values << Rex::Post::Meterpreter::Extensions::Stdapi::Sys::RegistrySubsystem::RegistryValue.new(
|
||||
client, hkey, value_name.value)
|
||||
}
|
||||
|
||||
return values
|
||||
@ -187,4 +190,4 @@ class Registry
|
||||
|
||||
end
|
||||
|
||||
end; end; end; end; end
|
||||
end; end; end; end; end; end
|
@ -1,13 +1,15 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/Constants'
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/Registry'
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/Sys/Registry'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Extensions
|
||||
module Stdapi
|
||||
module Sys
|
||||
module RegistrySubsystem
|
||||
|
||||
###
|
||||
#
|
||||
@ -45,13 +47,13 @@ class RegistryKey
|
||||
# Retrieves all of the registry keys that are direct descendents of
|
||||
# the class' registry key.
|
||||
def enum_key()
|
||||
return self.client.registry.enum_key(self.hkey)
|
||||
return self.client.sys.registry.enum_key(self.hkey)
|
||||
end
|
||||
|
||||
# Retrieves all of the registry values that exist within the opened
|
||||
# registry key.
|
||||
def enum_value()
|
||||
return self.client.registry.enum_value(self.hkey)
|
||||
return self.client.sys.registry.enum_value(self.hkey)
|
||||
end
|
||||
|
||||
|
||||
@ -63,24 +65,24 @@ class RegistryKey
|
||||
|
||||
# Opens a registry key that is relative to this registry key.
|
||||
def open_key(base_key, perm = KEY_READ)
|
||||
return self.client.registry.open_key(self.hkey, base_key, perm)
|
||||
return self.client.sys.registry.open_key(self.hkey, base_key, perm)
|
||||
end
|
||||
|
||||
# Creates a registry key that is relative to this registry key.
|
||||
def create_key(base_key, perm = KEY_READ)
|
||||
return self.client.registry.create_key(self.hkey, base_key, perm)
|
||||
return self.client.sys.registry.create_key(self.hkey, base_key, perm)
|
||||
end
|
||||
|
||||
# Deletes a registry key that is relative to this registry key.
|
||||
def delete_key(base_key, recursive = true)
|
||||
return self.client.registry.delete_key(self.hkey, base_key, recursive)
|
||||
return self.client.sys.registry.delete_key(self.hkey, base_key, recursive)
|
||||
end
|
||||
|
||||
# Closes the open key. This must be called if the registry
|
||||
# key was opened.
|
||||
def close()
|
||||
if (self.hkey != nil)
|
||||
return self.client.registry.close_key(hkey)
|
||||
return self.client.sys.registry.close_key(hkey)
|
||||
end
|
||||
|
||||
return false
|
||||
@ -94,13 +96,13 @@ class RegistryKey
|
||||
|
||||
# Sets a value relative to the opened registry key.
|
||||
def set_value(name, type, data)
|
||||
return self.client.registry.set_value(self.hkey, name, type, data)
|
||||
return self.client.sys.registry.set_value(self.hkey, name, type, data)
|
||||
end
|
||||
|
||||
# Queries the attributes of the supplied registry value relative to
|
||||
# the opened registry key.
|
||||
def query_value(name)
|
||||
return self.client.registry.query_value(self.hkey, name)
|
||||
return self.client.sys.registry.query_value(self.hkey, name)
|
||||
end
|
||||
|
||||
##
|
||||
@ -122,4 +124,4 @@ protected
|
||||
attr_writer :hkey, :root_key, :base_key, :perm
|
||||
end
|
||||
|
||||
end; end; end; end; end
|
||||
end; end; end; end; end; end; end
|
@ -1,13 +1,15 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/Constants'
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/Registry'
|
||||
require 'Rex/Post/Meterpreter/Extensions/Stdapi/Sys/Registry'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Extensions
|
||||
module Stdapi
|
||||
module Sys
|
||||
module RegistrySubsystem
|
||||
|
||||
###
|
||||
#
|
||||
@ -31,7 +33,7 @@ class RegistryValue
|
||||
if (type == nil)
|
||||
type = self.type
|
||||
end
|
||||
if (self.client.registry.set_value(self.hkey, self.name,
|
||||
if (self.client.sys.registry.set_value(self.hkey, self.name,
|
||||
type, data))
|
||||
self.data = data
|
||||
self.type = type
|
||||
@ -44,7 +46,7 @@ class RegistryValue
|
||||
|
||||
# Queries the value's data.
|
||||
def query()
|
||||
val = self.client.registry.query_value(self.hkey, self.name)
|
||||
val = self.client.sys.registry.query_value(self.hkey, self.name)
|
||||
|
||||
if (val != nil)
|
||||
self.data = val.data
|
||||
@ -56,7 +58,7 @@ class RegistryValue
|
||||
|
||||
# Deletes the value.
|
||||
def delete()
|
||||
return self.client.registry.delete_value(self.hkey, self.name)
|
||||
return self.client.sys.registry.delete_value(self.hkey, self.name)
|
||||
end
|
||||
|
||||
attr_reader :hkey, :name, :type, :data
|
||||
@ -65,4 +67,4 @@ protected
|
||||
attr_writer :hkey, :name, :type, :data
|
||||
end
|
||||
|
||||
end; end; end; end; end
|
||||
end; end; end; end; end; end; end
|
@ -6,26 +6,59 @@ module Meterpreter
|
||||
module Extensions
|
||||
module Stdapi
|
||||
|
||||
# Process
|
||||
TLV_TYPE_PID = TLV_META_TYPE_UINT | 0
|
||||
##
|
||||
#
|
||||
# General
|
||||
#
|
||||
##
|
||||
|
||||
TLV_TYPE_HANDLE = TLV_META_TYPE_UINT | 600
|
||||
TLV_TYPE_INHERIT = TLV_META_TYPE_BOOL | 601
|
||||
|
||||
##
|
||||
#
|
||||
# Sys
|
||||
#
|
||||
##
|
||||
|
||||
# Registry
|
||||
TLV_TYPE_HKEY = TLV_META_TYPE_UINT | 1000
|
||||
TLV_TYPE_ROOT_KEY = TLV_TYPE_HKEY
|
||||
TLV_TYPE_BASE_KEY = TLV_META_TYPE_STRING | 1001
|
||||
TLV_TYPE_PERMISSION = TLV_META_TYPE_UINT | 1002
|
||||
TLV_TYPE_KEY_NAME = TLV_META_TYPE_STRING | 1003
|
||||
TLV_TYPE_VALUE_NAME = TLV_META_TYPE_STRING | 1010
|
||||
TLV_TYPE_VALUE_TYPE = TLV_META_TYPE_UINT | 1011
|
||||
TLV_TYPE_VALUE_DATA = TLV_META_TYPE_RAW | 1012
|
||||
TLV_TYPE_HKEY = TLV_META_TYPE_UINT | 1000
|
||||
TLV_TYPE_ROOT_KEY = TLV_TYPE_HKEY
|
||||
TLV_TYPE_BASE_KEY = TLV_META_TYPE_STRING | 1001
|
||||
TLV_TYPE_PERMISSION = TLV_META_TYPE_UINT | 1002
|
||||
TLV_TYPE_KEY_NAME = TLV_META_TYPE_STRING | 1003
|
||||
TLV_TYPE_VALUE_NAME = TLV_META_TYPE_STRING | 1010
|
||||
TLV_TYPE_VALUE_TYPE = TLV_META_TYPE_UINT | 1011
|
||||
TLV_TYPE_VALUE_DATA = TLV_META_TYPE_RAW | 1012
|
||||
|
||||
# Process
|
||||
TLV_TYPE_BASE_ADDRESS = TLV_META_TYPE_UINT | 2000
|
||||
TLV_TYPE_ALLOCATION_TYPE = TLV_META_TYPE_UINT | 2001
|
||||
TLV_TYPE_PROTECTION = TLV_META_TYPE_UINT | 2002
|
||||
TLV_TYPE_PROCESS_PERMS = TLV_META_TYPE_UINT | 2003
|
||||
TLV_TYPE_PROCESS_MEMORY = TLV_META_TYPE_RAW | 2004
|
||||
TLV_TYPE_ALLOC_BASE_ADDRESS = TLV_META_TYPE_UINT | 2005
|
||||
TLV_TYPE_MEMORY_STATE = TLV_META_TYPE_UINT | 2006
|
||||
TLV_TYPE_MEMORY_TYPE = TLV_META_TYPE_UINT | 2007
|
||||
TLV_TYPE_ALLOC_PROTECTION = TLV_META_TYPE_UINT | 2008
|
||||
TLV_TYPE_PID = TLV_META_TYPE_UINT | 2300
|
||||
|
||||
##
|
||||
#
|
||||
# Fs
|
||||
TLV_TYPE_DIRECTORY_PATH = TLV_META_TYPE_STRING | 1200
|
||||
TLV_TYPE_FILE_NAME = TLV_META_TYPE_STRING | 1201
|
||||
TLV_TYPE_FILE_PATH = TLV_META_TYPE_STRING | 1202
|
||||
TLV_TYPE_FILE_MODE = TLV_META_TYPE_STRING | 1203
|
||||
TLV_TYPE_STAT_BUF = TLV_META_TYPE_COMPLEX | 1220
|
||||
#
|
||||
##
|
||||
|
||||
DELETE_KEY_FLAG_RECURSIVE = (1 << 0)
|
||||
TLV_TYPE_DIRECTORY_PATH = TLV_META_TYPE_STRING | 1200
|
||||
TLV_TYPE_FILE_NAME = TLV_META_TYPE_STRING | 1201
|
||||
TLV_TYPE_FILE_PATH = TLV_META_TYPE_STRING | 1202
|
||||
TLV_TYPE_FILE_MODE = TLV_META_TYPE_STRING | 1203
|
||||
TLV_TYPE_STAT_BUF = TLV_META_TYPE_COMPLEX | 1220
|
||||
|
||||
# Net
|
||||
TLV_TYPE_HOST_NAME = TLV_META_TYPE_STRING | 1400
|
||||
TLV_TYPE_PORT = TLV_META_TYPE_UINT | 1401
|
||||
|
||||
DELETE_KEY_FLAG_RECURSIVE = (1 << 0)
|
||||
|
||||
end; end; end; end; end
|
||||
|
@ -4,6 +4,54 @@ module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
|
||||
###
|
||||
#
|
||||
# ObjectAliasesContainer
|
||||
# ----------------------
|
||||
#
|
||||
# Mixin for classes that wish to have object aliases but do not
|
||||
# really need to inherit from the ObjectAliases class.
|
||||
#
|
||||
###
|
||||
module ObjectAliasesContainer
|
||||
|
||||
# Initialize the instance's aliases
|
||||
def initialize_aliases(aliases = {})
|
||||
self.aliases = aliases
|
||||
end
|
||||
|
||||
# Pass-thru aliases
|
||||
def method_missing(symbol, *args)
|
||||
return self.aliases[symbol.to_s];
|
||||
end
|
||||
|
||||
# Recursively dumps all of the aliases registered with a class that
|
||||
# is kind_of? ObjectAliases
|
||||
def dump_alias_tree(parent_path, current = nil)
|
||||
items = []
|
||||
|
||||
if (current == nil)
|
||||
current = self
|
||||
end
|
||||
|
||||
# If the current object may have object aliases...
|
||||
if (current.kind_of?(Rex::Post::Meterpreter::ObjectAliases))
|
||||
current.aliases.each_key { |x|
|
||||
current_path = parent_path + '.' + x
|
||||
|
||||
items << current_path
|
||||
|
||||
items.concat(dump_alias_tree(current_path,
|
||||
current.aliases[x]))
|
||||
}
|
||||
end
|
||||
|
||||
return items
|
||||
end
|
||||
|
||||
attr_accessor :aliases
|
||||
end
|
||||
|
||||
###
|
||||
#
|
||||
# ObjectAliases
|
||||
@ -14,17 +62,19 @@ module Meterpreter
|
||||
#
|
||||
###
|
||||
class ObjectAliases
|
||||
|
||||
def initialize()
|
||||
self.aliases = {}
|
||||
include Rex::Post::Meterpreter::ObjectAliasesContainer
|
||||
|
||||
##
|
||||
#
|
||||
# Constructor
|
||||
#
|
||||
##
|
||||
|
||||
# An instance
|
||||
def initialize(aliases = {})
|
||||
initialize_aliases(aliases)
|
||||
end
|
||||
|
||||
# Pass-thru aliases
|
||||
def method_missing(symbol, *args)
|
||||
return self.aliases[symbol.to_s];
|
||||
end
|
||||
|
||||
attr_accessor :aliases
|
||||
end
|
||||
|
||||
|
||||
end; end; end
|
||||
|
@ -165,7 +165,7 @@ class Tlv
|
||||
self.value = false
|
||||
end
|
||||
else
|
||||
self.value = raw[8..-1]
|
||||
self.value = raw[8..length-1]
|
||||
end
|
||||
|
||||
return length;
|
||||
|
20
lib/rex/post/permission.rb
Normal file
20
lib/rex/post/permission.rb
Normal file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
# Generic page protection flags
|
||||
PROT_NONE = 0
|
||||
PROT_READ = (1 << 0)
|
||||
PROT_WRITE = (1 << 1)
|
||||
PROT_EXEC = (1 << 2)
|
||||
PROT_COW = (1 << 20)
|
||||
|
||||
# Generic permissions
|
||||
GEN_NONE = 0
|
||||
GEN_READ = (1 << 0)
|
||||
GEN_WRITE = (1 << 1)
|
||||
GEN_EXEC = (1 << 2)
|
||||
|
||||
# Generic process attach permissions
|
||||
PROCESS_READ = (1 << 0)
|
||||
PROCESS_WRITE = (1 << 1)
|
||||
PROCESS_EXECUTE = (1 << 2)
|
||||
PROCESS_ALL = 0xffffffff
|
@ -5,8 +5,6 @@ module Post
|
||||
|
||||
class Process
|
||||
|
||||
private_class_method :new
|
||||
|
||||
def Process.getresuid
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user