diff --git a/volatility/cli/__init__.py b/volatility/cli/__init__.py index aa1589c4e..ce00dc4e1 100644 --- a/volatility/cli/__init__.py +++ b/volatility/cli/__init__.py @@ -1,3 +1,13 @@ +"""A CommandLine User Interface for the volatility framework + + User interfaces make use of the framework to: + * determine available plugins + * request necessary information for those plugins from the user + * determine what "automagic" modules will be used to populate information the user does not provide + * run the plugin + * display the results +""" + import argparse import json import logging @@ -28,10 +38,13 @@ logging.getLogger("").addHandler(console) class CommandLine(object): + """Constructs a command-line interface object for users to run plugins""" + def __init__(self): pass def run(self): + """Executes the command line module, taking the system arguments, determining the plugin to run and then running it""" sys.stdout.write("Volatility Framework {}\n".format(constants.PACKAGE_VERSION)) volatility.framework.require_interface_version(0, 0, 0) @@ -119,4 +132,5 @@ def progress_callback(progress, description = None): def main(): + """A convenience function for constructing and running the :class:`CommandLine`'s run method""" CommandLine().run() diff --git a/volatility/framework/automagic/__init__.py b/volatility/framework/automagic/__init__.py index 4b441f163..1c4e21385 100644 --- a/volatility/framework/automagic/__init__.py +++ b/volatility/framework/automagic/__init__.py @@ -1,3 +1,12 @@ +"""Automagic modules allow the framework to populate configuration elements that a user has not provided. + +Automagic objects accept a `context` and a `configurable`, and will make appropriate changes to the `context` in an +attempt to fulfill the requirements of the `configurable` object (or objects upon which that configurable may rely). + +Several pre-existing modules include one to stack layers on top of each other (allowing automatic detection and +loading of file format types) as well as a module to reconstruct layers based on their provided requirements. +""" + import logging import sys @@ -9,7 +18,11 @@ vollog = logging.getLogger(__name__) def available(): - """Determine all the available automagic classes""" + """Returns an ordered list of all subclasses of :class:`~volatility.framework.interfaces.automagic.AutomagicInterface`. + + The order is based on the priority attributes of the subclasses, in order to ensure the automagics are listed in + an appropriate order. + """ import_files(sys.modules[__name__]) return sorted([clazz() for clazz in class_subclasses(interfaces.automagic.AutomagicInterface)], key = lambda x: x.priority) @@ -26,7 +39,8 @@ def run(automagics, context, configurable, config_path = "", progress_callback = This is where any automagic is allowed to run, and alter the context in order to satisfy/improve all requirements - This is where any automagic is allowed to run, and alter the context in order to satisfy/improve all requirements + .. note:: The order of the `automagics` list is important. An `automagic` that populates configurations may be necessary + for an `automagic` that populates the context based on the configuration information. """ for automagic in automagics: if not isinstance(automagic, interfaces.automagic.AutomagicInterface): diff --git a/volatility/framework/automagic/construct_layers.py b/volatility/framework/automagic/construct_layers.py index a43c5bd24..3de5a7653 100644 --- a/volatility/framework/automagic/construct_layers.py +++ b/volatility/framework/automagic/construct_layers.py @@ -1,3 +1,6 @@ +"""An automagic module to use configuration data to configure and then construct classes that fulfill the descendants +of a :class:`~volatility.framework.interfaces.configuration.ConfigurableInterface`.""" + import logging from volatility.framework import constants @@ -7,9 +10,11 @@ vollog = logging.getLogger(__name__) class ConstructionMagic(interfaces.automagic.AutomagicInterface): - """Runs through the requirement tree and from the bottom up attempts to construct all TranslationLayerRequirements + """Class to run through the requirement tree of the :class:`~volatility.framework.interfaces.configuration.ConfigurableInterface` + and from the bottom of the tree upwards, attempt to construct all + :class:`~volatility.framework.interfaces.configuration.ConstructableRequirementInterface` based classes. - This should run first to prevent existing configurations getting re-configured + :warning: This `automagic` should run first to prevent existing configurations getting re-configured. """ priority = 0 diff --git a/volatility/framework/automagic/pdbscan.py b/volatility/framework/automagic/pdbscan.py index b3c65bbb8..8ce154177 100644 --- a/volatility/framework/automagic/pdbscan.py +++ b/volatility/framework/automagic/pdbscan.py @@ -1,5 +1,8 @@ -# pdbscan.py -- Scan Volatility Layers for Windows kernel PDB signatures -# +"""A module for scanning translation layers looking for Windows PDB records from loaded PE files. + + This module contains a standalone scanner, and also a :class:`~volatility.framework.interfaces.layers.ScannerInterface` + based scanner for use within the framework by calling :func:`~volatility.framework.interfaces.layers.DataLayerInterface.scan`. +""" import logging import math @@ -22,8 +25,17 @@ PAGE_SIZE = 0x1000 class PdbSigantureScanner(interfaces.layers.ScannerInterface): + """A :class:`~volatility.framework.interfaces.layers.ScannerInterface` based scanner use to identify Windows PDB records + + :param pdb_names: A list of bytestrings, used to match pdb signatures against the pdb names within the records. + :type pdb_names: A list of :class:`bytestring` objects + + .. note:: The pdb_names must be a list of byte strings, unicode strs will not match against the data scanned + """ overlap = 0x4000 + """The size of overlap needed for the signature to ensure data cannot hide between two scanned chunks""" thread_safe = True + """Determines whether the scanner accesses global variables in a thread safe manner (for use with :mod:`multiprocessing`)""" _RSDS_format = struct.Struct("<16BI") @@ -54,8 +66,7 @@ def scan(ctx, layer_name, progress_callback = None, start = None, end = None): """Scans through `layer_name` at `ctx` and returns the tuple (GUID, age, pdb_name, signature_offset, mz_offset) - Note that this is automagical and therefore not guaranteed to provide - correct results. + .. note:: This is automagical and therefore not guaranteed to provide correct results. The UI should always provide the user an opportunity to specify the appropriate types and PDB values themselves @@ -96,7 +107,10 @@ def scan(ctx, layer_name, progress_callback = None, start = None, end = None): class KernelPDBScanner(interfaces.automagic.AutomagicInterface): - """Looks for all Intel address spaces and attempts to identify the PDB guid required for the space""" + """An Automagic object that looks for all Intel translation layers and scans each of them for a pdb signature. + When found, a search for a corresponding Intermediate Format data file is carried out and if found an appropriate + symbol space is automatically loaded. + """ priority = 30 # Make sure uncompressed/outside-framework takes precedence, so users can overload. @@ -104,6 +118,7 @@ class KernelPDBScanner(interfaces.automagic.AutomagicInterface): os.path.join("..", "..", "symbols", "windows")] """Provides a list of prefixes that are searched when locating Intermediate Format data files""" suffixes = ['.json', '.json.xz'] + """Provides a list of supported suffixes for Intermediate Format data files""" def __init__(self): super().__init__() @@ -114,7 +129,13 @@ class KernelPDBScanner(interfaces.automagic.AutomagicInterface): Returns a list of possible kernel locations in the physical memory - Returns a list of possible kernel locations in the physical memory + :param context: The context in which the `requirement` lives + :type context: ~volatility.framework.interfaces.context.ContextInterface + :param config_path: The path within the `context` for the `requirement`'s configuration variables + :type config_path: str + :param requirement: The root of the requirement tree to search for :class:~`volatility.framework.interfaces.layers.TranslationLayerRequirement` objects to scan + :type requirement: ~volatility.framework.interfaces.configuration.RequirementInterface + :return: A list of (layer_name, scan_results) """ sub_config_path = interfaces.configuration.path_join(config_path, requirement.name) results = {}