Skip to content

Commit a3b3c43

Browse files
committed
Added support for custom formatter helpers log2timeline#444
1 parent 76225d5 commit a3b3c43

24 files changed

+366
-147
lines changed

data/formatters/browser.yaml

+21
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ boolean_helpers:
7676
- input_attribute: 'url_hidden'
7777
output_attribute: 'url_hidden_string'
7878
value_if_true: '(URL hidden)'
79+
custom_helpers:
80+
- identifier: 'chrome_history_typed_count'
81+
output_attribute: 'url_typed_string'
7982
enumeration_helpers:
8083
- input_attribute: 'page_transition_type'
8184
output_attribute: 'page_transition'
@@ -126,6 +129,11 @@ short_message:
126129
---
127130
type: 'conditional'
128131
data_type: 'chrome:preferences:content_settings:exceptions'
132+
custom_helpers:
133+
- identifier: 'chrome_preferences_primary_url'
134+
output_attribute: 'primary_url'
135+
- identifier: 'chrome_preferences_secondary_url'
136+
output_attribute: 'secondary_url'
129137
message:
130138
- 'Permission {permission}'
131139
- 'used by {primary_url}'
@@ -253,6 +261,11 @@ short_message: '{title}'
253261
---
254262
type: 'conditional'
255263
data_type: 'firefox:places:page_visited'
264+
custom_helpers:
265+
- identifier: 'firefox_history_typed_count'
266+
output_attribute: 'url_typed_string'
267+
- identifier: 'firefox_history_url_hidden'
268+
output_attribute: 'url_hidden_string'
256269
enumeration_helpers:
257270
- input_attribute: 'visit_type'
258271
output_attribute: 'transition_string'
@@ -290,6 +303,9 @@ boolean_helpers:
290303
- input_attribute: 'recovered'
291304
output_attribute: 'recovered_string'
292305
value_if_true: '[Recovered Entry]'
306+
custom_helpers:
307+
- identifier: 'msiecf_cached_path'
308+
output_attribute: 'cached_file_path'
293309
message:
294310
- 'Cached file: {cached_file_path}'
295311
- 'Cached file size: {cached_file_size}'
@@ -315,6 +331,11 @@ boolean_helpers:
315331
- input_attribute: 'recovered'
316332
output_attribute: 'recovered_string'
317333
value_if_true: '[Recovered Entry]'
334+
custom_helpers:
335+
- identifier: 'msiecf_cached_path'
336+
output_attribute: 'cached_file_path'
337+
- identifier: 'msiecf_http_headers'
338+
output_attribute: 'http_headers'
318339
message:
319340
- 'Location: {url}'
320341
- 'Number of hits: {number_of_hits}'

data/formatters/generic.yaml

+12
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,11 @@ short_message: '{filename}'
183183
---
184184
type: 'conditional'
185185
data_type: 'fs:ntfs:usn_change'
186+
custom_helpers:
187+
- identifier: 'ntfs_file_reference'
188+
output_attribute: 'file_reference'
189+
- identifier: 'ntfs_parent_file_reference'
190+
output_attribute: 'parent_file_reference'
186191
flags_helpers:
187192
- input_attribute: 'update_reason_flags'
188193
output_attribute: 'update_reason'
@@ -245,6 +250,13 @@ boolean_helpers:
245250
- input_attribute: 'is_allocated'
246251
output_attribute: 'unallocated'
247252
value_if_false: 'unallocated'
253+
custom_helpers:
254+
- identifier: 'ntfs_file_reference'
255+
output_attribute: 'file_reference'
256+
- identifier: 'ntfs_parent_file_reference'
257+
output_attribute: 'parent_file_reference'
258+
- identifier: 'ntfs_path_hints'
259+
output_attribute: 'path_hints'
248260
enumeration_helpers:
249261
- input_attribute: 'attribute_type'
250262
output_attribute: 'attribute_name'

data/formatters/windows.yaml

