Class: Rex::Post::Meterpreter::Extensions::Stdapi::Sys::ProcessSubsystem::Memory
- Inherits:
-
Object
- Object
- Rex::Post::Meterpreter::Extensions::Stdapi::Sys::ProcessSubsystem::Memory
- Defined in:
- lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb
Overview
Provides an interface to allocate, free, read, write, query, protect, lock, and unlock memory in the context of a given process.
Constant Summary collapse
- @@page_protection_map =
Page protection translation hash
{ 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 }
Instance Attribute Summary collapse
-
#process ⇒ Object
protected
:nodoc:.
Instance Method Summary collapse
-
#_allocate(base, length, allocation_type, protection) ⇒ Object
Low-level memory allocation.
-
#_free(base) ⇒ Object
Low-level memory deallocation.
-
#allocate(length, protection = nil, base = nil) ⇒ Object
Allocate storage of the supplied length and returns the address at which the memory was allocated.
-
#free(base) ⇒ Object
Deallocate a region of memory in the context of a process.
-
#gen_prot_to_specific(prot) ⇒ Object
protected
Translates general protection flags to specific protection flags.
-
#initialize(process) ⇒ Memory
constructor
Initializes a memory modification instance with the supplied process instance.
-
#lock(base, length) ⇒ Object
Lock a region of memory into physical memory so that it can’t be swapped to disk.
-
#protect(base, length = nil, protection = nil) ⇒ Object
Change the protection masks on the region supplied in base.
-
#query(base) ⇒ Object
Queries an address for information about its state.
-
#read(base, length) ⇒ Object
Read memory from the context of a process and return the buffer.
-
#readable?(base) ⇒ Boolean
Check to see if an address is readable.
-
#specific_prot_to_gen(prot) ⇒ Object
protected
Translates specific protection flags to general protection flags.
-
#unlock(base, length) ⇒ Object
Unlock a region of memory into physical memory so that it can be swapped to disk.
-
#writable?(base) ⇒ Boolean
Check to see if an address is writable.
-
#write(base, data) ⇒ Object
Write memory to the context of a process and return the number of bytes actually written.
Constructor Details
#initialize(process) ⇒ Memory
Initializes a memory modification instance with the supplied process instance.
51 52 53 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 51 def initialize(process) self.process = process end |
Instance Attribute Details
#process ⇒ Object (protected)
:nodoc:
333 334 335 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 333 def process @process end |
Instance Method Details
#_allocate(base, length, allocation_type, protection) ⇒ Object
Low-level memory allocation.
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 80 def _allocate(base, length, allocation_type, protection) request = Packet.create_request(COMMAND_ID_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) ⇒ Object
Low-level memory deallocation.
109 110 111 112 113 114 115 116 117 118 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 109 def _free(base) request = Packet.create_request(COMMAND_ID_STDAPI_SYS_PROCESS_MEMORY_FREE) request.add_tlv(TLV_TYPE_HANDLE, process.handle) request.add_tlv(TLV_TYPE_BASE_ADDRESS, base) process.client.send_request(request) return true end |
#allocate(length, protection = nil, base = nil) ⇒ Object
Allocate storage of the supplied length and returns the address at which the memory was allocated.
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 59 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) ⇒ Object
Deallocate a region of memory in the context of a process.
102 103 104 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 102 def free(base) return _free(base) end |
#gen_prot_to_specific(prot) ⇒ Object (protected)
Translates general protection flags to specific protection flags.
313 314 315 316 317 318 319 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 313 def gen_prot_to_specific(prot) if (prot == nil) return PAGE_READ end return @@page_protection_map[prot] end |
#lock(base, length) ⇒ Object
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.
233 234 235 236 237 238 239 240 241 242 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 233 def lock(base, length) request = Packet.create_request(COMMAND_ID_STDAPI_SYS_PROCESS_MEMORY_LOCK) request.add_tlv(TLV_TYPE_BASE_ADDRESS, base) request.add_tlv(TLV_TYPE_LENGTH, length) process.client.send_request(request) return true end |
#protect(base, length = nil, protection = nil) ⇒ Object
Change the protection masks on the region supplied in base.
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 201 def protect(base, length = nil, protection = nil) request = Packet.create_request(COMMAND_ID_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) ⇒ Object
Queries an address for information about its state.
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 154 def query(base) request = Packet.create_request(COMMAND_ID_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) ⇒ Object
Read memory from the context of a process and return the buffer.
123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 123 def read(base, length) request = Packet.create_request(COMMAND_ID_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) ⇒ Boolean
Check to see if an address is readable.
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 271 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 |
#specific_prot_to_gen(prot) ⇒ Object (protected)
Translates specific protection flags to general protection flags.
324 325 326 327 328 329 330 331 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 324 def specific_prot_to_gen(prot) if (prot == nil) return PAGE_READONLY end return @@page_protection_map.invert[prot] end |
#unlock(base, length) ⇒ Object
Unlock 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.
250 251 252 253 254 255 256 257 258 259 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 250 def unlock(base, length) request = Packet.create_request(COMMAND_ID_STDAPI_SYS_PROCESS_MEMORY_UNLOCK) request.add_tlv(TLV_TYPE_BASE_ADDRESS, base) request.add_tlv(TLV_TYPE_LENGTH, length) process.client.send_request(request) return true end |
#writable?(base) ⇒ Boolean
Check to see if an address is writable.
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 291 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) ⇒ Object
Write memory to the context of a process and return the number of bytes actually written.
139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 139 def write(base, data) request = Packet.create_request(COMMAND_ID_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 |