diff --git a/volatility/framework/configuration/requirements.py b/volatility/framework/configuration/requirements.py index 7a250b12a..4e0870dc8 100644 --- a/volatility/framework/configuration/requirements.py +++ b/volatility/framework/configuration/requirements.py @@ -119,3 +119,42 @@ class ChoiceRequirement(interfaces_configuration.RequirementInterface): vollog.log(constants.LOGLEVEL_V, "ValueError - Value is not within the set of available choices") return [interfaces_configuration.path_join(config_path, self.name)] return [] + + +class LayerListRequirement(ListRequirement): + """Allows a variable length list of layers that must exist """ + + # TODO: Consider making this a ConstructableRequirement such that sub-config options can be held underneath it + # and the swap layers can be reconstructed automatically + + def __init__(self, *args, **kwargs) -> None: + kwargs['element_type'] = str + super().__init__(*args, **kwargs) + + def unsatisfied(self, context: interfaces.context.ContextInterface, config_path: str) -> typing.List[str]: + """Determines whether any layer lists are not present (satisified)""" + list_check = super().unsatisfied(context, config_path) + if list_check: + return list_check + + value = self.config_value(context, config_path) + if not isinstance(value, typing.List): + vollog.log(constants.LOGLEVEL_V, "LayerList configuration value was not a list") + return [interfaces_configuration.path_join(config_path, self.name)] + + failed_layers = [] + for item in value: + if item not in context.memory: + failed_layers.append(item) + if failed_layers: + vollog.log(constants.LOGLEVEL_V, + "LayerList unsatisfied due to non-existant layers: {}".format(failed_layers)) + return [interfaces_configuration.path_join(config_path, self.name)] + return [] + + @classmethod + def get_requirements(cls) -> typing.List[interfaces.configuration.RequirementInterface]: + # This is not optional for the stacker to run, so optional must be marked as False + return [IntRequirement("number_of_elements", + description = "Determines how many layers are in this list", + optional = False)] diff --git a/volatility/framework/layers/intel.py b/volatility/framework/layers/intel.py index 993b25ce8..81626fe37 100644 --- a/volatility/framework/layers/intel.py +++ b/volatility/framework/layers/intel.py @@ -181,14 +181,10 @@ class Intel(interfaces.layers.TranslationLayerInterface): def get_requirements(cls) -> typing.List[interfaces.configuration.RequirementInterface]: return [requirements.TranslationLayerRequirement(name = 'memory_layer', optional = False), - requirements.ListRequirement(name = 'swap_layers', - element_type = requirements.StringRequirement( - name = 'layer_name', - optional = False - ), - min_elements = 0, - max_elements = 100, - optional = True), + requirements.LayerListRequirement(name = 'swap_layers', + min_elements = 0, + max_elements = 100, + optional = True), requirements.IntRequirement(name = 'page_map_offset', optional = False), requirements.IntRequirement(name = 'kernel_virtual_offset',