def dump_memory(self): """Dump process memory. @return: operation status. """ if not self.pid: log.warning("No valid pid specified, memory dump aborted") return False if not self.is_alive(): log.warning("The process with pid %d is not alive, memory " "dump aborted", self.pid) return False self.get_system_info() page_size = self.system_info.dwPageSize min_addr = self.system_info.lpMinimumApplicationAddress max_addr = self.system_info.lpMaximumApplicationAddress mem = min_addr root = os.path.join(PATHS["memory"], str(int(time.time()))) if not os.path.exists(root): os.makedirs(root) # Now upload to host from the StringIO. nf = NetlogFile(os.path.join("memory", "%s.dmp" % str(self.pid))) process_handle = self.open_process() while mem < max_addr: mbi = MEMORY_BASIC_INFORMATION() count = c_ulong(0) if KERNEL32.VirtualQueryEx(process_handle, mem, byref(mbi), sizeof(mbi)) < sizeof(mbi): mem += page_size continue if mbi.State & MEM_COMMIT and \ mbi.Type & (MEM_IMAGE | MEM_MAPPED | MEM_PRIVATE): buf = create_string_buffer(mbi.RegionSize) if KERNEL32.ReadProcessMemory(process_handle, mem, buf, mbi.RegionSize, byref(count)): nf.sock.sendall(buf.raw) mem += mbi.RegionSize else: mem += page_size KERNEL32.CloseHandle(process_handle) nf.close() log.info("Memory dump of process with pid %d completed", self.pid) return True
def dump_memory_block(self, addr, length): """Dump process memory. @return: operation status. """ if not self.pid: log.warning("No valid pid specified, memory dump aborted") return False if not self.is_alive(): log.warning( "The process with pid %d is not alive, memory " "dump aborted", self.pid) return False self.get_system_info() page_size = self.system_info.dwPageSize if length < page_size: length = page_size # Now upload to host from the StringIO. idx = self.dumpmem[self.pid] = self.dumpmem.get(self.pid, 0) + 1 file_name = os.path.join( "memory", "block-%s-%s-%s.dmp" % (self.pid, hex(addr), idx)) process_handle = self.open_process() mbi = MEMORY_BASIC_INFORMATION() if KERNEL32.VirtualQueryEx(process_handle, addr, byref(mbi), sizeof(mbi)) == 0: log.warning("Couldn't obtain MEM_BASIC_INFO for pid %d address %s", self.pid, hex(addr)) return False # override request with the full mem region attributes addr = mbi.BaseAddress length = mbi.RegionSize count = c_ulong(0) try: buf = create_string_buffer(length) if KERNEL32.ReadProcessMemory(process_handle, addr, buf, length, byref(count)): header = struct.pack("QIIII", addr, length, mbi.State, mbi.Type, mbi.Protect) nf = NetlogFile() nf.init(file_name) nf.sock.sendall(header) nf.sock.sendall(buf.raw) nf.close() else: log.warning( "ReadProcessMemory failed on process_handle %r addr %s length %s", process_handle, hex(addr), hex(length)) except: log.exception( "ReadProcessMemory exception on process_handle %r addr %s length %s", process_handle, hex(addr), hex(length)) KERNEL32.CloseHandle(process_handle) log.info( "Memory block dump of process with pid %d, addr %s, length %s completed", self.pid, hex(addr), hex(length)) return True