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
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
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)
def testWriteAscii(self): """Tests the Write function with ASCII encoding.""" output_writer = tools.StdoutOutputWriter(encoding='ascii') output_writer.Write('A first string\n')
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))
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()))