Beispiel #1
0
    def testWriteUtf8(self):
        """Tests the Write function with UTF-8 encoding."""
        original_stdout = sys.stdout
        output_writer = tools.StdoutOutputWriter()

        sys.stdout = io.BytesIO()
        output_writer.Write(u'A first string\n')
        string = sys.stdout.getvalue()
        self.assertEqual(string, b'A first string\n')

        # Byte string with ASCII characters.
        sys.stdout = io.BytesIO()
        output_writer.Write(b'A 2nd string\n')
        string = sys.stdout.getvalue()
        self.assertEqual(string, b'A 2nd string\n')

        # Unicode string with non-ASCII characters.
        sys.stdout = io.BytesIO()
        output_writer.Write(u'þriðja string\n')
        string = sys.stdout.getvalue()
        self.assertEqual(string, b'\xc3\xberi\xc3\xb0ja string\n')

        # Byte string with non-ASCII characters.
        sys.stdout = io.BytesIO()
        with self.assertRaises(UnicodeDecodeError):
            # This fails because the byte string cannot be converted to
            # a Unicode string before the call to encode().
            output_writer.Write(b'\xc3\xberi\xc3\xb0ja string\n')

        sys.stdout = original_stdout
Beispiel #2
0
    def __init__(self, tool):
        """Initialize a console.

    Args:
      tool (PregTool): preg tool.
    """
        super(PregConsole, self).__init__()
        self._currently_registry_helper = None
        self._currently_loaded_helper_path = ''
        self._registry_helpers = {}

        preferred_encoding = locale.getpreferredencoding()
        if not preferred_encoding:
            preferred_encoding = 'utf-8'

        # TODO: Make this configurable, or derive it from the tool.
        self._output_writer = cli_tools.StdoutOutputWriter(
            encoding=preferred_encoding)

        self.preg_tool = tool
Beispiel #3
0
    def _ProcessStorage(self):
        """Processes a plaso storage file.

    Raises:
      BadConfigOption: when a configuration parameter fails validation.
      RuntimeError: if a non-recoverable situation is encountered.
    """
        if self._analysis_plugins:
            read_only = False
        else:
            read_only = True

        try:
            storage_file = self._front_end.OpenStorage(self._storage_file_path,
                                                       read_only=read_only)
        except IOError as exception:
            raise RuntimeError(
                u'Unable to open storage file: {0:s} with error: {1:s}.'.
                format(self._storage_file_path, exception))

        output_module = self._front_end.GetOutputModule(
            storage_file,
            preferred_encoding=self.preferred_encoding,
            timezone=self._timezone)

        if isinstance(output_module, output_interface.LinearOutputModule):
            if self._output_filename:
                output_file_object = open(self._output_filename, u'wb')
                output_writer = cli_tools.FileObjectOutputWriter(
                    output_file_object)
            else:
                output_writer = cli_tools.StdoutOutputWriter()
            output_module.SetOutputWriter(output_writer)

        helpers_manager.ArgumentHelperManager.ParseOptions(
            self._options, output_module)

        # Check if there are parameters that have not been defined and need to
        # in order for the output module to continue. Prompt user to supply
        # those that may be missing.
        missing_parameters = output_module.GetMissingArguments()
        while missing_parameters:
            # TODO: refactor this.
            configuration_object = PsortOptions()
            setattr(configuration_object, u'output_format', output_module.NAME)
            for parameter in missing_parameters:
                value = self._PromptUserForInput(
                    u'Missing parameter {0:s} for output module'.format(
                        parameter))
                if value is None:
                    logging.warning(
                        u'Unable to set the missing parameter for: {0:s}'.
                        format(parameter))
                    continue

                setattr(configuration_object, parameter, value)

            helpers_manager.ArgumentHelperManager.ParseOptions(
                configuration_object, output_module)
            missing_parameters = output_module.GetMissingArguments()

        # TODO: fix or remove this comment.
        # Get ANALYSIS PLUGINS AND CONFIGURE!
        get_plugins_and_producers = self._front_end.GetAnalysisPluginsAndEventQueues
        analysis_plugins, event_queue_producers = get_plugins_and_producers(
            self._analysis_plugins)

        for analysis_plugin in analysis_plugins:
            helpers_manager.ArgumentHelperManager.ParseOptions(
                self._options, analysis_plugin)

        try:
            counter = self._front_end.ProcessStorage(
                output_module,
                storage_file,
                self._storage_file_path,
                analysis_plugins,
                event_queue_producers,
                command_line_arguments=self._command_line_arguments,
                deduplicate_events=self._deduplicate_events,
                preferred_encoding=self.preferred_encoding,
                time_slice=self._time_slice,
                use_time_slicer=self._use_time_slicer)

        finally:
            storage_file.Close()

        if not self._quiet_mode:
            self._output_writer.Write(u'Processing completed.\n')

            table_view = cli_views.ViewsFactory.GetTableView(
                self._views_format_type, title=u'Counter')
            for element, count in counter.most_common():
                table_view.AddRow([element, count])
            table_view.Write(self._output_writer)
