コード例 #1
0
ファイル: volatility_cli_classes.py プロジェクト: soumy/panda
    def run(self):
        # we aren't really doing logging, but you can change these numbers to get more details
        vollog = logging.getLogger(__name__)
        vollog = logging.getLogger()
        # vollog.setLevel(1000)
        console = logging.StreamHandler()
        #console.setLevel(logging.WARNING)
        formatter = logging.Formatter(
            '%(levelname)-8s %(name)-12s: %(message)s')
        console.setFormatter(formatter)
        vollog.addHandler(console)
        volatility.framework.require_interface_version(1, 0, 0)
        # also change here for log level
        #console.setLevel(1000)
        constants.PARALLELISM = constants.Parallelism.Off
        ctx = contexts.Context()  # Construct a blank context
        failures = framework.import_files(
            volatility.plugins,
            True)  # Will not log as console's default level is WARNING
        automagics = automagic.available(ctx)
        plugin_list = framework.list_plugins()
        seen_automagics = set()
        configurables_list = {}
        for amagic in automagics:
            if amagic in seen_automagics:
                continue
            seen_automagics.add(amagic)
            if isinstance(amagic,
                          interfaces.configuration.ConfigurableInterface):
                configurables_list[amagic.__class__.__name__] = amagic

        plugin_name = "linux.pstree.PsTree"  # we're just "kinda" running a plugin
        plugin = plugin_list[plugin_name]
        base_config_path = "plugins"
        plugin_config_path = interfaces.configuration.path_join(
            base_config_path, plugin.__name__)

        # It should be up to the UI to determine which automagics to run, so this is before BACK TO THE FRAMEWORK
        automagics = automagic.choose_automagic(automagics, plugin)
        # this is our fake file that represents QEMU memory
        single_location = "file:" + pathname2url("/panda.panda")
        ctx.config['automagic.LayerStacker.single_location'] = single_location
        constructed = plugins.construct_plugin(ctx, automagics,
                                               plugin, base_config_path,
                                               MuteProgress(), self)
        return constructed
