def get_type(self, type_name: str) -> interfaces.objects.Template: """Resolves an individual symbol.""" if constants.BANG in type_name: index = type_name.find(constants.BANG) table_name, type_name = type_name[:index], type_name[index + 1:] raise exceptions.SymbolError( type_name, table_name, "Symbol for a different table requested: {}".format( table_name + constants.BANG + type_name)) if type_name not in self._json_object['user_types']: # Fall back to the natives table if type_name in self.natives.types: return self.natives.get_type(self.name + constants.BANG + type_name) else: raise exceptions.SymbolError( type_name, self.name, "Unknown symbol: {}".format(type_name)) curdict = self._json_object['user_types'][type_name] members = {} for member_name in curdict['fields']: interdict = curdict['fields'][member_name] member = (interdict['offset'], self._interdict_to_template(interdict['type'])) members[member_name] = member object_class = self.get_type_class(type_name) if object_class == objects.AggregateType: for clazz in objects.AggregateTypes: if objects.AggregateTypes[clazz] == curdict['kind']: object_class = clazz return objects.templates.ObjectTemplate(type_name=self.name + constants.BANG + type_name, object_class=object_class, size=curdict['size'], members=members)
def _weak_resolve(self, resolve_type: SymbolType, name: str) -> SymbolSpaceReturnType: """Takes a symbol name and resolves it with ReferentialTemplates.""" if resolve_type == SymbolType.TYPE: get_function = 'get_type' elif resolve_type == SymbolType.SYMBOL: get_function = 'get_symbol' elif resolve_type == SymbolType.ENUM: get_function = 'get_enumeration' else: raise TypeError("Weak_resolve called without a proper SymbolType") name_array = name.split(constants.BANG) if len(name_array) == 2: table_name = name_array[0] component_name = name_array[1] try: return getattr(self._dict[table_name], get_function)(component_name) except KeyError as e: raise exceptions.SymbolError( component_name, table_name, 'Type {} references missing Type/Symbol/Enum: {}'.format( name, e)) raise exceptions.SymbolError(name, None, "Malformed name: {}".format(name))
def determine_map(cls, module: interfaces.context.ModuleInterface) -> \ Dict[str, List[Tuple[int, int]]]: """Returns the virtual map from a windows kernel module.""" layer = module.context.layers[module.layer_name] if not isinstance(layer, intel.Intel): raise result = {} # type: Dict[str, List[Tuple[int, int]]] try: system_va_type = module.get_enumeration('_MI_SYSTEM_VA_TYPE') large_page_size = (layer.page_size** 2) // module.get_type("_MMPTE").size except exceptions.SymbolError: raise exceptions.SymbolError("Required structures not found") if module.has_symbol('MiVisibleState'): symbol = module.get_symbol('MiVisibleState') visible_state = module.object( object_type='pointer', offset=symbol.address, subtype=module.get_type('_MI_VISIBLE_STATE')).dereference() if hasattr(visible_state, 'SystemVaRegions'): for i in range(visible_state.SystemVaRegions.count): lookup = system_va_type.lookup(i) region_range = result.get(lookup, []) region_range.append( (visible_state.SystemVaRegions[i].BaseAddress, visible_state.SystemVaRegions[i].NumberOfBytes)) result[lookup] = region_range elif hasattr(visible_state, 'SystemVaType'): system_range_start = module.object( object_type="pointer", offset=module.get_symbol("MmSystemRangeStart").address) result = cls._enumerate_system_va_type( large_page_size, system_range_start, module, visible_state.SystemVaType) else: raise exceptions.SymbolError("Required structures not found") elif module.has_symbol('MiSystemVaType'): system_range_start = module.object( object_type="pointer", offset=module.get_symbol("MmSystemRangeStart").address) symbol = module.get_symbol('MiSystemVaType') array_count = (0xFFFFFFFF + 1 - system_range_start) // large_page_size type_array = module.object(object_type='array', offset=symbol.address, count=array_count, subtype=module.get_type('char')) result = cls._enumerate_system_va_type(large_page_size, system_range_start, module, type_array) else: raise exceptions.SymbolError("Required structures not found") return result
def get_enumeration(self, enum_name: str) -> interfaces.objects.Template: """Look-up a set of enumeration choices from a specific symbol table.""" retval = self._weak_resolve(SymbolType.ENUM, enum_name) if not isinstance(retval, interfaces.objects.Template): raise exceptions.SymbolError("Unresolvable Enumeration: {}".format(enum_name)) return retval
def get_type(self, type_name: str) -> interfaces.objects.Template: """Resolves an individual symbol.""" index = type_name.find(constants.BANG) if index != -1: table_name, type_name = type_name[:index], type_name[index + 1:] raise exceptions.SymbolError( type_name, table_name, "Symbol for a different table requested: {}".format( table_name + constants.BANG + type_name)) type_definition = self._json_object['user_types'].get(type_name) if type_definition is None: # Fall back to the natives table return self.natives.get_type(self.name + constants.BANG + type_name) members = self._process_fields(type_definition['fields']) object_class = self.get_type_class(type_name) if object_class == objects.AggregateType: for clazz in objects.AggregateTypes: if objects.AggregateTypes[clazz] == type_definition['kind']: object_class = clazz return objects.templates.ObjectTemplate(type_name=self.name + constants.BANG + type_name, object_class=object_class, size=type_definition['size'], members=members)
def get_symbol(self, name: str) -> interfaces.symbols.SymbolInterface: """Returns the symbol given by the symbol name.""" if self._symbol_cache.get(name, None): return self._symbol_cache[name] symbol = self._json_object['symbols'].get(name, None) if not symbol: raise exceptions.SymbolError(name, self.name, "Unknown symbol: {}".format(name)) symbol_type = None if 'type' in symbol: symbol_type = self._interdict_to_template(symbol['type']) symbol_constant_data = None if 'constant_data' in symbol: symbol_constant_data = base64.b64decode( symbol.get('constant_data')) # Mask the addresses if necessary address = symbol['address'] + self.config.get('symbol_shift', 0) if self.config.get('symbol_mask', 0): address = address & self.config['symbol_mask'] self._symbol_cache[name] = interfaces.symbols.SymbolInterface( name=name, address=address, type=symbol_type, constant_data=symbol_constant_data) return self._symbol_cache[name]
def get_symbol(self, symbol_name: str) -> interfaces.symbols.SymbolInterface: """Look-up a symbol name across all the contained symbol spaces.""" retval = self._weak_resolve(SymbolType.SYMBOL, symbol_name) if symbol_name not in self._resolved_symbols and retval.type is not None: # Stash the old resolved type if it exists old_resolved = self._resolved_symbols.get(symbol_name, None) try: self._resolved_symbols[symbol_name] = retval.type for child in retval.type.children: if isinstance(child, objects.templates.ReferenceTemplate): # Resolve the child, then replace it child_resolved = self.get_type(child.vol.type_name) retval.type.replace_child(child, child_resolved) finally: if old_resolved is not None: self._resolved_symbols[symbol_name] = old_resolved if not isinstance(retval, interfaces.symbols.SymbolInterface): table_name = None index = symbol_name.find(constants.BANG) if index > 0: table_name, symbol_name = symbol_name[:index], symbol_name[ index + 1:] raise exceptions.SymbolError( symbol_name, table_name, "Unresolvable Symbol: {}".format(symbol_name)) return retval
def get_enumeration(self, enum_name: str) -> interfaces.objects.Template: """Resolves an individual enumeration.""" if constants.BANG in enum_name: raise exceptions.SymbolError(enum_name, self.name, "Enumeration for a different table requested: {}".format(enum_name)) if enum_name not in self._json_object['enums']: # Fall back to the natives table raise exceptions.SymbolError(enum_name, self.name, "Enumeration not found in {} table: {}".format(self.name, enum_name)) curdict = self._json_object['enums'][enum_name] base_type = self.natives.get_type(curdict['base']) # The size isn't actually used, the base-type defines it. return objects.templates.ObjectTemplate(type_name = self.name + constants.BANG + enum_name, object_class = objects.Enumeration, base_type = base_type, choices = curdict['constants'])
def get_symbol(self, name: str) -> interfaces.symbols.SymbolInterface: """Returns the location offset given by the symbol name.""" # TODO: Add the ability to add/remove/change symbols after creation # note that this should invalidate/update the cache if self._symbol_cache.get(name, None): return self._symbol_cache[name] symbol = self._json_object['symbols'].get(name, None) if not symbol: raise exceptions.SymbolError(name, self.name, "Unknown symbol: {}".format(name)) self._symbol_cache[name] = interfaces.symbols.SymbolInterface(name = name, address = symbol['address']) return self._symbol_cache[name]
def _unresolved(self, *args, **kwargs) -> Any: """Referenced symbols must be appropriately resolved before they can provide information such as size This is because the size request has no context within which to determine the actual symbol structure.""" type_name = self.vol.type_name.split(constants.BANG) table_name = None if len(type_name) == 2: table_name = type_name[0] symbol_name = type_name[-1] raise exceptions.SymbolError( symbol_name, table_name, "Template contains no information about its structure: {}".format(self.vol.type_name))
def get_type(self, type_name: str) -> interfaces.objects.Template: """Takes a symbol name and resolves it. This method ensures that all referenced templates (including self-referential templates) are satisfied as ObjectTemplates """ # Traverse down any resolutions if type_name not in self._resolved: self._resolved[type_name] = self._weak_resolve(SymbolType.TYPE, type_name) # type: ignore self._iterative_resolve([type_name]) if isinstance(self._resolved[type_name], objects.templates.ReferenceTemplate): raise exceptions.SymbolError("Unresolvable symbol requested: {}".format(type_name)) return self._resolved[type_name]
def get_symbol(self, name: str) -> interfaces.symbols.SymbolInterface: """Returns the symbol given by the symbol name.""" if self._symbol_cache.get(name, None): return self._symbol_cache[name] symbol = self._json_object['symbols'].get(name, None) if not symbol: raise exceptions.SymbolError("Unknown symbol: {}".format(name)) symbol_type = None if 'type' in symbol: symbol_type = self._interdict_to_template(symbol['type']) self._symbol_cache[name] = interfaces.symbols.SymbolInterface( name=name, address=symbol['address'], type=symbol_type) return self._symbol_cache[name]
def get_enumeration(self, enum_name: str) -> interfaces.objects.Template: """Look-up a set of enumeration choices from a specific symbol table.""" retval = self._weak_resolve(SymbolType.ENUM, enum_name) if not isinstance(retval, interfaces.objects.Template): table_name = None index = enum_name.find(constants.BANG) if index > 0: table_name, enum_name = enum_name[:index], enum_name[index + 1:] raise exceptions.SymbolError( enum_name, table_name, "Unresolvable Enumeration: {}".format(enum_name)) return retval
def get_symbol(self, symbol_name: str) -> interfaces.symbols.SymbolInterface: """Look-up a symbol name across all the contained symbol spaces.""" retval = self._weak_resolve(SymbolType.SYMBOL, symbol_name) if symbol_name not in self._resolved_symbols and retval.type is not None: self._resolved_symbols[symbol_name] = self._subresolve(retval.type) if not isinstance(retval, interfaces.symbols.SymbolInterface): table_name = None index = symbol_name.find(constants.BANG) if index > 0: table_name, symbol_name = symbol_name[:index], symbol_name[ index + 1:] raise exceptions.SymbolError( symbol_name, table_name, "Unresolvable Symbol: {}".format(symbol_name)) return retval
def _unresolved(self, *args, **kwargs) -> Any: """Referenced symbols must be appropriately resolved before they can provide information such as size This is because the size request has no context within which to determine the actual symbol structure.""" raise exceptions.SymbolError("Template contains no information about its structure: {}".format( self.vol.type_name))
def get_enumeration(self, name: str) -> objects.Template: raise exceptions.SymbolError(name, self.name, "NativeTables never hold enumerations")
def get_symbol(self, name: str) -> SymbolInterface: raise exceptions.SymbolError(name, self.name, "NativeTables never hold symbols")