Files
volatility3/volatility/framework/automagic/stacker.py
T

106 lines
4.7 KiB
Python

from urllib import parse
import logging
import volatility
from volatility.framework import interfaces
from volatility.framework.automagic import construct_layers
from volatility.framework.layers import physical
vollog = logging.getLogger(__name__)
class LayerStacker(interfaces.automagic.AutomagicInterface):
"""Class that attempts to build up """
# Most important automagic, must happen first!
priority = 10
page_map_offset = None
location = None
def __call__(self, context, config_path, requirement):
"""Runs the automagic over the configurable"""
# Quick exit if we're not needed
if requirement.validate(context, config_path):
return
# Bow out quickly if the UI hasn't provided a single_location
if "automagic.general.single_location" not in context.config:
return
location = context.config["automagic.general.single_location"]
self._check_type(location, str)
self._check_type(requirement, interfaces.configuration.RequirementInterface)
self.location = parse.urlparse(location)
# Setup the local copy of the resource
self.local_store = None
if self.location.scheme == "file":
self.local_store = self.location.path
new_context = context.clone()
current_layer_name = context.memory.free_layer_name("FileLayer")
current_config_path = interfaces.configuration.path_join("automagic", "layer_stacker", "stack",
current_layer_name)
# This must be specific to get us started, setup the config and run
new_context.config[interfaces.configuration.path_join(current_config_path, "filename")] = self.local_store
new_context.add_layer(physical.FileLayer(new_context, current_config_path, current_layer_name))
# Repeatedly apply "determine what this is" code and build as much up as possible
stacked = True
stacked_layers = [current_layer_name]
stack_set = sorted(volatility.framework.class_subclasses(interfaces.automagic.StackerLayerInterface),
key = lambda x: x.stack_order)
while stacked == True:
stacked = False
new_layer = None
stacker_cls = None
for stacker_cls in stack_set:
stacker = stacker_cls()
try:
new_layer = stacker.stack(new_context, current_layer_name)
if new_layer:
new_context.memory.add_layer(new_layer)
break
except Exception as excp:
pass
else:
stacked = False
if new_layer and stacker_cls:
stacked_layers = [new_layer.name] + stacked_layers
current_layer_name = new_layer.name
stacked = True
stack_set.remove(stacker_cls)
vollog.debug("Stacked layers: {}".format(stacked_layers))
if stacked_layers:
result = self.find_suitable_requirements(stacked_layers, requirement, new_context, config_path)
if result:
path, layer = result
# splice in the new configuration into the original context
context.config.splice(path, new_context.memory[layer].build_configuration())
# Call the construction magic now we may have new things to construct
constructor = construct_layers.ConstructionMagic()
constructor(context, config_path, requirement)
def find_suitable_requirements(self, stacked_layers, requirement, context, config_path):
child_config_path = interfaces.configuration.path_join(config_path, requirement.name)
if isinstance(requirement, interfaces.configuration.TranslationLayerRequirement):
if not requirement.validate(context, config_path):
original_setting = context.config.get(child_config_path, None)
for layer in stacked_layers:
context.config[child_config_path] = layer
if requirement.validate(context, config_path):
return child_config_path, layer
else:
# Clean-up to restore the config
if original_setting:
context.config[child_config_path] = original_setting
else:
del context.config[child_config_path]
for req_name, req in requirement.requirements.items():
result = self.find_suitable_requirements(stacked_layers, req, context, child_config_path)
if result:
return result