Skip to content

Commit 3f2d09d

Browse files
committed
Moved AMCache formatter to configuration log2timeline#444
1 parent a6ad979 commit 3f2d09d

File tree

10 files changed

+140
-80
lines changed

10 files changed

+140
-80
lines changed

data/formatters.yaml

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Event formatters.
2+
3+
type: 'conditional'
4+
data_type: 'windows:registry:amcache'
5+
message:
6+
- 'path: {full_path}'
7+
- 'sha1: {sha1}'
8+
- 'productname: {productname}'
9+
- 'companyname: {companyname}'
10+
- 'fileversion: {fileversion}'
11+
- 'languagecode: {languagecode}'
12+
- 'filesize: {filesize}'
13+
- 'filedescription: {filedescription}'
14+
- 'linkerts: {linkerts}'
15+
- 'lastmodifiedts: {lastmodifiedts}'
16+
- 'createdts: {createdts}'
17+
- 'programid: {programid}'
18+
short_message:
19+
- 'path: {full_path}'
20+
short_source: 'AMCACHE'
21+
source: 'Amcache Registry Entry'
22+
---
23+
type: 'conditional'
24+
data_type: 'windows:registry:amcache:programs'
25+
message:
26+
- 'name: {name}'
27+
- 'version: {version}'
28+
- 'publisher: {publisher}'
29+
- 'languagecode: {languagecode}'
30+
- 'entrytype: {entrytype}'
31+
- 'uninstallkey: {uninstallkey}'
32+
- 'filepaths: {filepaths}'
33+
- 'productcode: {productcode}'
34+
- 'packagecode: {packagecode}'
35+
- 'msiproductcode: {msiproductcode}'
36+
- 'msipackagecode: {msipackagecode}'
37+
- 'files: {files}'
38+
short_message:
39+
- 'name: {name}'
40+
short_source: 'AMCACHEPROGRAM'
41+
source: 'Amcache Programs Registry Entry'

