diff --git a/volatility3/framework/interfaces/symbols.py b/volatility3/framework/interfaces/symbols.py index bf0ead3b3..b271de412 100644 --- a/volatility3/framework/interfaces/symbols.py +++ b/volatility3/framework/interfaces/symbols.py @@ -4,10 +4,11 @@ """Symbols provide structural information about a set of bytes.""" import bisect import collections.abc -from abc import abstractmethod, ABC -from typing import Any, Dict, Iterable, List, Optional, Tuple, Type, Mapping +from abc import ABC, abstractmethod +from typing import Any, Dict, Iterable, List, Mapping, Optional, Tuple, Type from volatility3.framework import constants, exceptions, interfaces +from volatility3.framework.configuration import requirements from volatility3.framework.interfaces import configuration, objects from volatility3.framework.interfaces.configuration import RequirementInterface @@ -301,7 +302,10 @@ class SymbolTableInterface(BaseSymbolTableInterface, configuration.ConfigurableI @classmethod def get_requirements(cls) -> List[RequirementInterface]: - return super().get_requirements() + return super().get_requirements() + [ + requirements.IntRequirement(name = 'symbol_mask', description = 'Address mask for symbols', optional = True, + default = 0), + ] class NativeTableInterface(BaseSymbolTableInterface): diff --git a/volatility3/framework/symbols/intermed.py b/volatility3/framework/symbols/intermed.py index 6e55c4b35..c48fcc8a7 100644 --- a/volatility3/framework/symbols/intermed.py +++ b/volatility3/framework/symbols/intermed.py @@ -82,7 +82,8 @@ class IntermediateSymbolTable(interfaces.symbols.SymbolTableInterface): native_types: interfaces.symbols.NativeTableInterface = None, table_mapping: Optional[Dict[str, str]] = None, validate: bool = True, - class_types: Optional[Mapping[str, Type[interfaces.objects.ObjectInterface]]] = None) -> None: + class_types: Optional[Mapping[str, Type[interfaces.objects.ObjectInterface]]] = None, + symbol_mask: int = 0) -> None: """Instantiates a SymbolTable based on an IntermediateSymbolFormat JSON file. This is validated against the appropriate schema. The validation can be disabled by passing validate = False, but this should almost never be done. @@ -96,6 +97,7 @@ class IntermediateSymbolTable(interfaces.symbols.SymbolTableInterface): table_mapping: A dictionary linking names referenced in the file with symbol tables in the context validate: Determines whether the ISF file will be validated against the appropriate schema class_types: A dictionary of type names and classes that override StructType when they are instantiated + symbol_mask: An address mask used for all returned symbol offsets from this table (a mask of 0 disables masking) """ # Check there are no obvious errors # Open the file and test the version @@ -131,6 +133,7 @@ class IntermediateSymbolTable(interfaces.symbols.SymbolTableInterface): # Since we've been created with parameters, ensure our config is populated likewise self.config['isf_url'] = isf_url + self.config['symbol_mask'] = symbol_mask @staticmethod def _closest_version(version: str, versions: Dict[Tuple[int, int, int], Type['ISFormatTable']]) \ @@ -214,7 +217,8 @@ class IntermediateSymbolTable(interfaces.symbols.SymbolTableInterface): filename: str, native_types: Optional[interfaces.symbols.NativeTableInterface] = None, table_mapping: Optional[Dict[str, str]] = None, - class_types: Optional[Mapping[str, Type[interfaces.objects.ObjectInterface]]] = None) -> str: + class_types: Optional[Mapping[str, Type[interfaces.objects.ObjectInterface]]] = None, + symbol_mask: int = 0) -> str: """Takes a context and loads an intermediate symbol table based on a filename. @@ -225,6 +229,7 @@ class IntermediateSymbolTable(interfaces.symbols.SymbolTableInterface): filename: Basename of the file to find under the sub_path native_types: Set of native types, defaults to native types read from the intermediate symbol format file table_mapping: a dictionary of table names mentioned within the ISF file, and the tables within the context which they map to + symbol_mask: An address mask used for all returned symbol offsets from this table (a mask of 0 disables masking) Returns: the name of the added symbol table @@ -239,7 +244,8 @@ class IntermediateSymbolTable(interfaces.symbols.SymbolTableInterface): isf_url = urls[0], native_types = native_types, table_mapping = table_mapping, - class_types = class_types) + class_types = class_types, + symbol_mask = symbol_mask) context.symbol_space.append(table) return table_name @@ -324,7 +330,11 @@ class Version1Format(ISFormatTable): symbol = self._json_object['symbols'].get(name, None) if not symbol: raise exceptions.SymbolError(name, self.name, f"Unknown symbol: {name}") - self._symbol_cache[name] = interfaces.symbols.SymbolInterface(name = name, address = symbol['address']) + address = symbol['address'] + if self.config.get('symbol_mask', 0): + address = address & self.config['symbol_mask'] + + self._symbol_cache[name] = interfaces.symbols.SymbolInterface(name = name, address = address) return self._symbol_cache[name] @property @@ -522,13 +532,15 @@ class Version3Format(Version2Format): symbol = self._json_object['symbols'].get(name, None) if not symbol: raise exceptions.SymbolError(name, self.name, f"Unknown symbol: {name}") + address = symbol['address'] + if self.config.get('symbol_mask', 0): + address = address & self.config['symbol_mask'] + 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) + self._symbol_cache[name] = interfaces.symbols.SymbolInterface(name = name, address = address, type = symbol_type) return self._symbol_cache[name] @@ -575,6 +587,10 @@ class Version5Format(Version4Format): symbol = self._json_object['symbols'].get(name, None) if not symbol: raise exceptions.SymbolError(name, self.name, f"Unknown symbol: {name}") + address = symbol['address'] + if self.config.get('symbol_mask', 0): + address = address & self.config['symbol_mask'] + symbol_type = None if 'type' in symbol: symbol_type = self._interdict_to_template(symbol['type']) @@ -583,7 +599,7 @@ class Version5Format(Version4Format): symbol_constant_data = base64.b64decode(symbol.get('constant_data')) self._symbol_cache[name] = interfaces.symbols.SymbolInterface(name = name, - address = symbol['address'], + address = address, type = symbol_type, constant_data = symbol_constant_data) return self._symbol_cache[name]