def collect(self): pool_offset = None pool_header = self.SearchForPoolHeader( self.plugin_args.offset, search=self.plugin_args.search) if pool_header: name = (pool_header.m("ProcessBilled").name or utils.encode_string(pool_header.Tag)) yield dict(divider=("{0:#x} is inside pool allocation with " "tag '{1}' ({2:#x}) and size {3:#x}".format( self.plugin_args.offset, name, pool_header, pool_header.size))) for relative_offset, info in self.GuessMembers( self.plugin_args.offset, size=self.plugin_args.size, search=self.plugin_args.search): if pool_header: pool_offset = (self.plugin_args.offset + relative_offset - pool_header.obj_offset) yield dict(offset=relative_offset, pool_offset=pool_offset, content=" ".join( [utils.encode_string(x) for x in info]))
def _TestProfile(self, address_space, image_base, profile, symbols, minimal_match=1): """Match _all_ the symbols against this data.""" count_matched = 0 count_unmatched = 0 for offset, possible_values in symbols: # The possible_values can be a single string which means there is # only one option. If it is a list, then any of the symbols may # match at this offset to be considered a match. if isinstance(possible_values, basestring): possible_values = [possible_values] # If the offset is not mapped in we can not compare it. Skip it. offset_to_check = image_base + offset if address_space.vtop(offset_to_check) == None: continue match = self._TestSymbols( address_space=address_space, offset=offset_to_check, possible_values=possible_values) if match: self.session.report_progress( "%s matched offset %#x+%#x=%#x (%s)", profile, offset, image_base, offset+image_base, utils.encode_string (match)) count_matched += 1 else: # FIXME: We get here if the comparison point does not match - # does it make sense to allow some points to not match? Should # we consider these a failure to match? count_unmatched += 1 # Require at least this many comparison points to be matched. if count_matched < minimal_match: return 0 if count_matched > 0: self.session.report_progress( "%s matches %d/%d comparison points", profile, count_matched, count_matched + count_unmatched) return float(count_matched) / (count_matched + count_unmatched) return 0
def GuessMembers(self, offset, size=0x100, search=0x100): offset = int(offset) resolver = self.session.address_resolver result = [] for member in self.session.profile.Array(offset, target="Pointer", count=old_div(size,8)): address_info = ["Data:%#x" % member.v()] relative_offset = member.obj_offset - offset result.append((relative_offset, address_info)) # Try to find pointers to known pool allocations. pool = self.SearchForPoolHeader(member.v(), search=search) if pool: address_info.append("Tag:%s" % utils.encode_string(pool.Tag)) proc = pool.m("ProcessBilled") # Does the tag refer to a real _EPROCESS? If so it must have a # valid environment block (and a corresponding address space). if proc.Peb: address_info.append("ProcessBilled:%s" % proc.name) address_info.append("@ %#x (%#x)" % (member.v(), pool.size)) else: # Look for pointers to global symbols. sym_offset, symbol = resolver.get_nearest_constant_by_address( member.v()) if symbol and sym_offset == member.v(): address_info.append("Const:%s" % ", ".join(symbol)) # Check for _LIST_ENTRYs list_member = member.cast("_LIST_ENTRY") if list_member.obj_offset == list_member.Flink.Blink.v(): address_info.append("_LIST_ENTRY") address_info.append("@ %#x" % list_member.Flink.v()) if list_member.obj_offset == list_member.Flink.v(): address_info.append("Empty") return result
def __repr__(self): return " [{0}:{1}]: '{2}'".format(self.obj_type, self.obj_name, utils.encode_string(self.v()))
def __str__(self): return utils.encode_string(self.__bytes__())