def readProcessMappings(process): """ Read all memory mappings of the specified process. Return a list of MemoryMapping objects, or empty list if it's not possible to read the mappings. May raise a ProcessError. """ maps = [] if not HAS_PROC: return maps try: mapsfile = openProc(process.pid) except ProcError as err: raise ProcessError(process, "Unable to read process maps: %s" % err) before = None # save the current ctypes module. mappings = Mappings(None) # FIXME Debug, but probably useless now that ctypes is in config if True: import ctypes before = ctypes try: for line in mapsfile: line = line.rstrip() match = PROC_MAP_REGEX.match(line) if not match: raise ProcessError( process, "Unable to parse memory mapping: %r" % line) log.debug('readProcessMappings %s' % (str(match.groups()))) _map = ProcessMemoryMapping( # cfg, process, int(match.group(1), 16), int(match.group(2), 16), match.group(3), int(match.group(4), 16), int(match.group(5), 16), int(match.group(6), 16), int(match.group(7)), match.group(8)) mappings.append(_map) finally: if isinstance(mapsfile, file): mapsfile.close() # reposition the previous ctypes module. if True: ctypes = types.set_ctypes(before) return mappings
def _make_mmap_with_values(self, intervals, struct_offset=None): """Make a memory map, with a fake structure of pointer pattern inside. Return the pattern signature""" # template of a memory map metadata self._mstart = 0x0C00000 self._mlength = 4096 # end at (0x0c01000) # could be 8, it doesn't really matter self.word_size = self.config.get_word_size() if struct_offset is not None: self._struct_offset = struct_offset else: self._struct_offset = self.word_size * 12 # 12, or any other aligned mmap, values = self._make_mmap(self._mstart, self._mlength, self._struct_offset, intervals, self.word_size) mappings = Mappings([mmap], "test") mappings.config = self.config mappings._reset_config() return mmap, values
def _load_memory_mappings(self): """ make the python objects""" self.mappings = Mappings(None, self.dumpname) for _start, _end, permissions, offset, devices, inode, mmap_pathname in self.metalines: start, end = int(_start, 16), int(_end, 16) offset = int(offset, 16) inode = int(inode) # rebuild filename mmap_fname = "%s-%s" % (_start, _end) # get devices nums major_device, minor_device = devices.split(':') major_device = int(major_device, 16) minor_device = int(minor_device, 16) log.debug('Loading %s - %s' % (mmap_fname, mmap_pathname)) # open the file in the archive try: mmap_content_file = self._protected_open_file( mmap_fname, mmap_pathname) except (IOError, KeyError) as e: log.debug('Ignore absent file : %s' % (e)) mmap = MemoryMapping(start, end, permissions, offset, major_device, minor_device, inode, pathname=mmap_pathname) self.mappings.append(mmap) continue # except ValueError,e: # explicit non-loading # log.debug('Ignore useless file : %s'%(e)) # mmap = MemoryMapping(start, end, permissions, offset, # major_device, minor_device, inode,pathname=mmap_pathname) # self.mappings.append(mmap) # continue except LazyLoadingException as e: mmap = FilenameBackedMemoryMapping(e._filename, start, end, permissions, offset, major_device, minor_device, inode, pathname=mmap_pathname) self.mappings.append(mmap) continue if isinstance(self.archive, zipfile.ZipFile): # ZipExtFile is lame log.warning( 'Using a local memory mapping . Zipfile sux. thx ruby.') mmap = MemoryMapping(start, end, permissions, offset, major_device, minor_device, inode, pathname=mmap_pathname) mmap = LocalMemoryMapping.fromBytebuffer( mmap, mmap_content_file.read()) # use file mmap when file is too big elif end - start > config.MAX_MAPPING_SIZE_FOR_MMAP: log.warning('Using a file backed memory mapping. no mmap in memory for this memorymap (%s).' % (mmap_pathname) + ' Search will fail. Buffer is needed.') mmap = FileBackedMemoryMapping(mmap_content_file, start, end, permissions, offset, major_device, minor_device, inode, pathname=mmap_pathname) else: log.debug('Using a MemoryDumpMemoryMapping. small size') mmap = MemoryDumpMemoryMapping(mmap_content_file, start, end, permissions, offset, major_device, minor_device, inode, pathname=mmap_pathname) self.mappings.append(mmap) self.mappings.init_config(cpu=self._cpu_bits, os_name=self._os_name) return
class ProcessMemoryDumpLoader(MemoryDumpLoader): """ Handles memory load from several recognized format.""" indexFilename = 'mappings' filePrefix = './' def _is_valid(self): """Validates if we handle the format.""" if os.path.isdir(self.dumpname): if self._test_dir(): self._open_archive = lambda archive: archive self._list_names = os.listdir self._open_file = lambda archive, name: file( os.path.sep.join([archive, name]), 'rb') return True else: raise IOError('%s is not a directory' % (self.dumpname)) return False def _test_dir(self): try: self.archive = self.dumpname members = os.listdir(self.archive) if self.indexFilename not in members: log.error('no mappings index file in the directory.') return False self.filePrefix = '' self.mmaps = [m for m in members if '-0x' in m] if len(self.mmaps) > 0: return True except OSError as e: log.info('Not a valid directory') return False def _protected_open_file(self, mmap_fname, mmap_pathname): return self._open_file(self.archive, self.filePrefix + mmap_fname) def _load_mappings(self): """Loads the mappings content from the dump to a MemoryMappings. If an underlying file containing a memory dump does not exists, still create a MemoryMap for metadata purposes. If the memory map is > config.MAX_MAPPING_SIZE_FOR_MMAP, use a slow FileBackedMemoryMapping. Else, load the mapping in memory. """ self._load_metadata() self._load_memory_mappings() # set self.mappings return def _load_metadata(self): """ Load amemory dump meta data """ mappingsFile = self._open_file(self.archive, self.indexFilename) self.metalines = [] for l in mappingsFile.readlines(): fields = l.strip().split(' ') if '' in fields: fields.remove('') self.metalines.append( (fields[0], fields[1], fields[2], fields[3], fields[4], fields[5], ' '.join( fields[ 6:]))) return def _load_memory_mappings(self): """ make the python objects""" self.mappings = Mappings(None, self.dumpname) for _start, _end, permissions, offset, devices, inode, mmap_pathname in self.metalines: start, end = int(_start, 16), int(_end, 16) offset = int(offset, 16) inode = int(inode) # rebuild filename mmap_fname = "%s-%s" % (_start, _end) # get devices nums major_device, minor_device = devices.split(':') major_device = int(major_device, 16) minor_device = int(minor_device, 16) log.debug('Loading %s - %s' % (mmap_fname, mmap_pathname)) # open the file in the archive try: mmap_content_file = self._protected_open_file( mmap_fname, mmap_pathname) except (IOError, KeyError) as e: log.debug('Ignore absent file : %s' % (e)) mmap = MemoryMapping(start, end, permissions, offset, major_device, minor_device, inode, pathname=mmap_pathname) self.mappings.append(mmap) continue # except ValueError,e: # explicit non-loading # log.debug('Ignore useless file : %s'%(e)) # mmap = MemoryMapping(start, end, permissions, offset, # major_device, minor_device, inode,pathname=mmap_pathname) # self.mappings.append(mmap) # continue except LazyLoadingException as e: mmap = FilenameBackedMemoryMapping(e._filename, start, end, permissions, offset, major_device, minor_device, inode, pathname=mmap_pathname) self.mappings.append(mmap) continue if isinstance(self.archive, zipfile.ZipFile): # ZipExtFile is lame log.warning( 'Using a local memory mapping . Zipfile sux. thx ruby.') mmap = MemoryMapping(start, end, permissions, offset, major_device, minor_device, inode, pathname=mmap_pathname) mmap = LocalMemoryMapping.fromBytebuffer( mmap, mmap_content_file.read()) # use file mmap when file is too big elif end - start > config.MAX_MAPPING_SIZE_FOR_MMAP: log.warning('Using a file backed memory mapping. no mmap in memory for this memorymap (%s).' % (mmap_pathname) + ' Search will fail. Buffer is needed.') mmap = FileBackedMemoryMapping(mmap_content_file, start, end, permissions, offset, major_device, minor_device, inode, pathname=mmap_pathname) else: log.debug('Using a MemoryDumpMemoryMapping. small size') mmap = MemoryDumpMemoryMapping(mmap_content_file, start, end, permissions, offset, major_device, minor_device, inode, pathname=mmap_pathname) self.mappings.append(mmap) self.mappings.init_config(cpu=self._cpu_bits, os_name=self._os_name) return