import argparse import json import logging import os import sys import volatility.framework import volatility.plugins from volatility.framework import automagic, constants, contexts, interfaces from volatility.framework.interfaces.configuration import HierarchicalDict from volatility.framework.renderers.text import TextRenderer __author__ = 'mike' logging.basicConfig(filename = 'example.log', format = '%(asctime)s %(name)-12s %(levelname)-8s %(message)s', datefmt = '%m-%d %H:%M', level = logging.DEBUG) vollog = logging.getLogger("volatility") console = logging.StreamHandler() console.setLevel(logging.DEBUG) formatter = logging.Formatter('%(levelname)-8s %(name)-12s: %(message)s') console.setFormatter(formatter) logging.getLogger("").addHandler(console) class CommandLine(object): def __init__(self): pass def run(self): sys.stdout.write("Volatility Framework {}\n".format(constants.PACKAGE_VERSION)) volatility.framework.require_interface_version(0, 0, 0) # TODO: Get CLI config options volatility.framework.import_files(volatility.plugins) # TODO: Choose a plugin parser = argparse.ArgumentParser(prog = 'volatility', description = "An open-source memory forensics framework") parser.add_argument("-p", "--plugin", help = "Run the following plugin", default = "windows.pslist.PsList") parser.add_argument("file", help = "Temporary method for changing the file", default = None) parser.add_argument("-c", "--config", help = "Load the configuration from a json file", default = None, type = str) # argparse_adapter.adapt_config(context.config, parser) # Run the argparser args = parser.parse_args() print("PLUGIN", args.plugin) plug_class = args.plugin.split(".")[-1] plug_mod = ".".join(args.plugin.split(".")[:-1]) plug_name = "volatility.plugins." + plug_mod plugin = None for module in sys.modules: if plug_name == module: plugin = getattr(sys.modules[module], plug_class) break else: raise RuntimeError("Invalid plugin requested: {}".format(plug_name)) config_path = interfaces.configuration.path_join("plugins", plugin.__name__.lower()) ### # PASS TO UI ### # Hand the plugin requirements over to the CLI (us) and let it construct the config tree # UI fills in the config: ctx = contexts.Context() if args.config: with open(args.config, "r") as f: json_val = json.load(f) ctx.config.splice("plugins.pslist", HierarchicalDict(json_val)) if not args.file or not os.path.exists(args.file): raise RuntimeError("Please provide a valid filename") else: ctx.config["automagic.general.single_location"] = "file://" + os.path.abspath(args.file) pass # ctx.config["automagic.general.single_page_map_offset"] = 0x1ab000 ### # BACK TO THE FRAMEWORK ### # Clever magic figures out how to fulfill each requirement that might not be fulfilled automagics = automagic.available() automagic.run(automagics, ctx, plugin, "plugins") # Check all the requirements and/or go back to the automagic step if not plugin.validate(ctx, config_path): raise RuntimeError("Unable to validate the plugin configuration") print("\n\n") constructed = plugin(ctx, config_path) with open("config.json", "w") as f: json.dump(dict(constructed.build_configuration()), f, sort_keys = True, indent = 2) # Construct and run the plugin TextRenderer().render(constructed.run()) def main(): CommandLine().run()