From ede5ba07aa59c4d819938822891aae733f2dc5cc Mon Sep 17 00:00:00 2001 From: Mike Auty Date: Wed, 10 Jun 2020 01:13:30 +0100 Subject: [PATCH] Symbols: Apply symbol_masking option to IntermediateSymbolTables --- .../framework/automagic/symbol_finder.py | 1 + volatility/framework/interfaces/symbols.py | 4 ++- volatility/framework/symbols/intermed.py | 28 +++++++++++++------ 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/volatility/framework/automagic/symbol_finder.py b/volatility/framework/automagic/symbol_finder.py index 44c2eb64d..30c2cc888 100644 --- a/volatility/framework/automagic/symbol_finder.py +++ b/volatility/framework/automagic/symbol_finder.py @@ -107,6 +107,7 @@ class SymbolFinder(interfaces.automagic.AutomagicInterface): path_join = interfaces.configuration.path_join context.config[path_join(config_path, requirement.name, "class")] = clazz context.config[path_join(config_path, requirement.name, "isf_url")] = isf_path + context.config[path_join(config_path, requirement.name, "symbol_mask")] = layer.address_mask # Set a default symbol_shift when attempt to determine it, # so we can create the symbols which are used in finding the aslr_shift anyway diff --git a/volatility/framework/interfaces/symbols.py b/volatility/framework/interfaces/symbols.py index d95b64d11..1115a45d8 100644 --- a/volatility/framework/interfaces/symbols.py +++ b/volatility/framework/interfaces/symbols.py @@ -294,7 +294,9 @@ class SymbolTableInterface(BaseSymbolTableInterface, configuration.ConfigurableI @classmethod def get_requirements(cls) -> List[RequirementInterface]: return super().get_requirements() + [ - requirements.IntRequirement(name = 'symbol_shift', description = 'Symbol Shift', optional = False) + requirements.IntRequirement(name = 'symbol_shift', description = 'Symbol Shift', optional = False), + requirements.IntRequirement( + name = 'symbol_mask', description = 'Address mask for symbols', optional = True, default = 0), ] diff --git a/volatility/framework/symbols/intermed.py b/volatility/framework/symbols/intermed.py index 87a7c00eb..075d762c8 100644 --- a/volatility/framework/symbols/intermed.py +++ b/volatility/framework/symbols/intermed.py @@ -84,7 +84,8 @@ class IntermediateSymbolTable(interfaces.symbols.SymbolTableInterface): table_mapping: Optional[Dict[str, str]] = None, validate: bool = True, class_types: Optional[Mapping[str, Type[interfaces.objects.ObjectInterface]]] = None, - symbol_shift: int = 0) -> None: + symbol_shift: int = 0, + 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. @@ -98,12 +99,13 @@ 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_shift: An offset by which to alter all returned symbols for this table + 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 - self._isf_url = isf_url self._versions = dict([(x.version, x) for x in class_subclasses(ISFormatTable)]) - fp = volatility.framework.layers.resources.ResourceAccessor().open(self._isf_url) + fp = volatility.framework.layers.resources.ResourceAccessor().open(isf_url) reader = codecs.getreader("utf-8") json_object = json.load(reader(fp)) # type: ignore fp.close() @@ -127,6 +129,11 @@ class IntermediateSymbolTable(interfaces.symbols.SymbolTableInterface): table_mapping = table_mapping, class_types = class_types) + # Since we've been created with parameters, ensure our config is populated likewise + self.config['isf_url'] = isf_url + self.config['symbol_shift'] = symbol_shift + self.config['symbol_mask'] = symbol_mask + @staticmethod def _closest_version(version: str, versions: Dict[Tuple[int, int, int], Type['ISFormatTable']]) \ -> Type['ISFormatTable']: @@ -210,7 +217,8 @@ class IntermediateSymbolTable(interfaces.symbols.SymbolTableInterface): native_types: Optional[interfaces.symbols.NativeTableInterface] = None, table_mapping: Optional[Dict[str, str]] = None, class_types: Optional[Mapping[str, Type[interfaces.objects.ObjectInterface]]] = None, - symbol_shift: int = 0) -> str: + symbol_shift: int = 0, + symbol_mask: int = 0) -> str: """Takes a context and loads an intermediate symbol table based on a filename. @@ -221,6 +229,8 @@ 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_shift: An offset by which to alter all returned symbols for this table + 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 @@ -236,7 +246,8 @@ class IntermediateSymbolTable(interfaces.symbols.SymbolTableInterface): native_types = native_types, table_mapping = table_mapping, class_types = class_types, - symbol_shift = symbol_shift) + symbol_shift = symbol_shift, + symbol_mask = symbol_mask) context.symbol_space.append(table) return table_name @@ -245,7 +256,6 @@ class IntermediateSymbolTable(interfaces.symbols.SymbolTableInterface): return super().get_requirements() + [ requirements.StringRequirement( "isf_url", description = "JSON file containing the symbols encoded in the Intermediate Symbol Format"), - requirements.IntRequirement(name = 'symbol_shift', description = 'Symbol Shift', optional = False) ] @@ -318,8 +328,10 @@ class Version1Format(ISFormatTable): 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'] + self.config.get('symbol_shift', 0)) + 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) return self._symbol_cache[name] @property