Beispiel #4
0
 def testWriteAscii(self):
     """Tests the Write function with ASCII encoding."""
     output_writer = tools.StdoutOutputWriter(encoding='ascii')
     output_writer.Write('A first string\n')
Beispiel #5
0
    def _ProcessStorage(self):
        """Processes a plaso storage file.

    Raises:
      RuntimeError: if a non-recoverable situation is encountered.
    """
        time_slice = None
        if self._time_slice_event_time_string is not None or self._use_time_slicer:
            time_slice = self._front_end.GetTimeSlice(
                self._time_slice_event_time_string,
                duration=self._time_slice_duration,
                timezone=self._timezone)

        if self._analysis_plugins:
            read_only = False
        else:
            read_only = True

        try:
            storage_file = self._front_end.OpenStorage(self._storage_file_path,
                                                       read_only=read_only)
        except IOError as exception:
            raise RuntimeError(
                u'Unable to open storage file: {0:s} with error: {1:s}.'.
                format(self._storage_file_path, exception))

        output_module = self._front_end.GetOutputModule(
            storage_file,
            preferred_encoding=self.preferred_encoding,
            timezone=self._timezone)

        if isinstance(output_module, output_interface.LinearOutputModule):
            if self._output_filename:
                output_file_object = open(self._output_filename, u'wb')
                output_writer = cli_tools.FileObjectOutputWriter(
                    output_file_object)
            else:
                output_writer = cli_tools.StdoutOutputWriter()
            output_module.SetOutputWriter(output_writer)

        # TODO: To set the filter we need to have the filter object. This may
        # be better handled in an argument helper, but ATM the argument helper
        # does not have access to the actual filter object.
        if hasattr(output_module, u'SetFieldsFilter') and self._filter_object:
            output_module.SetFieldsFilter(self._filter_object)

        try:
            helpers_manager.ArgumentHelperManager.ParseOptions(
                self._options, output_module)
        except errors.BadConfigOption as exception:
            raise RuntimeError(exception)

        # Check if there are parameters that have not been defined and need to
        # in order for the output module to continue. Prompt user to supply
        # those that may be missing.
        missing_parameters = output_module.GetMissingArguments()
        while missing_parameters:
            # TODO: refactor this.
            configuration_object = PsortOptions()
            setattr(configuration_object, u'output_format', output_module.NAME)
            for parameter in missing_parameters:
                value = self._PromptUserForInput(
                    u'Missing parameter {0:s} for output module'.format(
                        parameter))
                if value is None:
                    logging.warning(
                        u'Unable to set the missing parameter for: {0:s}'.
                        format(parameter))
                    continue
                setattr(configuration_object, parameter, value)
            helpers_manager.ArgumentHelperManager.ParseOptions(
                configuration_object, output_module)
            missing_parameters = output_module.GetMissingArguments()

        # Get ANALYSIS PLUGINS AND CONFIGURE!
        get_plugins_and_producers = self._front_end.GetAnalysisPluginsAndEventQueues
        analysis_plugins, event_queue_producers = get_plugins_and_producers(
            self._analysis_plugins)

        for analysis_plugin in analysis_plugins:
            helpers_manager.ArgumentHelperManager.ParseOptions(
                self._options, analysis_plugin)

        counter = self._front_end.ProcessStorage(
            output_module,
            storage_file,
            analysis_plugins,
            event_queue_producers,
            deduplicate_events=self._deduplicate_events,
            preferred_encoding=self.preferred_encoding,
            time_slice=time_slice,
            use_time_slicer=self._use_time_slicer)

        if not self._quiet_mode:
            self.PrintHeader(u'Counter')
            for element, count in counter.most_common():
                self.PrintColumnValue(element, u'{0:d}'.format(count))