+16
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,11 @@ short_message:
161161
---
162162
type: 'conditional'
163163
data_type: 'windows:lnk:link'
164+
custom_helpers:
165+
- identifier: 'windows_shortcut_description'
166+
output_attribute: 'description'
167+
- identifier: 'windows_shortcut_linked_path'
168+
output_attribute: 'linked_path'
164169
message:
165170
- '[{description}]'
166171
- 'File size: {file_size}'
@@ -224,6 +229,11 @@ short_message:
224229
---
225230
type: 'conditional'
226231
data_type: 'windows:prefetch:execution'
232+
custom_helpers:
233+
- identifier: 'windows_prefetch_path_hints'
234+
output_attribute: 'path_hints'
235+
- identifier: 'windows_prefetch_volumes_string'
236+
output_attribute: 'volumes_string'
227237
message:
228238
- 'Prefetch'
229239
- '[{executable}] was executed -'
@@ -330,6 +340,9 @@ short_message:
330340
---
331341
type: 'conditional'
332342
data_type: 'windows:registry:key_value'
343+
custom_helpers:
344+
- identifier: 'windows_registry_values'
345+
output_attribute: 'values'
333346
message:
334347
- '[{key_path}]'
335348
- '{values}'
@@ -637,6 +650,9 @@ short_message: '[{key_path}] {entries}'
637650
---
638651
type: 'conditional'
639652
data_type: 'windows:shell_item:file_entry'
653+
custom_helpers:
654+
- identifier: 'shell_item_file_entry_name'
655+
output_attribute: 'file_entry_name'
640656
message:
641657
- 'Name: {name}'
642658
- 'Long name: {long_name}'

plaso/formatters/chrome.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77
from plaso.formatters import manager
88

99

10-
class ChromePageVisitedFormatter(interface.CustomEventFormatterHelper):
11-
"""Custom formatter for Chrome page visited event values."""
10+
class ChromeHistoryTypedCountFormatterHelper(
11+
interface.CustomEventFormatterHelper):
12+
"""Google Chrome history typed count formatter helper."""
1213

13-
DATA_TYPE = 'chrome:history:page_visited'
14+
IDENTIFIER = 'chrome_history_typed_count'
1415

1516
def FormatEventValues(self, event_values):
1617
"""Formats event values using the helper.
@@ -30,4 +31,4 @@ def FormatEventValues(self, event_values):
3031

3132

3233
manager.FormattersManager.RegisterEventFormatterHelper(
33-
ChromePageVisitedFormatter)
34+
ChromeHistoryTypedCountFormatterHelper)

plaso/formatters/chrome_preferences.py

+24-10
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,36 @@
77
from plaso.formatters import manager
88

99

10-
class ChromeContentSettingsExceptionsFormatter(
10+
class ChromePreferencesPrimaryURLFormatterHelper(
1111
interface.CustomEventFormatterHelper):
12-
"""Custom formatter for Chrome content settings exceptions event values."""
12+
"""Google Chrome preferences primary URL formatter helper."""
1313

14-
DATA_TYPE = 'chrome:preferences:content_settings:exceptions'
14+
IDENTIFIER = 'chrome_preferences_primary_url'
1515

1616
def FormatEventValues(self, event_values):
1717
"""Formats event values using the helper.
1818
1919
Args:
2020
event_values (dict[str, object]): event values.
2121
"""
22-
# There is apparently a bug, either in GURL.cc or
22+
primary_url = event_values.get('primary_url', None)
23+
if primary_url == '':
24+
event_values['primary_url'] = 'local file'
25+
26+
27+
class ChromePreferencesSecondaryURLFormatterHelper(
28+
interface.CustomEventFormatterHelper):
29+
"""Google Chrome preferences secondary URL formatter helper."""
30+
31+
IDENTIFIER = 'chrome_preferences_secondary_url'
32+
33+
def FormatEventValues(self, event_values):
34+
"""Formats event values using the helper.
35+
36+
Args:
37+
event_values (dict[str, object]): event values.
38+
"""
39+
# There appears to be an issue in either GURL.cc or
2340
# content_settings_pattern.cc where URLs with file:// scheme are stored in
2441
# the URL as an empty string, which is later detected as being Invalid, and
2542
# Chrome produces the following example logs:
@@ -29,19 +46,16 @@ def FormatEventValues(self, event_values):
2946
# More research needed, could be related to https://crbug.com/132659
3047

3148
primary_url = event_values.get('primary_url', None)
32-
if primary_url == '':
33-
primary_url = 'local file'
34-
3549
secondary_url = event_values.get('secondary_url', None)
3650
if secondary_url == '':
3751
secondary_url = 'local file'
3852

3953
if secondary_url in (primary_url, '*'):
4054
secondary_url = None
4155

42-
event_values['primary_url'] = primary_url
4356
event_values['secondary_url'] = secondary_url
4457

4558

46-
manager.FormattersManager.RegisterEventFormatterHelper(
47-
ChromeContentSettingsExceptionsFormatter)
59+
manager.FormattersManager.RegisterEventFormatterHelpers([
60+
ChromePreferencesPrimaryURLFormatterHelper,
61+
ChromePreferencesSecondaryURLFormatterHelper])

plaso/formatters/file_system.py

+24-20
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
from plaso.formatters import manager
88

99

10-
class NTFSFileStatEventFormatter(interface.CustomEventFormatterHelper):
11-
"""Custom formatter for NTFS file system stat event values."""
10+
class NTFSFileReferenceFormatterHelper(interface.CustomEventFormatterHelper):
11+
"""NTFS file reference formatter helper."""
1212

13-
DATA_TYPE = 'fs:stat:ntfs'
13+
IDENTIFIER = 'ntfs_file_reference'
1414

1515
def FormatEventValues(self, event_values):
1616
"""Formats event values using the helper.
@@ -23,37 +23,41 @@ def FormatEventValues(self, event_values):
2323
event_values['file_reference'] = '{0:d}-{1:d}'.format(
2424
file_reference & 0xffffffffffff, file_reference >> 48)
2525