コード例 #2
0
ファイル: volatility_cli_classes.py プロジェクト: soumy/panda
    def run(self, argstring):
        # Make sure we log everything

        vollog = logging.getLogger()
        #vollog.setLevel(1)
        # Trim the console down by default
        console = logging.StreamHandler()
        #console.setLevel(logging.FATAL)
        formatter = logging.Formatter(
            '%(levelname)-8s %(name)-12s: %(message)s')
        console.setFormatter(formatter)
        vollog.addHandler(console)
        # Make sure we log everything
        vollog = logging.getLogger()
        #vollog.setLevel(1)
        # Trim the console down by default
        console = logging.StreamHandler()
        #console.setLevel(logging.WARNING)
        formatter = logging.Formatter(
            '%(levelname)-8s %(name)-12s: %(message)s')
        console.setFormatter(formatter)
        vollog.addHandler(console)
        arg_arr = shlex.split(argstring)
        """Executes the command line module, taking the system arguments,
            determining the plugin to run and then running it."""
        sys.stdout.write("Volatility 3 Framework {}\n".format(
            constants.PACKAGE_VERSION))

        volatility.framework.require_interface_version(1, 0, 0)

        renderers = dict([
            (x.name.lower(), x)
            for x in framework.class_subclasses(text_renderer.CLIRenderer)
        ])

        parser = argparse.ArgumentParser(
            prog='volatility',
            description="An open-source memory forensics framework")
        parser.add_argument("-c",
                            "--config",
                            help="Load the configuration from a json file",
                            default=None,
                            type=str)
        parser.add_argument(
            "--parallelism",
            help=
            "Enables parallelism (defaults to processes if no argument given)",
            nargs='?',
            choices=['processes', 'threads', 'off'],
            const='processes',
            default=None,
            type=str)
        parser.add_argument(
            "-e",
            "--extend",
            help="Extend the configuration with a new (or changed) setting",
            default=None,
            action='append')
        parser.add_argument(
            "-p",
            "--plugin-dirs",
            help="Semi-colon separated list of paths to find plugins",
            default="",
            type=str)
        parser.add_argument(
            "-s",
            "--symbol-dirs",
            help="Semi-colon separated list of paths to find symbols",
            default="",
            type=str)
        parser.add_argument("-v",
                            "--verbosity",
                            help="Increase output verbosity",
                            default=0,
                            action="count")
        parser.add_argument("-l",
                            "--log",
                            help="Log output to a file as well as the console",
                            default=None,
                            type=str)
        parser.add_argument(
            "-o",
            "--output-dir",
            help="Directory in which to output any generated files",
            default=os.path.abspath(
                os.path.join(os.path.dirname(__file__), '..', '..')),
            type=str)
        parser.add_argument("-q",
                            "--quiet",
                            help="Remove progress feedback",
                            default=False,
                            action='store_true')
        parser.add_argument(
            "-r",
            "--renderer",
            metavar='RENDERER',
            help="Determines how to render the output ({})".format(", ".join(
                list(renderers))),
            default="quick",
            choices=list(renderers))
        parser.add_argument(
            "-f",
            "--file",
            metavar='FILE',
            default=None,
            type=str,
            help=
            "Shorthand for --single-location=file:// if single-location is not defined"
        )
        parser.add_argument(
            "--write-config",
            help="Write configuration JSON file out to config.json",
            default=False,
            action='store_true')

        # We have to filter out help, otherwise parse_known_args will trigger the help message before having
        # processed the plugin choice or had the plugin subparser added.
        known_args = [
            arg for arg in arg_arr if arg != '--help' and arg != '-h'
        ]
        partial_args, _ = parser.parse_known_args(known_args)
        if partial_args.plugin_dirs:
            volatility.plugins.__path__ = [
                os.path.abspath(p) for p in partial_args.plugin_dirs.split(";")
            ] + constants.PLUGINS_PATH

        if partial_args.symbol_dirs:
            volatility.symbols.__path__ = [
                os.path.abspath(p) for p in partial_args.symbol_dirs.split(";")
            ] + constants.SYMBOL_BASEPATHS

        if partial_args.log:
            file_logger = logging.FileHandler(partial_args.log)
            #file_logger.setLevel(1)
            file_formatter = logging.Formatter(
                datefmt='%y-%m-%d %H:%M:%S',
                fmt='%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
            file_logger.setFormatter(file_formatter)
            vollog.addHandler(file_logger)
            vollog.info("Logging started")
        if partial_args.verbosity < 3:
            console.setLevel(30 - (partial_args.verbosity * 10))
        else:
            console.setLevel(10 - (partial_args.verbosity - 2))
        #console.setLevel(0)

        vollog.info("Volatility plugins path: {}".format(
            volatility.plugins.__path__))
        vollog.info("Volatility symbols path: {}".format(
            volatility.symbols.__path__))

        # Set the PARALLELISM
        if partial_args.parallelism == 'processes':
            constants.PARALLELISM = constants.Parallelism.Multiprocessing
        elif partial_args.parallelism == 'threading':
            constants.PARALLELISM = constants.Parallelism.Threading
        else:
            constants.PARALLELISM = constants.Parallelism.Off

        # Do the initialization
        ctx = contexts.Context()  # Construct a blank context
        failures = framework.import_files(
            volatility.plugins,
            True)  # Will not log as console's default level is WARNING
        if failures:
            parser.epilog = "The following plugins could not be loaded (use -vv to see why): " + \
                ", ".join(sorted(failures))
            vollog.info(parser.epilog)
        automagics = automagic.available(ctx)

        plugin_list = framework.list_plugins()

        seen_automagics = set()
        configurables_list = {}
        for amagic in automagics:
            if amagic in seen_automagics:
                continue
            seen_automagics.add(amagic)
            if isinstance(amagic,
                          interfaces.configuration.ConfigurableInterface):
                self.populate_requirements_argparse(parser, amagic.__class__)
                configurables_list[amagic.__class__.__name__] = amagic

        subparser = parser.add_subparsers(title="Plugins",
                                          dest="plugin",
                                          action=HelpfulSubparserAction)
        for plugin in sorted(plugin_list):
            plugin_parser = subparser.add_parser(
                plugin, help=plugin_list[plugin].__doc__)
            self.populate_requirements_argparse(plugin_parser,
                                                plugin_list[plugin])
            configurables_list[plugin] = plugin_list[plugin]

        ###
        # PASS TO UI
        ###
        # Hand the plugin requirements over to the CLI (us) and let it construct the config tree

        # Run the argparser
        args = parser.parse_args(arg_arr)
        print(partial_args.verbosity)
        print(args.plugin, type(args.plugin))
        if args.plugin is None:
            parser.error("Please select a plugin to run")

        vollog.log(constants.LOGLEVEL_VVV,
                   "Cache directory used: {}".format(constants.CACHE_PATH))

        plugin = plugin_list[args.plugin]
        base_config_path = "plugins"
        plugin_config_path = interfaces.configuration.path_join(
            base_config_path, plugin.__name__)

        # Special case the -f argument because people use is so frequently
        # It has to go here so it can be overridden by single-location if it's defined
        # NOTE: This will *BREAK* if LayerStacker, or the automagic configuration system, changes at all
        ###
        if args.file:
            file_name = os.path.abspath(args.file)
            if not os.path.exists(
                    file_name) and "panda.panda" not in file_name:
                print("File does not exist: {}".format(file_name))
            else:
                single_location = "file:" + request.pathname2url(file_name)
                ctx.config[
                    'automagic.LayerStacker.single_location'] = single_location

        # UI fills in the config, here we load it from the config file and do it before we process the CL parameters
        if args.config:
            with open(args.config, "r") as f:
                json_val = json.load(f)
                ctx.config.splice(
                    plugin_config_path,
                    interfaces.configuration.HierarchicalDict(json_val))

        self.populate_config(ctx, configurables_list, args, plugin_config_path)

        if args.extend:
            for extension in args.extend:
                if '=' not in extension:
                    raise ValueError(
                        "Invalid extension (extensions must be of the format \"conf.path.value='value'\")"
                    )
                address, value = extension[:extension.find('=')], json.loads(
                    extension[extension.find('=') + 1:])
                ctx.config[address] = value

        # It should be up to the UI to determine which automagics to run, so this is before BACK TO THE FRAMEWORK
        automagics = automagic.choose_automagic(automagics, plugin)
        self.output_dir = args.output_dir

        ###
        # BACK TO THE FRAMEWORK
        ###
        try:
            progress_callback = PrintedProgress()
            if args.quiet:
                progress_callback = MuteProgress()

            constructed = plugins.construct_plugin(ctx, automagics, plugin,
                                                   base_config_path,
                                                   progress_callback, self)
            #	return (ctx, automagics, plugin, base_config_path, progress_callback, self)

            if args.write_config:
                vollog.debug("Writing out configuration data to config.json")
                with open("config.json", "w") as f:
                    json.dump(dict(constructed.build_configuration()),
                              f,
                              sort_keys=True,
                              indent=2)
            # return StringTextRenderer().render(constructed.run())
            return constructed
        except exceptions.UnsatisfiedException as excp:
            self.process_exceptions(excp)
            parser.exit(
                1, "Unable to validate the plugin requirements: {}\n".format(
                    [x for x in excp.unsatisfied]))