plaso/cli/extraction_tool.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ def _ReadParserPresetsFromFile(self):
208208
parsers_manager.ParsersManager.ReadPresetsFromFile(self._presets_file)
209209
except errors.MalformedPresetError as exception:
210210
raise errors.BadConfigOption(
211-
'Unable to read presets from file with error: {0!s}'.format(
211+
'Unable to read parser presets from file with error: {0!s}'.format(
212212
exception))
213213

214214
def _SetExtractionParsersAndPlugins(self, configuration, session):

plaso/cli/psort_tool.py

+29
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
from plaso.engine import engine
3030
from plaso.engine import knowledge_base
3131
from plaso.filters import event_filter
32+
from plaso.formatters import manager as formatters_manager
3233
from plaso.lib import errors
3334
from plaso.lib import loggers
3435
from plaso.lib import timelib
@@ -61,6 +62,8 @@ class PsortTool(
6162
'Application to read, filter and process output from a plaso storage '
6263
'file.')
6364

65+
_FORMATTERS_FILE_NAME = 'formatters.yaml'
66+
6467
def __init__(self, input_reader=None, output_writer=None):
6568
"""Initializes the CLI tool object.
6669
@@ -79,6 +82,7 @@ def __init__(self, input_reader=None, output_writer=None):
7982
self._deduplicate_events = True
8083
self._event_filter_expression = None
8184
self._event_filter = None
85+
self._formatters_file = None
8286
self._knowledge_base = knowledge_base.KnowledgeBase()
8387
self._number_of_analysis_reports = 0
8488
self._preferred_language = 'en-US'
@@ -151,6 +155,9 @@ def _ParseAnalysisPluginOptions(self, options):
151155
152156
Args:
153157
options (argparse.Namespace): command line arguments.
158+
159+
Raises:
160+
BadConfigOption: if the options are invalid.
154161
"""
155162
# Get a list of all available plugins.
156163
analysis_plugin_info = self._analysis_manager.GetAllPluginInformation()
@@ -282,6 +289,26 @@ def _PrintAnalysisReportsDetails(self, storage_reader):
282289

283290
table_view.Write(self._output_writer)
284291

292+
def _ReadEventFormattersFromFile(self):
293+
"""Reads the event formatters the formatters.yaml file.
294+
295+
Raises:
296+
BadConfigOption: if the event formatters file cannot be read.
297+
"""
298+
self._formatters_file = os.path.join(
299+
self._data_location, self._FORMATTERS_FILE_NAME)
300+
if not os.path.isfile(self._formatters_file):
301+
raise errors.BadConfigOption(
302+
'No such event formatters file: {0:s}.'.format(self._formatters_file))
303+
304+
try:
305+
formatters_manager.FormattersManager.ReadFormattersFromFile(
306+
self._formatters_file)
307+
except KeyError as exception:
308+
raise errors.BadConfigOption(
309+
'Unable to read event formatters from file with error: {0!s}'.format(
310+
exception))
311+
285312
def AddProcessingOptions(self, argument_group):
286313
"""Adds processing options to the argument group
287314
@@ -449,6 +476,8 @@ def ParseOptions(self, options):
449476
helpers_manager.ArgumentHelperManager.ParseOptions(
450477
options, self, names=['data_location'])
451478

479+
self._ReadEventFormattersFromFile()
480+
452481
self._ParseLogFileOptions(options)
453482

454483
self._ParseProcessingOptions(options)

plaso/cli/psteal_tool.py

+25
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from plaso.engine import engine
2424
from plaso.engine import knowledge_base
2525
from plaso.engine import single_process as single_process_engine
26+
from plaso.formatters import manager as formatters_manager
2627
from plaso.lib import errors
2728
from plaso.lib import loggers
2829
from plaso.multi_processing import psort
@@ -83,6 +84,8 @@ class PstealTool(
8384
'And that is how you build a timeline using psteal...',
8485
'']))
8586

87+
_FORMATTERS_FILE_NAME = 'formatters.yaml'
88+
8689
_SOURCE_TYPES_TO_PREPROCESS = frozenset([
8790
dfvfs_definitions.SOURCE_TYPE_DIRECTORY,
8891
dfvfs_definitions.SOURCE_TYPE_STORAGE_MEDIA_DEVICE,
@@ -103,6 +106,7 @@ def __init__(self, input_reader=None, output_writer=None):
103106
self._command_line_arguments = None
104107
self._deduplicate_events = True
105108
self._enable_sigsegv_handler = False
109+
self._formatters_file = None
106110
self._knowledge_base = knowledge_base.KnowledgeBase()
107111
self._number_of_analysis_reports = 0
108112
self._number_of_extraction_workers = 0
@@ -172,6 +176,26 @@ def _PrintAnalysisReportsDetails(
172176

173177
table_view.Write(self._output_writer)
174178

179+
def _ReadEventFormattersFromFile(self):
180+
"""Reads the event formatters the formatters.yaml file.
181+
182+
Raises:
183+
BadConfigOption: if the event formatters file cannot be read.
184+
"""
185+
self._formatters_file = os.path.join(
186+
self._data_location, self._FORMATTERS_FILE_NAME)
187+
if not os.path.isfile(self._formatters_file):
188+
raise errors.BadConfigOption(
189+
'No such event formatters file: {0:s}.'.format(self._formatters_file))
190+
191+
try:
192+
formatters_manager.FormattersManager.ReadFormattersFromFile(
193+
self._formatters_file)
194+
except KeyError as exception:
195+
raise errors.BadConfigOption(
196+
'Unable to read event formatters from file with error: {0!s}'.format(
197+
exception))
198+
175199
def AnalyzeEvents(self):
176200
"""Analyzes events from a plaso storage file and generate a report.
177201
@@ -440,6 +464,7 @@ def ParseOptions(self, options):
440464
options, self, names=['data_location'])
441465

442466
self._ReadParserPresetsFromFile()
467+
self._ReadEventFormattersFromFile()
443468

444469
# The output modules options are dependent on the preferred language
445470
# and preferred time zone options.

plaso/formatters/__init__.py

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# -*- coding: utf-8 -*-
22
"""This file contains an import statement for each formatter."""
33

4-
from plaso.formatters import amcache
54
from plaso.formatters import android_app_usage
65
from plaso.formatters import android_calls
76
from plaso.formatters import android_sms

plaso/formatters/amcache.py

-61
This file was deleted.

plaso/formatters/manager.py

+32-8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from plaso.formatters import default
77
from plaso.formatters import logger
8+
from plaso.formatters import yaml_formatters_file
89

910

1011
class FormattersManager(object):
@@ -13,6 +14,9 @@ class FormattersManager(object):
1314
_formatter_classes = {}
1415
_formatter_objects = {}
1516

17+
# Work-around to prevent the tests re-reading the formatters file.
18+
_file_was_read = False
19+
1620
@classmethod
1721
def DeregisterFormatter(cls, formatter_class):
1822
"""Deregisters a formatter class.
@@ -27,9 +31,8 @@ def DeregisterFormatter(cls, formatter_class):
2731
"""
2832
formatter_data_type = formatter_class.DATA_TYPE.lower()
2933
if formatter_data_type not in cls._formatter_classes:
30-
raise KeyError(
31-
'Formatter class not set for data type: {0:s}.'.format(
32-
formatter_class.DATA_TYPE))
34+
raise KeyError('Formatter class not set for data type: {0:s}.'.format(
35+
formatter_class.DATA_TYPE))
3336