26+
27+
class NTFSParentFileReferenceFormatterHelper(
28+
interface.CustomEventFormatterHelper):
29+
"""NTFS parent file reference formatter helper."""
30+
31+
IDENTIFIER = 'ntfs_parent_file_reference'
32+
33+
def FormatEventValues(self, event_values):
34+
"""Formats event values using the helper.
35+
36+
Args:
37+
event_values (dict[str, object]): event values.
38+
"""
2639
parent_file_reference = event_values.get('parent_file_reference', None)
2740
if parent_file_reference:
2841
event_values['parent_file_reference'] = '{0:d}-{1:d}'.format(
2942
parent_file_reference & 0xffffffffffff, parent_file_reference >> 48)
3043

31-
path_hints = event_values.get('path_hints', [])
32-
if path_hints:
33-
event_values['path_hints'] = ';'.join(path_hints)
34-
3544

36-
class NTFSUSNChangeEventFormatter(interface.CustomEventFormatterHelper):
37-
"""Custom formatter for NTFS USN change event values."""
45+
class NTFSPathHintsFormatterHelper(interface.CustomEventFormatterHelper):
46+
"""NTFS path hints formatter helper."""
3847

39-
DATA_TYPE = 'fs:ntfs:usn_change'
48+
IDENTIFIER = 'ntfs_path_hints'
4049

4150
def FormatEventValues(self, event_values):
4251
"""Formats event values using the helper.
4352
4453
Args:
4554
event_values (dict[str, object]): event values.
4655
"""
47-
file_reference = event_values.get('file_reference', None)
48-
if file_reference:
49-
event_values['file_reference'] = '{0:d}-{1:d}'.format(
50-
file_reference & 0xffffffffffff, file_reference >> 48)
51-
52-
parent_file_reference = event_values.get('parent_file_reference', None)
53-
if parent_file_reference:
54-
event_values['parent_file_reference'] = '{0:d}-{1:d}'.format(
55-
parent_file_reference & 0xffffffffffff, parent_file_reference >> 48)
56+
path_hints = event_values.get('path_hints', [])
57+
if path_hints:
58+
event_values['path_hints'] = ';'.join(path_hints)
5659

5760

5861
manager.FormattersManager.RegisterEventFormatterHelpers([
59-
NTFSFileStatEventFormatter, NTFSUSNChangeEventFormatter])
62+
NTFSFileReferenceFormatterHelper, NTFSParentFileReferenceFormatterHelper,
63+
NTFSPathHintsFormatterHelper])

plaso/formatters/firefox.py

+24-9
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,18 @@
77
from plaso.formatters import manager
88

99

