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.
-
#search(needles, min_search_len = 5, match_len = 500) ⇒ Object
Search memory for supplied regexes and return matches.
-
#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:
362 363 364 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 362 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.
342 343 344 345 346 347 348 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 342 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.
262 263 264 265 266 267 268 269 270 271 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 262 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.
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 230 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.
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 183 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.
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 300 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 |
#search(needles, min_search_len = 5, match_len = 500) ⇒ Object
Search memory for supplied regexes and return matches
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 138 def search(needles, min_search_len = 5, match_len = 500) request = Packet.create_request(COMMAND_ID_STDAPI_SYS_PROCESS_MEMORY_SEARCH) request.add_tlv(TLV_TYPE_PID, process.pid) needles.each { | needle | request.add_tlv(TLV_TYPE_MEMORY_SEARCH_NEEDLE, needle) } request.add_tlv(TLV_TYPE_MEMORY_SEARCH_MATCH_LEN, match_len) request.add_tlv(TLV_TYPE_UINT, min_search_len) response = process.client.send_request(request) matches = [] if response.result == 0 response.each(TLV_TYPE_MEMORY_SEARCH_RESULTS) do |res| match_data = {} match_data['match_str'] = res.get_tlv_value(TLV_TYPE_MEMORY_SEARCH_MATCH_STR) match_data['match_offset'] = res.get_tlv_value(TLV_TYPE_MEMORY_SEARCH_MATCH_ADDR) match_data['sect_start'] = res.get_tlv_value(TLV_TYPE_MEMORY_SEARCH_START_ADDR) match_data['sect_len'] = res.get_tlv_value(TLV_TYPE_MEMORY_SEARCH_SECT_LEN) matches << match_data end end matches end |
#specific_prot_to_gen(prot) ⇒ Object (protected)
Translates specific protection flags to general protection flags.
353 354 355 356 357 358 359 360 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 353 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.
279 280 281 282 283 284 285 286 287 288 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 279 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.
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 320 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.
168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb', line 168 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 |