-
Notifications
You must be signed in to change notification settings - Fork 325
/
artifacts.py
717 lines (576 loc) · 24.8 KB
/
artifacts.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
# -*- coding: utf-8 -*-
"""Artifact attribute containers."""
from plaso.containers import interface
from plaso.containers import manager
from plaso.lib import definitions
class ArtifactAttributeContainer(interface.AttributeContainer):
"""Base class to represent an artifact attribute container."""
class SystemSubConfigurationArtifactAttributeContainer(
ArtifactAttributeContainer):
"""System sub configuration artifact attribute container."""
def __init__(self):
"""Initializes a system sub configuration artifact attribute container."""
super(SystemSubConfigurationArtifactAttributeContainer, self).__init__()
self._system_configuration_identifier = None
def GetSystemConfigurationIdentifier(self):
"""Retrieves the identifier of the associated system configuration.
The system configuration identifier is a storage specific value that
requires special handling during serialization.
Returns:
AttributeContainerIdentifier: system configuration identifier or None
when not set.
"""
return self._system_configuration_identifier
def SetSystemConfigurationIdentifier(self, system_configuration_identifier):
"""Sets the identifier of the associated system configuration.
The system configuration identifier is a storage specific value that
requires special handling during serialization.
Args:
system_configuration_identifier (AttributeContainerIdentifier): system
configuration identifier.
"""
self._system_configuration_identifier = system_configuration_identifier
class EnvironmentVariableArtifact(ArtifactAttributeContainer):
"""Environment variable artifact attribute container.
Also see:
https://en.wikipedia.org/wiki/Environment_variable
Attributes:
case_sensitive (bool): True if environment variable name is case sensitive.
name (str): environment variable name such as "SystemRoot" as in
"%SystemRoot%" or "HOME" as in "$HOME".
value (str): environment variable value such as "C:\\Windows" or
"/home/user".
"""
CONTAINER_TYPE = 'environment_variable'
def __init__(self, case_sensitive=True, name=None, value=None):
"""Initializes an environment variable artifact.
Args:
case_sensitive (Optional[bool]): True if environment variable name
is case sensitive.
name (Optional[str]): environment variable name.
value (Optional[str]): environment variable value.
"""
super(EnvironmentVariableArtifact, self).__init__()
self.case_sensitive = case_sensitive
self.name = name
self.value = value
class HostnameArtifact(ArtifactAttributeContainer):
"""Hostname artifact attribute container.
Also see:
https://en.wikipedia.org/wiki/Hostname
Cybox / Stix Hostname Object
Attributes:
name (str): name of the host according to the naming schema.
schema (str): naming schema such as "DNS", "NIS", "SMB/NetBIOS".
"""
CONTAINER_TYPE = 'hostname'
def __init__(self, name=None, schema='DNS'):
"""Initializes a hostname artifact.
Args:
name (Optional[str]): name of the host according to the naming schema.
schema (Optional[str]): naming schema.
"""
super(HostnameArtifact, self).__init__()
self.name = name
self.schema = schema
class OperatingSystemArtifact(ArtifactAttributeContainer):
"""Operating system artifact attribute container.
Attributes:
family (str): operating system family name, such as "Linux", "MacOS"
or "Windows", defined in definitions.OPERATING_SYSTEM_FAMILIES.
This value is used to programmatically link a parser preset to an
operating system and therefore must be one of predefined values.
name (str): operating system name, such as "macOS Mojave" or "Windows XP".
This value is used to programmatically link a parser preset to an
operating system and therefore must be one of predefined values.
product (str): product information, such as "macOS Mojave" or "Windows
Professional XP". This value is typically obtained from the source data.
version (str): version, such as "10.14.1" or "5.1". This value is typically
obtained from the source data.
"""
CONTAINER_TYPE = 'operating_system'
_DEFAULT_FAMILY_AND_VERSION = (
definitions.OPERATING_SYSTEM_FAMILY_UNKNOWN, (0, 0))
_FAMILY_AND_VERSION_PER_NAME = {
'Windows 2000': (definitions.OPERATING_SYSTEM_FAMILY_WINDOWS_NT, (5, 0)),
'Windows 2003': (definitions.OPERATING_SYSTEM_FAMILY_WINDOWS_NT, (5, 2)),
'Windows 2003 R2': (
definitions.OPERATING_SYSTEM_FAMILY_WINDOWS_NT, (5, 2)),
'Windows 2008': (definitions.OPERATING_SYSTEM_FAMILY_WINDOWS_NT, (6, 0)),
'Windows 2008 R2': (
definitions.OPERATING_SYSTEM_FAMILY_WINDOWS_NT, (6, 1)),
'Windows 2012': (definitions.OPERATING_SYSTEM_FAMILY_WINDOWS_NT, (6, 2)),
'Windows 2012 R2': (
definitions.OPERATING_SYSTEM_FAMILY_WINDOWS_NT, (6, 3)),
'Windows 2016': (definitions.OPERATING_SYSTEM_FAMILY_WINDOWS_NT, (10, 0)),
'Windows 2019': (definitions.OPERATING_SYSTEM_FAMILY_WINDOWS_NT, (10, 0)),
'Windows 7': (definitions.OPERATING_SYSTEM_FAMILY_WINDOWS_NT, (6, 1)),
'Windows 8': (definitions.OPERATING_SYSTEM_FAMILY_WINDOWS_NT, (6, 2)),
'Windows 8.1': (definitions.OPERATING_SYSTEM_FAMILY_WINDOWS_NT, (6, 3)),
'Windows 10': (definitions.OPERATING_SYSTEM_FAMILY_WINDOWS_NT, (10, 0)),
'Windows Vista': (definitions.OPERATING_SYSTEM_FAMILY_WINDOWS_NT, (6, 0)),
'Windows XP': (definitions.OPERATING_SYSTEM_FAMILY_WINDOWS_NT, (5, 1))}
def __init__(self, family=None, product=None, version=None):
"""Initializes an operating system artifact.
Args:
family (Optional[str]): operating system family name, such as "Linux",
"MacOS" or "Windows", defined in definitions.OPERATING_SYSTEM_FAMILIES.
This value is used to programmatically link a parser preset to an
operating system and therefore must be one of predefined values.
product (Optional[str]): product information, such as "macOS Mojave" or
"Windows Professional XP". This value is typically obtained from the
source data.
version (Optional[str]): version, such as "10.14.1" or "5.1". This value
is typically obtained from the source data.
"""
super(OperatingSystemArtifact, self).__init__()
self.family = family
self.name = None
self.product = product
self.version = version
if product:
self.name = self._GetNameFromProduct()
@property
def version_tuple(self):
"""tuple[int]: version tuple or None if version is not set or invalid."""
try:
# pylint: disable=consider-using-generator
return tuple([int(digit, 10) for digit in self.version.split('.')])
except (AttributeError, TypeError, ValueError):
return None
def _GetNameFromProduct(self):
"""Determines the predefined operating system name from the product.
Returns:
str: operating system name, such as "macOS Mojave" or "Windows XP" or
None if the name cannot be determined. This value is used to
programmatically link a parser preset to an operating system and
therefore must be one of predefined values.
"""
product = self.product or ''
product = product.split(' ')
product_lower_case = [segment.lower() for segment in product]
number_of_segments = len(product)
if 'windows' in product_lower_case:
segment_index = product_lower_case.index('windows') + 1
if product_lower_case[segment_index] in ('(r)', 'server', 'web'):
segment_index += 1
# Check if the version has a suffix.
suffix_segment_index = segment_index + 1
if (suffix_segment_index < number_of_segments and
product_lower_case[suffix_segment_index] == 'r2'):
return 'Windows {0:s} R2'.format(product[segment_index])
return 'Windows {0:s}'.format(product[segment_index])
return None
def IsEquivalent(self, other):
"""Determines if 2 operating system artifacts are equivalent.
This function compares the operating systems based in order of:
* name derived from product
* family and version
* family
Args:
other (OperatingSystemArtifact): operating system artifact attribute
container to compare with.
Returns:
bool: True if the operating systems are considered equivalent, False if
the most specific criteria do no match, or no criteria are available.
"""
if self.name and other.name:
return self.name == other.name
if self.name:
self_family, self_version_tuple = self._FAMILY_AND_VERSION_PER_NAME.get(
self.name, self._DEFAULT_FAMILY_AND_VERSION)
return (
self_family == other.family and
self_version_tuple == other.version_tuple)
if self.family and self.version:
if other.name:
other_family, other_version_tuple = (
self._FAMILY_AND_VERSION_PER_NAME.get(
other.name, self._DEFAULT_FAMILY_AND_VERSION))
else:
other_family = other.family
other_version_tuple = other.version_tuple
return (
self.family == other_family and
self.version_tuple == other_version_tuple)
if self.family:
if other.name:
other_family, _ = self._FAMILY_AND_VERSION_PER_NAME.get(
other.name, self._DEFAULT_FAMILY_AND_VERSION)
else:
other_family = other.family
return self.family == other_family
return False
class PathArtifact(ArtifactAttributeContainer):
"""Path artifact attribute container.
Attributes:
data_stream (str): name of a data stream.
path_segment_separator (str): path segment separator.
path_segments (list[str]): path segments.
"""
CONTAINER_TYPE = 'path'
def __init__(self, data_stream=None, path=None, path_segment_separator='/'):
"""Initializes a path artifact.
Args:
data_stream (Optional[str]): name of a data stream.
path (Optional[str]): a path.
path_segment_separator (Optional[str]): path segment separator.
"""
super(PathArtifact, self).__init__()
self.data_stream = data_stream
self.path_segment_separator = path_segment_separator
self.path_segments = self._SplitPath(path, path_segment_separator)
def __eq__(self, other):
"""Determines if the path is equal to other.
Args:
other (str): path to compare against.
Returns:
bool: True if the path are equal to other.
"""
if not isinstance(other, str):
return False
other_path_segments = self._SplitPath(other, self.path_segment_separator)
return self.path_segments == other_path_segments
def __ge__(self, other):
"""Determines if the path are greater than or equal to other.
Args:
other (str): path to compare against.
Returns:
bool: True if the path are greater than or equal to other.
Raises:
ValueError: if other is not an instance of string.
"""
if not isinstance(other, str):
raise ValueError('Other not an instance of string.')
other_path_segments = self._SplitPath(other, self.path_segment_separator)
return self.path_segments >= other_path_segments
def __gt__(self, other):
"""Determines if the path are greater than other.
Args:
other (str): path to compare against.
Returns:
bool: True if the path are greater than other.
Raises:
ValueError: if other is not an instance of string.
"""
if not isinstance(other, str):
raise ValueError('Other not an instance of string.')
other_path_segments = self._SplitPath(other, self.path_segment_separator)
return self.path_segments > other_path_segments
def __le__(self, other):
"""Determines if the path are greater than or equal to other.
Args:
other (str): path to compare against.
Returns:
bool: True if the path are greater than or equal to other.
Raises:
ValueError: if other is not an instance of string.
"""
if not isinstance(other, str):
raise ValueError('Other not an instance of string.')
other_path_segments = self._SplitPath(other, self.path_segment_separator)
return self.path_segments <= other_path_segments
def __lt__(self, other):
"""Determines if the path are less than other.
Args:
other (str): path to compare against.
Returns:
bool: True if the path are less than other.
Raises:
ValueError: if other is not an instance of string.
"""
if not isinstance(other, str):
raise ValueError('Other not an instance of string.')
other_path_segments = self._SplitPath(other, self.path_segment_separator)
return self.path_segments < other_path_segments
def __ne__(self, other):
"""Determines if the path are not equal to other.
Args:
other (str): path to compare against.
Returns:
bool: True if the path are not equal to other.
"""
if not isinstance(other, str):
return False
other_path_segments = self._SplitPath(other, self.path_segment_separator)
return self.path_segments != other_path_segments
def _SplitPath(self, path, path_segment_separator):
"""Splits a path.
Args:
path (str): a path.
path_segment_separator (str): path segment separator.
Returns:
list[str]: path segments.
"""
path = path or ''
split_path = path.split(path_segment_separator)
path_segments = [split_path[0]]
path_segments.extend(list(filter(None, split_path[1:])))
return path_segments
def ContainedIn(self, other):
"""Determines if the path are contained in other.
Args:
other (str): path to compare against.
Returns:
bool: True if the path is contained in other.
"""
if isinstance(other, str):
number_of_path_segments = len(self.path_segments)
other_path_segments = self._SplitPath(other, self.path_segment_separator)
number_of_other_path_segments = len(other_path_segments)
if number_of_path_segments < number_of_other_path_segments:
maximum_compare_length = (
number_of_other_path_segments - number_of_path_segments + 1)
for compare_start_index in range(0, maximum_compare_length):
compare_end_index = compare_start_index + number_of_path_segments
compare_path_segments = other_path_segments[
compare_start_index:compare_end_index]
if self.path_segments == compare_path_segments:
return True
return False
class SourceConfigurationArtifact(ArtifactAttributeContainer):
"""Source configuration artifact attribute container.
The source configuration contains the configuration data of a source
that is (or going to be) processed such as volume in a storage media
image or a mounted directory.
Attributes:
mount_path (str): path of a "mounted" directory input source.
path_spec (dfvfs.PathSpec): path specification of the source that is
processed.
system_configuration (SystemConfigurationArtifact): system configuration of
a specific system installation, such as Windows or Linux, detected by
the pre-processing on the source.
"""
CONTAINER_TYPE = 'source_configuration'
def __init__(self, path_spec=None):
"""Initializes a source configuration artifact.
Args:
path_spec (Optional[dfvfs.PathSpec]): path specification of the source
that is processed.
"""
super(SourceConfigurationArtifact, self).__init__()
self.mount_path = None
self.path_spec = path_spec
self.system_configuration = None
class SystemConfigurationArtifact(ArtifactAttributeContainer):
"""System configuration artifact attribute container.
The system configuration contains the configuration data of a specific
system installation such as Windows or Linux.
Attributes:
available_time_zones (list[TimeZone]): available time zones.
code_page (str): system code page.
hostname (HostnameArtifact): hostname.
keyboard_layout (str): keyboard layout.
language (str): system language.
operating_system (str): operating system for example "MacOS" or "Windows".
operating_system_product (str): operating system product for example
"Windows XP".
operating_system_version (str): operating system version for example
"10.9.2" or "8.1".
time_zone (str): system time zone.
user_accounts (list[UserAccountArtifact]): user accounts.
"""
CONTAINER_TYPE = 'system_configuration'
def __init__(self, code_page=None, language=None, time_zone=None):
"""Initializes a system configuration artifact.
Args:
code_page (Optional[str]): system code page.
language (Optional[str]): system language.
time_zone (Optional[str]): system time zone.
"""
super(SystemConfigurationArtifact, self).__init__()
self.available_time_zones = []
self.code_page = code_page
self.hostname = None
self.keyboard_layout = None
self.language = language
self.operating_system = None
self.operating_system_product = None
self.operating_system_version = None
self.time_zone = time_zone
self.user_accounts = []
class TimeZoneArtifact(ArtifactAttributeContainer):
"""Time zone artifact attribute container.
Attributes:
localized_name (str): name describing the time zone in localized language
for example "Greenwich (standaardtijd)".
mui_form (str): MUI form of the name describing the time zone for example
"@tzres.dll,-112".
name (str): name describing the time zone for example "Greenwich Standard
Time".
offset (int): time zone offset in number of minutes from UTC.
"""
CONTAINER_TYPE = 'time_zone'
def __init__(
self, localized_name=None, mui_form=None, name=None, offset=None):
"""Initializes a time zone artifact.
Args:
localized_name (Optional[str]): name describing the time zone in localized
language for example "Greenwich (standaardtijd)".
mui_form (Optional[str]): MUI form of the name describing the time zone
for example "@tzres.dll,-112".
name (Optional[str]): name describing the time zone for example "Greenwich
Standard Time".
offset (Optional[int]): time zone offset in number of minutes from UTC.
"""
super(TimeZoneArtifact, self).__init__()
self.localized_name = localized_name
self.mui_form = mui_form
self.name = name
self.offset = offset
class UserAccountArtifact(ArtifactAttributeContainer):
"""User account artifact attribute container.
Also see:
Cybox / Stix User Account Object
Attributes:
full_name (str): name describing the user.
group_identifier (str): identifier of the primary group the user is part of.
identifier (str): user identifier.
user_directory (str): path of the user (or home or profile) directory.
username (str): name uniquely identifying the user.
"""
CONTAINER_TYPE = 'user_account'
def __init__(
self, full_name=None, group_identifier=None, identifier=None,
path_separator='/', user_directory=None, username=None):
"""Initializes a user account artifact.
Args:
full_name (Optional[str]): name describing the user.
group_identifier (Optional[str]): identifier of the primary group
the user is part of.
identifier (Optional[str]): user identifier.
path_separator (Optional[str]): path segment separator.
user_directory (Optional[str]): path of the user (or home or profile)
directory.
username (Optional[str]): name uniquely identifying the user.
"""
super(UserAccountArtifact, self).__init__()
self._path_separator = path_separator
self.full_name = full_name
self.group_identifier = group_identifier
self.identifier = identifier
# TODO: add shell.
self.user_directory = user_directory
self.username = username
def GetUserDirectoryPathSegments(self):
"""Retrieves the path segments of the user directory.
Returns:
list[str]: path segments of the user directory or an empty list if no
user directory is set.
"""
if not self.user_directory:
return []
return self.user_directory.split(self._path_separator)
class WindowsEventLogMessageFileArtifact(ArtifactAttributeContainer):
"""Windows EventLog message file attribute container.
Attributes:
path (str): path.
windows_path (str): path as defined by the Windows EventLog provider.
"""
CONTAINER_TYPE = 'windows_eventlog_message_file'
SCHEMA = {
'path': 'str',
'windows_path': 'str'}
def __init__(self, path=None, windows_path=None):
"""Initializes a Windows EventLog message file artifact.
Args:
path (Optional[str]): path.
windows_path (Optional[str]): path as defined by the Window EventLog
provider.
"""
super(WindowsEventLogMessageFileArtifact, self).__init__()
self.path = path
self.windows_path = windows_path
class WindowsEventLogMessageStringArtifact(ArtifactAttributeContainer):
"""Windows EventLog message string attribute container.
Attributes:
language_identifier (str): language identifier.
message_identifier (int): message identifier.
string (str): string.
"""
CONTAINER_TYPE = 'windows_eventlog_message_string'
SCHEMA = {
'_message_file_row_identifier': 'AttributeContainerIdentifier',
'language_identifier': 'int',
'message_identifier': 'int',
'string': 'str'}
def __init__(
self, language_identifier=None, message_identifier=None, string=None):
"""Initializes a Windows EventLog message string artifact.
Args:
language_identifier (Optional[str]): language identifier.
message_identifier (Optional[int]): message identifier.
string (Optional[str]): string.
"""
super(WindowsEventLogMessageStringArtifact, self).__init__()
self._message_file_identifier = None
self._message_file_row_identifier = None
self.language_identifier = language_identifier
self.message_identifier = message_identifier
self.string = string
def GetMessageFileIdentifier(self):
"""Retrieves the identifier of the associated message file.
Returns:
AttributeContainerIdentifier: message file identifier or None when
not set.
"""
return self._message_file_identifier
def SetMessageFileIdentifier(self, message_file_identifier):
"""Sets the identifier of the associated message file.
Args:
message_file_identifier (AttributeContainerIdentifier): message file
identifier.
"""
self._message_file_identifier = message_file_identifier
class WindowsEventLogProviderArtifact(
SystemSubConfigurationArtifactAttributeContainer):
"""Windows EventLog provider artifact attribute container.
Attributes:
category_message_files (list[str]): filenames of the category message files.
event_message_files (list[str]): filenames of the event message files.
identifier (str): identifier of the provider, contains a GUID.
log_source (str): name of the Windows EventLog source.
log_source_alias (str): alternate name of the Windows EventLog source.
log_type (str): Windows EventLog type.
parameter_message_files (list[str]): filenames of the parameter message
files.
"""
CONTAINER_TYPE = 'windows_eventlog_provider'
SCHEMA = {
'_system_configuration_row_identifier': 'AttributeContainerIdentifier',
'category_message_files': 'List[str]',
'event_message_files': 'List[str]',
'identifier': 'str',
'log_source': 'str',
'log_source_alias': 'str',
'log_type': 'str',
'parameter_message_files': 'List[str]'}
def __init__(
self, category_message_files=None, event_message_files=None,
identifier=None, log_source=None, log_type=None,
parameter_message_files=None):
"""Initializes a Windows EventLog provider artifact.
Args:
category_message_files (Optional[list[str]]): filenames of the category
message files.
event_message_files (Optional[list[str]]): filenames of the event message
files.
identifier (Optional[str]): identifier of the provider, contains a GUID.
log_source (Optional[str]): name of the Windows EventLog source.
log_type (Optional[str]): Windows EventLog type.
parameter_message_files (Optional[list[str]]): filenames of the parameter
message files.
"""
super(WindowsEventLogProviderArtifact, self).__init__()
self.category_message_files = category_message_files
self.event_message_files = event_message_files
self.identifier = identifier
self.log_source = log_source
self.log_source_alias = None
self.log_type = log_type
self.parameter_message_files = parameter_message_files
manager.AttributeContainersManager.RegisterAttributeContainers([
EnvironmentVariableArtifact, HostnameArtifact, OperatingSystemArtifact,
PathArtifact, SourceConfigurationArtifact, SystemConfigurationArtifact,
TimeZoneArtifact, UserAccountArtifact, WindowsEventLogMessageFileArtifact,
WindowsEventLogMessageStringArtifact, WindowsEventLogProviderArtifact])