10-
class FirefoxPageVisitFormatter(interface.CustomEventFormatterHelper):
11-
"""Custom formatter for Firefox page visited event values."""
10+
class FirefoxHistoryTypedCountFormatterHelper(
11+
interface.CustomEventFormatterHelper):
12+
"""Mozilla Firefox history typed count formatter helper."""
1213

13-
DATA_TYPE = 'firefox:places:page_visited'
14+
IDENTIFIER = 'firefox_history_typed_count'
1415

1516
def FormatEventValues(self, event_values):
1617
"""Formats event values using the helper.
1718
1819
Args:
1920
event_values (dict[str, object]): event values.
2021
"""
21-
hidden = event_values.get('hidden', None)
22-
if hidden == '1':
23-
event_values['url_hidden_string'] = '(URL hidden)'
24-
2522
typed = event_values.get('typed', None)
2623
if typed == '1':
2724
url_typed_string = '(URL directly typed)'
@@ -31,5 +28,23 @@ def FormatEventValues(self, event_values):
3128
event_values['url_typed_string'] = url_typed_string
3229

3330

34-
manager.FormattersManager.RegisterEventFormatterHelper(
35-
FirefoxPageVisitFormatter)
31+
class FirefoxHistoryURLHiddenFormatterHelper(
32+
interface.CustomEventFormatterHelper):
33+
"""Mozilla Firefox history URL hidden formatter helper."""
34+
35+
IDENTIFIER = 'firefox_history_url_hidden'
36+
37+
def FormatEventValues(self, event_values):
38+
"""Formats event values using the helper.
39+
40+
Args:
41+
event_values (dict[str, object]): event values.
42+
"""
43+
hidden = event_values.get('hidden', None)
44+
if hidden == '1':
45+
event_values['url_hidden_string'] = '(URL hidden)'
46+
47+
48+
manager.FormattersManager.RegisterEventFormatterHelpers([
49+
FirefoxHistoryTypedCountFormatterHelper,
50+
FirefoxHistoryURLHiddenFormatterHelper])

plaso/formatters/interface.py

+17-4
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ class CustomEventFormatterHelper(EventFormatterHelper):
8181
"""Base class for a helper for custom formatting of event data."""
8282

8383
DATA_TYPE = ''
84+
IDENTIFIER = ''
8485

8586
@abc.abstractmethod
8687
def FormatEventValues(self, event_values):
@@ -195,6 +196,7 @@ class EventFormatter(object):
195196
event object attribute is defined as {attribute_name}.
196197
197198
Attributes:
199+
custom_helpers (list[str]): identifiers of custom event formatter helpers.
198200
helpers (list[EventFormatterHelper]): event formatter helpers.
199201
"""
200202

@@ -208,10 +210,6 @@ class EventFormatter(object):
208210
FORMAT_STRING = ''
209211
FORMAT_STRING_SHORT = ''
210212

211-
# The source short and long strings.
212-
SOURCE_SHORT = 'LOG'
213-
SOURCE_LONG = ''
214-
215213
# The format string can be defined as:
216214
# {name}, {name:format}, {name!conversion}, {name!conversion:format}
217215
_FORMAT_STRING_ATTRIBUTE_NAME_RE = re.compile(
@@ -221,6 +219,7 @@ def __init__(self):
221219
"""Initializes an event formatter object."""
222220
super(EventFormatter, self).__init__()
223221
self._format_string_attribute_names = None
222+
self.custom_helpers = []
224223
self.helpers = []
225224

226225
def _FormatMessage(self, format_string, event_values):
@@ -309,6 +308,20 @@ def GetFormatStringAttributeNames(self):
309308

310309
return set(self._format_string_attribute_names)
311310

311+
# pylint: disable=unused-argument
312+
def AddCustomHelper(
313+
self, identifier, input_attribute=None, output_attribute=None):
314+
"""Adds a custom event formatter helper.
315+
316+
Args:
317+
identifier (str): identifier.
318+
input_attribute (Optional[str]): name of the attribute that contains
319+
the input value.
320+
output_attribute (Optional[str]): name of the attribute where the
321+
output value should be stored.
322+
"""
323+
self.custom_helpers.append(identifier)
324+
312325
def AddHelper(self, helper):
313326
"""Adds an event formatter helper.
314327

0 commit comments

Comments
 (0)