def __init__(self, input_reader=None, output_writer=None): """Initializes the CLI tool object. Args: input_reader (InputReader): the input reader. The default is None which indicates the use of the stdin input reader. output_writer (OutputWriter): the output writer. The default is None which indicates the use of the stdout output writer. """ super(PstealTool, self).__init__( input_reader=input_reader, output_writer=output_writer) self._analysis_front_end = psort.PsortFrontend() self._command_line_arguments = None self._deduplicate_events = True self._enable_sigsegv_handler = False self._extraction_front_end = log2timeline.Log2TimelineFrontend() self._force_preprocessing = False self._hasher_names_string = None self._number_of_extraction_workers = 0 self._options = None self._output_format = u'dynamic' self._output_filename = None self._output_module = None self._parser_filter_expression = None self._preferred_year = None self._single_process_mode = False self._source_type = None self._status_view_mode = u'window' self._time_slice = None self._use_time_slicer = False self._yara_rules_string = None
def __init__(self, input_reader=None, output_writer=None): """Initializes the CLI tool object. Args: input_reader (Optional[InputReader]): input reader, where None indicates that the stdin input reader should be used. output_writer (Optional[OutputWriter]): output writer, where None indicates that the stdout output writer should be used. """ super(Log2TimelineTool, self).__init__(input_reader=input_reader, output_writer=output_writer) self._command_line_arguments = None self._enable_sigsegv_handler = False self._filter_expression = None self._front_end = log2timeline.Log2TimelineFrontend() self._number_of_extraction_workers = 0 self._output = None self._source_type = None self._source_type_string = u'UNKNOWN' self._status_view_mode = u'linear' self._stdout_output_writer = isinstance(self._output_writer, cli_tools.StdoutOutputWriter) self._temporary_directory = None self._text_prepend = None self._worker_memory_limit = None self.dependencies_check = True self.list_output_modules = False self.show_info = False
def __init__(self, input_reader=None, output_writer=None): """Initializes the CLI tool object. Args: input_reader: the input reader (instance of InputReader). The default is None which indicates the use of the stdin input reader. output_writer: the output writer (instance of OutputWriter). The default is None which indicates the use of the stdout output writer. """ super(Log2TimelineTool, self).__init__(input_reader=input_reader, output_writer=output_writer) self._command_line_arguments = None self._enable_sigsegv_handler = False self._filter_expression = None self._foreman_verbose = False self._front_end = log2timeline.Log2TimelineFrontend() self._number_of_extraction_workers = 0 self._stdout_output_writer = isinstance(self._output_writer, cli_tools.StdoutOutputWriter) self._source_type = None self._source_type_string = u'UNKNOWN' self._status_view_mode = u'linear' self._output = None self.dependencies_check = True self.list_output_modules = False self.show_info = False
def testGetStorageInformation(self): """Tests the get storage information function.""" test_front_end = log2timeline.Log2TimelineFrontend() options = test_lib.Options() options.source = self._GetTestFilePath(['image.dd']) storage_file_path = os.path.join(self._temp_directory, 'plaso.db') test_front_end.ParseOptions(options) test_front_end.SetStorageFile(storage_file_path=storage_file_path) test_front_end.SetRunForeman(run_foreman=False) test_front_end.ProcessSource(options) try: storage_file = storage.StorageFile(storage_file_path, read_only=True) except IOError: # This is not a storage file, we should fail. self.assertTrue(False) # Make sure we can read an event out of the storage. event_object = storage_file.GetSortedEntry() self.assertIsNotNone(event_object)
def testGetOutputClasses(self): """Tests the GetOutputClasses function.""" test_front_end = log2timeline.Log2TimelineFrontend() output_classes = list(test_front_end.GetOutputClasses()) self.assertIsNotNone(output_classes) available_output_names = [name for name, _ in output_classes] self.assertIn(u'dynamic', available_output_names) self.assertIn(u'json', available_output_names)
def testGetOutputModulesInformation(self): """Tests the _GetOutputModulesInformation function.""" test_front_end = log2timeline.Log2TimelineFrontend() modules_info = test_front_end._GetOutputModulesInformation() self.assertIsNotNone(modules_info) available_module_names = [name for name, _ in modules_info] self.assertIn(u'dynamic', available_module_names) self.assertIn(u'json', available_module_names)
def testGetFiltersInformation(self): """Tests the _GetFiltersInformation function.""" test_front_end = log2timeline.Log2TimelineFrontend() filters_info = test_front_end._GetFiltersInformation() self.assertIsNotNone(filters_info) available_filter_names = [name for name, _ in filters_info] self.assertIn(u'DynamicFilter', available_filter_names) self.assertIn(u'EventObjectFilter', available_filter_names)
def testGetPluginData(self): """Tests the GetPluginData function.""" test_front_end = log2timeline.Log2TimelineFrontend() plugin_info = test_front_end.GetPluginData() self.assertIn(u'Hashers', plugin_info) available_hasher_names = [] for hasher_info in plugin_info[u'Hashers']: available_hasher_names.append(hasher_info[0]) self.assertIn(u'sha256', available_hasher_names) self.assertIn(u'sha1', available_hasher_names) self.assertIn(u'Parsers', plugin_info) self.assertIsNotNone(plugin_info[u'Parsers']) self.assertIn(u'Plugins', plugin_info) self.assertIsNotNone(plugin_info[u'Plugins'])
def __init__(self, input_reader=None, output_writer=None): """Initializes the CLI tool object. Args: input_reader: the input reader (instance of InputReader). The default is None which indicates the use of the stdin input reader. output_writer: the output writer (instance of OutputWriter). The default is None which indicates the use of the stdout output writer. """ super(Log2TimelineTool, self).__init__(input_reader=input_reader, output_writer=output_writer) self._filter_expression = None self._foreman_verbose = False self._front_end = log2timeline.Log2TimelineFrontend() self._output = None self.list_timezones = False self.list_parsers_and_plugins = False
def Main(): """Start the tool.""" multiprocessing.freeze_support() front_end = log2timeline.Log2TimelineFrontend() epilog = u'\n'.join([ u'', u'Example usage:', u'', u'Run the tool against an image (full kitchen sink)', u' log2timeline.py /cases/mycase/plaso.dump ímynd.dd', u'', u'Instead of answering questions, indicate some of the options on the', u'command line (including data from particular VSS stores).', (u' log2timeline.py -o 63 --vss_stores 1,2 /cases/plaso_vss.dump ' u'image.E01'), u'', u'And that\'s how you build a timeline using log2timeline...', u'' ]) description = u'\n'.join([ u'', u'log2timeline is the main front-end to the plaso back-end, used to', u'collect and correlate events extracted from a filesystem.', u'', u'More information can be gathered from here:', u' http://plaso.kiddaland.net/usage/log2timeline', u'' ]) arg_parser = argparse.ArgumentParser( description=textwrap.dedent(description), formatter_class=argparse.RawDescriptionHelpFormatter, epilog=textwrap.dedent(epilog), add_help=False) # Create few argument groups to make formatting help messages clearer. info_group = arg_parser.add_argument_group('Informational Arguments') function_group = arg_parser.add_argument_group('Functional Arguments') deep_group = arg_parser.add_argument_group('Deep Analysis Arguments') performance_group = arg_parser.add_argument_group('Performance Arguments') function_group.add_argument( '-z', '--zone', '--timezone', dest='timezone', action='store', type=str, default='UTC', help= (u'Define the timezone of the IMAGE (not the output). This is usually ' u'discovered automatically by preprocessing but might need to be ' u'specifically set if preprocessing does not properly detect or to ' u'overwrite the detected time zone.')) function_group.add_argument( '-t', '--text', dest='text_prepend', action='store', type=unicode, default=u'', metavar='TEXT', help=(u'Define a free form text string that is prepended to each path ' u'to make it easier to distinguish one record from another in a ' u'timeline (like c:\\, or host_w_c:\\)')) function_group.add_argument( '--parsers', dest='parsers', type=str, action='store', default='', metavar='PARSER_LIST', help= (u'Define a list of parsers to use by the tool. This is a comma ' u'separated list where each entry can be either a name of a parser ' u'or a parser list. Each entry can be prepended with a minus sign ' u'to negate the selection (exclude it). The list match is an ' u'exact match while an individual parser matching is a case ' u'insensitive substring match, with support for glob patterns. ' u'Examples would be: "reg" that matches the substring "reg" in ' u'all parser names or the glob pattern "sky[pd]" that would match ' u'all parsers that have the string "skyp" or "skyd" in it\'s name. ' u'All matching is case insensitive.')) function_group.add_argument( '--hashers', dest='hashers', type=str, action='store', default='', metavar='HASHER_LIST', help=( u'Define a list of hashers to use by the tool. This is a comma ' u'separated list where each entry is the name of a hasher. eg. md5,' u'sha256.')) info_group.add_argument('-h', '--help', action='help', help=u'Show this help message and exit.') info_group.add_argument( '--logfile', action='store', metavar='FILENAME', dest='logfile', type=unicode, default=u'', help=(u'If defined all log messages will be redirected to this file ' u'instead the default STDERR.')) function_group.add_argument( '-p', '--preprocess', dest='preprocess', action='store_true', default=False, help=(u'Turn on preprocessing. Preprocessing is turned on by default ' u'when parsing image files, however if a mount point is being ' u'parsed then this parameter needs to be set manually.')) front_end.AddPerformanceOptions(performance_group) performance_group.add_argument( '--workers', dest='workers', action='store', type=int, default=0, help=(u'The number of worker threads [defaults to available system ' u'CPU\'s minus three].')) # TODO: seems to be no longer used, remove. # function_group.add_argument( # '-i', '--image', dest='image', action='store_true', default=False, # help=( # 'Indicates that this is an image instead of a regular file. It is ' # 'not necessary to include this option if -o (offset) is used, then ' # 'this option is assumed. Use this when parsing an image with an ' # 'offset of zero.')) front_end.AddVssProcessingOptions(deep_group) performance_group.add_argument( '--single_thread', '--single-thread', '--single_process', '--single-process', dest='single_process', action='store_true', default=False, help=(u'Indicate that the tool should run in a single process.')) function_group.add_argument( '-f', '--file_filter', '--file-filter', dest='file_filter', action='store', type=unicode, default=None, help=( u'List of files to include for targeted collection of files to ' u'parse, one line per file path, setup is /path|file - where each ' u'element can contain either a variable set in the preprocessing ' u'stage or a regular expression.')) deep_group.add_argument('--scan_archives', dest='scan_archives', action='store_true', default=False, help=argparse.SUPPRESS) # This option is "hidden" for the time being, still left in there for testing # purposes, but hidden from the tool usage and help messages. # help=('Indicate that the tool should try to open files to extract embedd' # 'ed files within them, for instance to extract files from compress' # 'ed containers, etc. Be AWARE THAT THIS IS EXTREMELY SLOW.')) front_end.AddImageOptions(function_group) function_group.add_argument( '--partition', dest='partition_number', action='store', type=int, default=None, help=(u'Choose a partition number from a disk image. This partition ' u'number should correspond to the partion number on the disk ' u'image, starting from partition 1.')) # Build the version information. version_string = u'log2timeline - plaso back-end {0:s}'.format( plaso.GetVersion()) info_group.add_argument('-v', '--version', action='version', version=version_string, help=u'Show the current version of the back-end.') info_group.add_argument( '--info', dest='show_info', action='store_true', default=False, help=u'Print out information about supported plugins and parsers.') info_group.add_argument( '--show_memory_usage', '--show-memory-usage', action='store_true', default=False, dest='foreman_verbose', help=(u'Indicates that basic memory usage should be included in the ' u'output of the process monitor. If this option is not set the ' u'tool only displays basic status and counter information.')) info_group.add_argument( '--disable_worker_monitor', '--disable-worker-monitor', action='store_false', default=True, dest='foreman_enabled', help= (u'Turn off the foreman. The foreman monitors all worker processes ' u'and periodically prints out information about all running workers.' u'By default the foreman is run, but it can be turned off using this ' u'parameter.')) front_end.AddExtractionOptions(function_group) function_group.add_argument( '--output', dest='output_module', action='store', type=unicode, default='', help=( u'Bypass the storage module directly storing events according to ' u'the output module. This means that the output will not be in the ' u'pstorage format but in the format chosen by the output module. ' u'[Please not this feature is EXPERIMENTAL at this time, use at ' u'own risk (eg. sqlite output does not yet work)]')) function_group.add_argument( '--serializer-format', '--serializer_format', dest='serializer_format', action='store', default='proto', metavar='FORMAT', help=(u'By default the storage uses protobufs for serializing event ' u'objects. This parameter can be used to change that behavior. ' u'The choices are "proto" and "json".')) front_end.AddInformationalOptions(info_group) arg_parser.add_argument( 'output', action='store', metavar='STORAGE_FILE', nargs='?', type=unicode, help=(u'The path to the output file, if the file exists it will get ' u'appended to.')) arg_parser.add_argument( 'source', action='store', metavar='SOURCE', nargs='?', type=unicode, help= (u'The path to the source device, file or directory. If the source is ' u'a supported storage media device or image file, archive file or ' u'a directory, the files within are processed recursively.')) arg_parser.add_argument( 'filter', action='store', metavar='FILTER', nargs='?', default=None, type=unicode, help=(u'A filter that can be used to filter the dataset before it ' u'is written into storage. More information about the filters ' u'and it\'s usage can be found here: http://plaso.kiddaland.' u'net/usage/filters')) # Properly prepare the attributes according to local encoding. if front_end.preferred_encoding == 'ascii': logging.warning( u'The preferred encoding of your system is ASCII, which is not optimal ' u'for the typically non-ASCII characters that need to be parsed and ' u'processed. The tool will most likely crash and die, perhaps in a way ' u'that may not be recoverable. A five second delay is introduced to ' u'give you time to cancel the runtime and reconfigure your preferred ' u'encoding, otherwise continue at own risk.') time.sleep(5) u_argv = [x.decode(front_end.preferred_encoding) for x in sys.argv] sys.argv = u_argv try: options = arg_parser.parse_args() except UnicodeEncodeError: # If we get here we are attempting to print help in a "dumb" terminal. print arg_parser.format_help().encode(front_end.preferred_encoding) return False if options.timezone == 'list': front_end.ListTimeZones() return True if options.show_info: front_end.ListPluginInformation() return True format_str = ( u'%(asctime)s [%(levelname)s] (%(processName)-10s) PID:%(process)d ' u'<%(module)s> %(message)s') if options.debug: if options.logfile: logging.basicConfig(level=logging.DEBUG, format=format_str, filename=options.logfile) else: logging.basicConfig(level=logging.DEBUG, format=format_str) logging_filter = log2timeline.LoggingFilter() root_logger = logging.getLogger() root_logger.addFilter(logging_filter) elif options.logfile: logging.basicConfig(level=logging.INFO, format=format_str, filename=options.logfile) else: logging.basicConfig(level=logging.INFO, format=format_str) if not options.output: arg_parser.print_help() print u'' arg_parser.print_usage() print u'' logging.error(u'Wrong usage: need to define an output.') return False try: front_end.ParseOptions(options) front_end.SetStorageFile(options.output) except errors.BadConfigOption as exception: arg_parser.print_help() print u'' logging.error(u'{0:s}'.format(exception)) return False # Configure the foreman (monitors workers). front_end.SetShowMemoryInformation(show_memory=options.foreman_verbose) front_end.SetRunForeman(run_foreman=options.foreman_enabled) try: front_end.ProcessSource(options) logging.info(u'Processing completed.') except (KeyboardInterrupt, errors.UserAbort): logging.warning(u'Aborted by user.') return False except errors.SourceScannerError as exception: logging.warning( (u'Unable to scan for a supported filesystem with error: {0:s}\n' u'Most likely the image format is not supported by the ' u'tool.').format(exception)) return False return True
def testGetDisabledOutputClasses(self): """Tests the GetDisabledOutputClasses function.""" test_front_end = log2timeline.Log2TimelineFrontend() output_classes = list(test_front_end.GetDisabledOutputClasses()) self.assertIsNotNone(output_classes)