mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-08-17 20:35:40 +02:00
135 lines
6.8 KiB
Python
135 lines
6.8 KiB
Python
# This file was contributed to the Volatility Framework Version 3.
|
|
# Copyright (C) 2018 Volatility Foundation.
|
|
#
|
|
# THE LICENSED WORK IS PROVIDED UNDER THE TERMS OF THE Volatility Contributors
|
|
# Public License V1.0("LICENSE") AS FIRST COMPLETED BY: Volatility Foundation,
|
|
# Inc. ANY USE, PUBLIC DISPLAY, PUBLIC PERFORMANCE, REPRODUCTION OR DISTRIBUTION
|
|
# OF, OR PREPARATION OF SUBSEQUENT WORKS, DERIVATIVE WORKS OR DERIVED WORKS BASED
|
|
# ON, THE LICENSED WORK CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS LICENSE AND ITS
|
|
# TERMS, WHETHER OR NOT SUCH RECIPIENT READS THE TERMS OF THE LICENSE. "LICENSED
|
|
# WORK,” “RECIPIENT" AND “DISTRIBUTOR" ARE DEFINED IN THE LICENSE. A COPY OF THE
|
|
# LICENSE IS LOCATED IN THE TEXT FILE ENTITLED "LICENSE.txt" ACCOMPANYING THE
|
|
# CONTENTS OF THIS FILE. IF A COPY OF THE LICENSE DOES NOT ACCOMPANY THIS FILE, A
|
|
# COPY OF THE LICENSE MAY ALSO BE OBTAINED AT THE FOLLOWING WEB SITE:
|
|
# https://www.volatilityfoundation.org/license/vcpl_v1.0
|
|
#
|
|
# Software distributed under the License is distributed on an "AS IS" basis,
|
|
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
|
|
# specific language governing rights and limitations under the License.
|
|
#
|
|
"""Defines the automagic interfaces for populating the context before a plugin runs
|
|
|
|
Automagic objects attempt to automatically fill configuration values that a user has not filled.
|
|
"""
|
|
from abc import ABCMeta
|
|
from typing import Any, List, Optional, Tuple, Union, Type
|
|
|
|
from volatility.framework import interfaces, constants
|
|
from volatility.framework.configuration import requirements
|
|
|
|
|
|
class AutomagicInterface(interfaces.configuration.ConfigurableInterface, metaclass = ABCMeta):
|
|
"""Class that defines an automagic component that can help fulfill a Requirement
|
|
|
|
These classes are callable with the following parameters:
|
|
|
|
Args:
|
|
context: The context in which to store configuration data that the automagic might populate
|
|
config_path: Configuration path where the configurable's data under the context's config lives
|
|
configurable: The top level configurable whose requirements may need statisfying
|
|
progress_callback: An optional function accepting a percentage and optional description to indicate
|
|
progress during long calculations
|
|
|
|
.. note::
|
|
|
|
The `context` provided here may be different to that provided during initialization. The `context` provided at
|
|
initialization should be used for local configuration of the automagic itself, the `context` provided during
|
|
the call is to be populated by the automagic.
|
|
"""
|
|
|
|
priority = 10
|
|
"""An ordering to indicate how soon this automagic should be run"""
|
|
|
|
def __init__(self, context: interfaces.context.ContextInterface, config_path: str, *args, **kwargs) -> None:
|
|
super().__init__(context, config_path)
|
|
for requirement in self.get_requirements():
|
|
if not isinstance(requirement, (interfaces.configuration.SimpleTypeRequirement,
|
|
requirements.ChoiceRequirement, requirements.ListRequirement)):
|
|
raise ValueError(
|
|
"Automagic requirements must be a SimpleTypeRequirement, ChoiceRequirement or ListRequirement")
|
|
|
|
def __call__(self,
|
|
context: interfaces.context.ContextInterface,
|
|
config_path: str,
|
|
requirement: interfaces.configuration.RequirementInterface,
|
|
progress_callback: constants.ProgressCallback = None) -> Optional[List[Any]]:
|
|
"""Runs the automagic over the configurable"""
|
|
return []
|
|
|
|
# TODO: requirement_type can be made UnionType[Type[T], Tuple[Type[T], ...]]
|
|
# once mypy properly supports Tuples in instance
|
|
|
|
def find_requirements(self,
|
|
context: interfaces.context.ContextInterface,
|
|
config_path: str,
|
|
requirement_root: interfaces.configuration.RequirementInterface,
|
|
requirement_type: Union[Tuple[Type[interfaces.configuration.RequirementInterface], ...], Type[
|
|
interfaces.configuration.RequirementInterface]],
|
|
shortcut: bool = True) -> List[Tuple[str, interfaces.configuration.RequirementInterface]]:
|
|
"""Determines if there is actually an unfulfilled requirement waiting
|
|
|
|
This ensures we do not carry out an expensive search when there is no requirement for a particular requirement
|
|
|
|
Args:
|
|
context: Context on which to operate
|
|
config_path: Configuration path of the top-level requirement
|
|
requirement_root: Top-level requirement whose subrequirements will all be searched
|
|
requirement_type: Type of requirement to find
|
|
shortcut: Only returns requirements that live under unsatisfied requirements
|
|
|
|
Returns:
|
|
A list of tuples containing the config_path, sub_config_path and requirement identifying the SymbolTableRequirements
|
|
"""
|
|
sub_config_path = interfaces.configuration.path_join(config_path, requirement_root.name)
|
|
results = [] # type: List[Tuple[str, interfaces.configuration.RequirementInterface]]
|
|
recurse = not shortcut
|
|
if isinstance(requirement_root, requirement_type):
|
|
if recurse or requirement_root.unsatisfied(context, config_path):
|
|
results.append((sub_config_path, requirement_root))
|
|
else:
|
|
recurse = True
|
|
if recurse:
|
|
for subreq in requirement_root.requirements.values():
|
|
results += self.find_requirements(context, sub_config_path, subreq, requirement_type, shortcut)
|
|
return results
|
|
|
|
|
|
class StackerLayerInterface(metaclass = ABCMeta):
|
|
"""Class that takes a lower layer and attempts to build on it
|
|
|
|
stack_order determines the order (from low to high) that stacking layers
|
|
should be attempted lower levels should have lower stack_orders
|
|
"""
|
|
|
|
stack_order = 0
|
|
|
|
@classmethod
|
|
def stack(self,
|
|
context: interfaces.context.ContextInterface,
|
|
layer_name: str,
|
|
progress_callback: constants.ProgressCallback = None) -> Optional[interfaces.layers.DataLayerInterface]:
|
|
"""
|
|
Method to determine whether this builder can operate on the named layer. If so, modify the context appropriately.
|
|
|
|
Returns the name of any new_layer stacked on top of this layer or None. The stacking is therefore strictly
|
|
linear rather than tree driven.
|
|
|
|
Configuration options provided by the context are ignored, and defaults are to be used by this method
|
|
to build a space where possible.
|
|
|
|
Args:
|
|
context: Context in which to construct the higher layer
|
|
layer_name: Name of the layer to stack on top of
|
|
progress_callback: A callback function to indicate progress through a scan (if one is necessary)
|
|
"""
|