Beispiel #6
0
class PregMagics(magic.Magics):
    """Preg iPython magics."""

    # Needed to give the magic class access to the front end tool
    # for processing and formatting.
    console = None

    REGISTRY_KEY_PATH_SEPARATOR = '\\'

    # TODO: move into helper.
    REGISTRY_FILE_BASE_PATH = '\\'

    # TODO: Use the output writer from the tool.
    output_writer = cli_tools.StdoutOutputWriter()

    # pylint: disable=unused-argument
    def _HiveActionList(self, line):
        """Handles the hive list action.

    Args:
      line (str): command line provide via the console.
    """
        self.console.PrintRegistryFileList()
        self.output_writer.Write('\n')
        self.output_writer.Write(
            'To open a Registry file, use: hive open INDEX\n')

    def _HiveActionOpen(self, line):
        """Handles the hive open action.

    Args:
      line (str): command line provide via the console.
    """
        try:
            registry_file_index = int(line[5:], 10)
        except ValueError:
            self.output_writer.Write(
                'Unable to open Registry file, invalid index number.\n')
            return

        try:
            self.console.LoadRegistryFile(registry_file_index)
        except errors.UnableToLoadRegistryHelper as exception:
            self.output_writer.Write(
                'Unable to load hive, with error: {0:s}.\n'.format(exception))
            return

        registry_helper = self.console.current_helper
        self.output_writer.Write('Opening hive: {0:s} [{1:s}]\n'.format(
            registry_helper.path, registry_helper.collector_name))
        self.console.SetPrompt(registry_file_path=registry_helper.path)

    def _HiveActionScan(self, line):
        """Handles the hive scan action.

    Args:
      line (str): command line provide via the console.
    """
        # Line contains: "scan REGISTRY_TYPES" where REGISTRY_TYPES is a comma
        # separated list.
        registry_file_type_string = line[5:]
        if not registry_file_type_string:
            registry_file_types = self.console.preg_tool.GetRegistryTypes()
        else:
            registry_file_types = [
                string.strip()
                for string in registry_file_type_string.split(',')
            ]

        registry_helpers = self.console.preg_tool.GetRegistryHelpers(
            self.console.preg_tool.artifacts_registry,
            registry_file_types=registry_file_types)

        for registry_helper in registry_helpers:
            self.console.AddRegistryHelper(registry_helper)

        self.console.PrintRegistryFileList()

    def _PrintPluginHelp(self, plugin_object):
        """Prints the help information of a plugin.

    Args:
      plugin_object (WindowsRegistryPlugin): a Windows Registry plugin.
    """
        table_view = cli_views.CLITableView(title=plugin_object.NAME)

        # TODO: replace __doc__ by DESCRIPTION.
        description = plugin_object.__doc__
        table_view.AddRow(['Description', description])
        self.output_writer.Write('\n')

        for registry_key in plugin_object.expanded_keys:
            table_view.AddRow(['Registry Key', registry_key])
        table_view.Write(self.output_writer)

    def _SanitizeKeyPath(self, key_path):
        """Sanitizes a Windows Registry key path.

    Args:
      key_path (str): Windows Registry key path.

    Returns:
      str: sanitized Windows Registry key path.
    """
        key_path = key_path.replace('}', '}}')
        key_path = key_path.replace('{', '{{')
        return key_path.replace('\\', '\\\\')

    @magic.line_magic('cd')
    def ChangeDirectory(self, key_path):
        """Change between Registry keys, like a directory tree.

    The key path can either be an absolute path or a relative one.
    Absolute paths can use '.' and '..' to denote current and parent
    directory/key path. If no key path is set the current key is changed
    to point to the root key.

    Args:
      key_path (str): Windows Registry key path to change to.
    """
        if not self.console and not self.console.IsLoaded():
            return

        registry_helper = self.console.current_helper
        if not registry_helper:
            return

        registry_key = registry_helper.ChangeKeyByPath(key_path)
        if not registry_key:
            self.output_writer.Write(
                'Unable to change to key: {0:s}\n'.format(key_path))
            return

        sanitized_path = self._SanitizeKeyPath(registry_key.path)
        self.console.SetPrompt(registry_file_path=registry_helper.path,
                               prepend_string=sanitized_path)

    @magic.line_magic('hive')
    def HiveActions(self, line):
        """Handles the hive actions.

    Args:
      line (str): command line provide via the console.
    """
        if line.startswith('list'):
            self._HiveActionList(line)

        elif line.startswith('open ') or line.startswith('load '):
            self._HiveActionOpen(line)

        elif line.startswith('scan'):
            self._HiveActionScan(line)

    @magic.line_magic('ls')
    def ListDirectoryContent(self, line):
        """Outputs a list of the subkeys and values of the current key.

    Args:
      line (str): command line provide via the console.
    """
        if not self.console and not self.console.IsLoaded():
            return

        if 'true' in line.lower():
            verbose = True
        elif '-v' in line.lower():
            verbose = True
        else:
            verbose = False

        if not self.console.current_helper:
            return

        output = self.console.current_helper.ListCurrentKey(verbose=verbose)
        self.output_writer.Write(output)

    @magic.line_magic('parse')
    def ParseCurrentKey(self, line):
        """Parse the current key.

    Args:
      line (str): command line provide via the console.
    """
        if not self.console and not self.console.IsLoaded():
            return

        if 'true' in line.lower():
            verbose = True
        elif '-v' in line.lower():
            verbose = True
        else:
            verbose = False

        current_helper = self.console.current_helper
        if not current_helper:
            return

        current_key = current_helper.GetCurrentRegistryKey()
        parsed_data = self.console.preg_tool.ParseRegistryKey(
            current_key, current_helper)

        self.console.preg_tool.PrintParsedRegistryKey(
            parsed_data,
            file_entry=current_helper.file_entry,
            show_hex=verbose)

        # Print a hexadecimal representation of all binary values.
        if verbose:
            header_shown = False
            current_key = current_helper.GetCurrentRegistryKey()
            for value in current_key.GetValues():
                if not value.DataIsBinaryData():
                    continue

                if not header_shown:
                    table_view = cli_views.CLITableView(
                        title='Hexadecimal representation')
                    header_shown = True
                else:
                    table_view = cli_views.CLITableView()

                table_view.AddRow(['Attribute', value.name])
                table_view.Write(self.output_writer)

                self.console.preg_tool.PrintSeparatorLine()
                self.console.preg_tool.PrintSeparatorLine()

                value_string = hexdump.Hexdump.FormatData(value.data)
                self.output_writer.Write(value_string)
                self.output_writer.Write('\n')
                self.output_writer.Write('+-' * 40)
                self.output_writer.Write('\n')

    @magic.line_magic('plugin')
    def ParseWithPlugin(self, line):
        """Parses a Windows Registry key using a specific plugin.

    Args:
      line (str): command line provide via the console.
    """
        if not self.console and not self.console.IsLoaded():
            self.output_writer.Write('No hive loaded, unable to parse.\n')
            return

        current_helper = self.console.current_helper
        if not current_helper:
            return

        if not line:
            self.output_writer.Write('No plugin name added.\n')
            return

        plugin_name = line
        if '-h' in line:
            items = line.split()
            if len(items) != 2:
                self.output_writer.Write(
                    'Wrong usage: plugin [-h] PluginName\n')
                return
            if items[0] == '-h':
                plugin_name = items[1]
            else:
                plugin_name = items[0]

        registry_file_type = current_helper.file_type
        registry_plugin_list = self.console.preg_tool.GetWindowsRegistryPlugins(
        )
        plugin_object = registry_plugin_list.GetPluginObjectByName(
            registry_file_type, plugin_name)
        if not plugin_object:
            self.output_writer.Write(
                'No plugin named: {0:s} available for Registry type {1:s}\n'.
                format(plugin_name, registry_file_type))
            return

        key_paths = plugin_list.PluginList.GetKeyPathsFromPlugin(plugin_object)
        if not key_paths:
            self.output_writer.Write(
                'Plugin: {0:s} has no key information.\n'.format(line))
            return

        if '-h' in line:
            self._PrintPluginHelp(plugin_object)
            return

        for key_path in key_paths:
            registry_key = current_helper.GetKeyByPath(key_path)
            if not registry_key:
                self.output_writer.Write(
                    'Key: {0:s} not found\n'.format(key_path))
                continue

            # Move the current location to the key to be parsed.
            self.ChangeDirectory(key_path)
            # Parse the key.
            current_key = current_helper.GetCurrentRegistryKey()
            parsed_data = self.console.preg_tool.ParseRegistryKey(
                current_key, current_helper, use_plugins=[plugin_name])
            self.console.preg_tool.PrintParsedRegistryKey(
                parsed_data, file_entry=current_helper.file_entry)

    # pylint: disable=unused-argument
    @magic.line_magic('pwd')
    def PrintCurrentWorkingDirectory(self, line):
        """Print the current path.

    Args:
      line (str): command line provide via the console.
    """
        if not self.console and not self.console.IsLoaded():
            return

        current_helper = self.console.current_helper
        if not current_helper:
            return

        self.output_writer.Write('{0:s}\n'.format(
            current_helper.GetCurrentRegistryPath()))