Skip to content

Commit 3e747ab

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

25 files changed

+653
-197
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}'

docs/sources/user/Output-and-formatting.md

+42-6
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ An event formatter is defined as a set of attributes:
9696

9797
* "data_type"; required event data type.
9898
* "boolean_helpers"; optional boolean helpers.
99+
* "custom_helpers"; optional custom helpers.
99100
* "enumeration_helpers"; optional enumeration helpers.
100101
* "message"; required formatter message string, for a basic type, or list of messages string pieces, for a conditional type.
101102
* "separator"; optional conditional message string piece separator, the default is a single space.
@@ -143,14 +144,42 @@ short_message:
143144
- '{path}'
144145
```
145146

146-
boolean helpers are defined as a set of attributes:
147+
Boolean helpers are defined as a set of attributes:
147148

148-
* "input_attribute"; required name of the attribute which the value that needs to be mapped is read from.
149-
* "output_attribute"; required name of the attribute which the mapped value is written to.
149+
* "input_attribute"; required name of the attribute which the value is read from.
150+
* "output_attribute"; required name of the attribute which the formatted value is written to.
150151
* "default_value"; optional default value if there is no corresponding mapping in "values".
151152
* "value_if_false"; optional output value if the boolean input value is False.
152153
* "value_if_true"; optional output value if the boolean input value is True.
153154

155+
#### Custom helpers
156+
157+
Custom helpers can be defined to map a value of an event attribute to custom
158+
formatting code.
159+
160+
```
161+
type: 'conditional'
162+
data_type: 'fs:stat:ntfs'
163+
custom_helpers:
164+
- identifier: 'ntfs_file_reference'
165+
output_attribute: 'file_reference'
166+
message:
167+
- '{display_name}'
168+
- 'File reference: {file_reference}'
169+
short_message:
170+
- '{filename}'
171+
- '{file_reference}'
172+
```
173+
174+
Here `ntfs_file_reference` references the `NTFSFileReferenceFormatterHelper`,
175+
which is defined in `plaso/formatters/file_system.py`.
176+
177+
Custom helpers are defined as a set of attributes:
178+
179+
* "identifier"; required identifier of the custom format helper.
180+
* "input_attribute"; optional name of the attribute which the value is read from.
181+
* "output_attribute"; optional name of the attribute which the formatted value is written to.
182+
154183
#### Enumeration helpers
155184

156185
Enumeration helpers can be defined to map a value of an event attribute to
@@ -186,10 +215,10 @@ short_message:
186215
- '{description}'
187216
```
188217

189-
enumeration helpers are defined as a set of attributes:
218+
Enumeration helpers are defined as a set of attributes:
190219

191-
* "input_attribute"; required name of the attribute which the value that needs to be mapped is read from.
192-
* "output_attribute"; required name of the attribute which the mapped value is written to.
220+
* "input_attribute"; required name of the attribute which the value is read from.
221+
* "output_attribute"; required name of the attribute which the formatted value is written to.
193222
* "default_value"; optional default value if there is no corresponding mapping in "values".
194223
* "values"; required value mappings, contains key value pairs.
195224

@@ -241,10 +270,17 @@ short_message:
241270
- '{flag_values}'
242271
```
243272

273+
Flags helpers are defined as a set of attributes:
274+
275+
* "input_attribute"; required name of the attribute which the value is read from.
276+
* "output_attribute"; required name of the attribute which the formatted value is written to.
277+
* "values"; required value mappings, contains key value pairs.
278+
244279
#### Change log
245280

246281
* 20200227 Added support for formatter configuration files.
247282
* 20200822 Added support for enumeration helpers.
248283
* 20200904 Added support for flags helpers.
249284
* 20200916 Removed source types from formatters.
250285
* 20201220 Added support for boolean helpers.
286+
* 20201227 Added support for custom helpers.

plaso/formatters/chrome.py

+16-12
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,31 @@
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.
1718
1819
Args:
1920
event_values (dict[str, object]): event values.
2021
"""
21-
typed_count = event_values.get('typed_count', 0)
22-
if typed_count == 0:
23-
url_typed_string = '(URL not typed directly)'
24-
elif typed_count == 1:
25-
url_typed_string = '(URL typed {0:d} time)'
26-
else:
27-
url_typed_string = '(URL typed {0:d} times)'
22+
typed_count = event_values.get('typed_count', None)
23+
if typed_count is not None:
24+
if typed_count == 0:
25+
url_typed_string = '(URL not typed directly)'
26+
elif typed_count == 1:
27+
url_typed_string = '(URL typed 1 time)'
28+
elif typed_count > 1:
29+
url_typed_string = '(URL typed {0:d} times)'.format(typed_count)
30+
else:
31+
url_typed_string = typed_count
2832

29-
event_values['url_typed_string'] = url_typed_string
33+
event_values['url_typed_string'] = url_typed_string
3034

3135

3236
manager.FormattersManager.RegisterEventFormatterHelper(
33-
ChromePageVisitedFormatter)
37+
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', None)
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])

0 commit comments

Comments
 (0)