diff --git a/volatility/framework/interfaces/configuration.py b/volatility/framework/interfaces/configuration.py index 1a0898995..a50b7479f 100644 --- a/volatility/framework/interfaces/configuration.py +++ b/volatility/framework/interfaces/configuration.py @@ -12,6 +12,8 @@ import collections.abc import copy import json import logging +import random +import string import sys from abc import ABCMeta, abstractmethod @@ -489,6 +491,26 @@ class ConfigurableInterface(validity.ValidityRoutines, metaclass = ABCMeta): result.append(value) return result + def make_subconfig(self, *args, **kwargs): + """Constructs a new subconfig, containing each element from kwargs and returns the full config_path to it""" + if args: + vollog.debug("Non-keyword arguments to make_subconfig are ignored - this is a bug in the calling code") + + random_config_dict = ''.join( + random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(8)) + new_config_path = path_join(self.config_path, random_config_dict) + # TODO: Check that the new_config_path is empty, although it's not critical if it's not since the values are merged in + + # This should check that each k corresponds to a requirement and each v is of the appropriate type + # This would require knowledge of the new configurable itself to verify, and they should do validation in the + # constructor anyway, however, to prevent bad types getting into the config tree we just verify that v is a simple type + for k, v in kwargs.items(): + if not isinstance(v, (int, str, bool, float, bytes)): + raise TypeError("Config values passed to make_subconfig can only be simple types") + self.context.config[path_join(new_config_path, k)] = v + + return new_config_path + class TranslationLayerRequirement(ConstructableRequirementInterface): """Class maintaining the limitations on what sort of translation layers are acceptable""" diff --git a/volatility/framework/interfaces/plugins.py b/volatility/framework/interfaces/plugins.py index 8d296ef7b..f27fea9e7 100644 --- a/volatility/framework/interfaces/plugins.py +++ b/volatility/framework/interfaces/plugins.py @@ -56,10 +56,3 @@ class PluginInterface(interfaces_configuration.ConfigurableInterface, validity.V :return: a TreeGrid object that can then be passed to a Renderer. :rtype: interfaces.renderers.TreeGrid """ - - def __call__(self, method = 'run', **kwargs): - """Method to make a plugin callable. It must still have been instantiated with a context and a config_path""" - for k, v in kwargs: - self.config[k] = v - method = getattr(self, method) - return method() diff --git a/volatility/plugins/windows/printkey.py b/volatility/plugins/windows/printkey.py index 6f61c1060..9823c4ec1 100644 --- a/volatility/plugins/windows/printkey.py +++ b/volatility/plugins/windows/printkey.py @@ -2,8 +2,6 @@ import datetime import volatility.framework.interfaces.plugins as plugins from volatility.framework.configuration import requirements -from volatility.framework.interfaces import configuration -from volatility.framework.interfaces.configuration import HierarchicalDict from volatility.framework.layers.registry import RegistryHive from volatility.framework.renderers import TreeGrid from volatility.framework.symbols.windows.extensions.registry import RegValueTypes @@ -66,14 +64,10 @@ class PrintKey(plugins.PluginInterface): yield from self.registry_walker(registry, node) def run(self): - layer = self.context.memory[self.config['primary']] - reg_config = HierarchicalDict({'hive_offset': self.config['offset'], - 'base_layer': self.config['primary'], - 'ntsymbols': self.config['ntsymbols']}) - self.config.splice('registry', reg_config) - - registry_config_path = configuration.path_join(self.config_path, 'registry') - registry_layer = RegistryHive(self.context, registry_config_path, name = 'hive', os = 'Windows') + reg_config_path = self.make_subconfig(hive_offset = self.config['offset'], + base_layer = self.config['primary'], + ntsymbols = self.config['ntsymbols']) + registry_layer = RegistryHive(self.context, reg_config_path, name = 'hive', os = 'Windows') self.context.memory.add_layer(registry_layer) node = None