3437
del cls._formatter_classes[formatter_data_type]
3538

@@ -55,8 +58,8 @@ def GetFormatterObject(cls, data_type):
5558
formatter_object = formatter_class()
5659

5760
if not formatter_object:
58-
logger.warning(
59-
'Using default formatter for data type: {0:s}'.format(data_type))
61+
logger.warning('Using default formatter for data type: {0:s}'.format(
62+
data_type))
6063
formatter_object = default.DefaultFormatter()
6164

6265
cls._formatter_objects[data_type] = formatter_object
@@ -95,6 +98,28 @@ def GetSourceStrings(cls, event, event_data):
9598
formatter_object = cls.GetFormatterObject(event_data.data_type)
9699
return formatter_object.GetSources(event, event_data)
97100

101+
@classmethod
102+
def ReadFormattersFromFile(cls, path):
103+
"""Reads formatters from a file.
104+
105+
Args:
106+
path (str): path of file that contains the formatters configuration.
107+
108+
Raises:
109+
KeyError: if formatter class is already set for the corresponding
110+
data type.
111+
"""
112+
if not cls._file_was_read:
113+
formatters_file = yaml_formatters_file.YAMLFormattersFile()
114+
for formatter in formatters_file.ReadFromFile(path):
115+
# TODO: refactor RegisterFormatter to only use formatter objects.
116+
cls.RegisterFormatter(formatter)
117+
118+
data_type = formatter.DATA_TYPE.lower()
119+
cls._formatter_objects[data_type] = formatter
120+
121+
cls._file_was_read = True
122+
98123
@classmethod
99124
def RegisterFormatter(cls, formatter_class):
100125
"""Registers a formatter class.
@@ -110,9 +135,8 @@ def RegisterFormatter(cls, formatter_class):
110135
"""
111136
formatter_data_type = formatter_class.DATA_TYPE.lower()
112137
if formatter_data_type in cls._formatter_classes:
113-
raise KeyError((
114-
'Formatter class already set for data type: {0:s}.').format(
115-
formatter_class.DATA_TYPE))
138+
raise KeyError('Formatter class already set for data type: {0:s}.'.format(
139+
formatter_class.DATA_TYPE))
116140

117141
cls._formatter_classes[formatter_data_type] = formatter_class
118142

plaso/parsers/manager.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ def ReadPresetsFromFile(cls, path):
463463
"""Reads parser and parser plugin presets from a file.
464464
465465
Args:
466-
path (str): path of file that contains the the parser and parser plugin
466+
path (str): path of file that contains the parser and parser plugin
467467
presets configuration.
468468
469469
Raises:

tests/parsers/amcache.py

+5-8
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,15 @@ def testParse(self):
3636
'is-f4510.tmp\\idafree50.tmp')
3737
self.assertEqual(event.full_path, expected_full_path)
3838

39-
expected_sha1 = '82274eef0911a948f91425f5e5b0e730517fe75e'
40-
self.assertEqual(event.sha1, expected_sha1)
39+
self.assertEqual(event.sha1, '82274eef0911a948f91425f5e5b0e730517fe75e')
4140

4241
event = events[1148]
4342

44-
expected_program_name = 'FileInsight - File analysis tool'
45-
self.assertEqual(event.name, expected_program_name)
43+
self.assertEqual(event.name, 'FileInsight - File analysis tool')
44+
self.assertEqual(event.publisher, 'McAfee Inc.')
4645

47-
expected_publisher = 'McAfee Inc.'
48-
self.assertEqual(event.publisher, expected_publisher)
49-
50-
# TODO: add test for message string
46+
expected_message = 'name: FileInsight - File analysis tool'
47+
self._TestGetMessageStrings(event, expected_message, expected_message)
5148

5249
@shared_test_lib.skipUnlessHasTestFile(['SYSTEM'])
5350
def testParseWithSystem(self):

tests/parsers/test_lib.py

+6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
from __future__ import unicode_literals
55

6+
import os
7+
68
from dfdatetime import posix_time as dfdatetime_posix_time
79

810
from dfvfs.lib import definitions as dfvfs_definitions
@@ -175,6 +177,10 @@ def _TestGetMessageStrings(
175177
expected_message (str): expected message string.
176178
expected_short_message (str): expected short message string.
177179
"""
180+
formatters_file_path = os.path.join(self._DATA_PATH, 'formatters.yaml')
181+
formatters_manager.FormattersManager.ReadFormattersFromFile(
182+
formatters_file_path)
183+
178184
formatter_mediator = formatters_mediator.FormatterMediator(
179185
data_location=self._DATA_PATH)
180186
message, message_short = (

0 commit comments

Comments
 (0)