dissect.target 3.17.dev37__py3-none-any.whl → 3.18__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. dissect/target/exceptions.py +4 -0
  2. dissect/target/filesystem.py +0 -10
  3. dissect/target/helpers/cache.py +3 -1
  4. dissect/target/helpers/hashutil.py +0 -40
  5. dissect/target/helpers/protobuf.py +6 -10
  6. dissect/target/helpers/ssh.py +3 -4
  7. dissect/target/loaders/mqtt.py +147 -2
  8. dissect/target/loaders/raw.py +7 -0
  9. dissect/target/plugins/apps/av/mcafee.py +3 -0
  10. dissect/target/plugins/apps/av/sophos.py +6 -0
  11. dissect/target/plugins/apps/av/symantec.py +6 -0
  12. dissect/target/plugins/apps/av/trendmicro.py +8 -3
  13. dissect/target/plugins/apps/browser/chromium.py +12 -0
  14. dissect/target/plugins/apps/browser/firefox.py +13 -1
  15. dissect/target/plugins/apps/browser/iexplore.py +6 -0
  16. dissect/target/plugins/apps/container/docker.py +1 -1
  17. dissect/target/plugins/os/unix/etc/__init__.py +0 -0
  18. dissect/target/plugins/os/unix/etc/etc.py +77 -0
  19. dissect/target/plugins/os/unix/history.py +1 -1
  20. dissect/target/plugins/os/unix/linux/cmdline.py +3 -0
  21. dissect/target/plugins/os/unix/linux/environ.py +3 -0
  22. dissect/target/plugins/os/unix/linux/processes.py +3 -0
  23. dissect/target/plugins/os/unix/linux/sockets.py +15 -0
  24. dissect/target/plugins/os/unix/locate/gnulocate.py +1 -2
  25. dissect/target/plugins/os/unix/locate/mlocate.py +3 -4
  26. dissect/target/plugins/os/unix/locate/plocate.py +34 -25
  27. dissect/target/plugins/os/unix/log/atop.py +6 -4
  28. dissect/target/plugins/os/unix/log/journal.py +5 -4
  29. dissect/target/plugins/os/unix/log/lastlog.py +2 -3
  30. dissect/target/plugins/os/unix/log/utmp.py +6 -7
  31. dissect/target/plugins/os/windows/_os.py +17 -6
  32. dissect/target/plugins/os/windows/activitiescache.py +3 -0
  33. dissect/target/plugins/os/windows/adpolicy.py +3 -4
  34. dissect/target/plugins/os/windows/catroot.py +6 -0
  35. dissect/target/plugins/os/windows/credhist.py +1 -2
  36. dissect/target/plugins/os/windows/datetime.py +3 -4
  37. dissect/target/plugins/os/windows/defender.py +221 -5
  38. dissect/target/plugins/os/windows/defender_helpers/__init__.py +0 -0
  39. dissect/target/plugins/os/windows/defender_helpers/defender_patterns.py +282 -0
  40. dissect/target/plugins/os/windows/defender_helpers/defender_records.py +191 -0
  41. dissect/target/plugins/os/windows/dpapi/blob.py +1 -2
  42. dissect/target/plugins/os/windows/dpapi/master_key.py +2 -3
  43. dissect/target/plugins/os/windows/lnk.py +3 -0
  44. dissect/target/plugins/os/windows/log/etl.py +9 -0
  45. dissect/target/plugins/os/windows/log/evt.py +3 -0
  46. dissect/target/plugins/os/windows/log/evtx.py +3 -0
  47. dissect/target/plugins/os/windows/log/pfro.py +3 -0
  48. dissect/target/plugins/os/windows/log/schedlgu.py +5 -2
  49. dissect/target/plugins/os/windows/notifications.py +1 -2
  50. dissect/target/plugins/os/windows/prefetch.py +32 -27
  51. dissect/target/plugins/os/windows/recyclebin.py +13 -8
  52. dissect/target/plugins/os/windows/regf/appxdebugkeys.py +3 -0
  53. dissect/target/plugins/os/windows/regf/auditpol.py +4 -5
  54. dissect/target/plugins/os/windows/regf/bam.py +5 -3
  55. dissect/target/plugins/os/windows/regf/cit.py +1 -2
  56. dissect/target/plugins/os/windows/regf/clsid.py +3 -0
  57. dissect/target/plugins/os/windows/regf/firewall.py +3 -0
  58. dissect/target/plugins/os/windows/regf/muicache.py +3 -0
  59. dissect/target/plugins/os/windows/regf/recentfilecache.py +6 -4
  60. dissect/target/plugins/os/windows/regf/regf.py +6 -0
  61. dissect/target/plugins/os/windows/regf/runkeys.py +3 -0
  62. dissect/target/plugins/os/windows/regf/shellbags.py +9 -7
  63. dissect/target/plugins/os/windows/regf/shimcache.py +5 -3
  64. dissect/target/plugins/os/windows/regf/trusteddocs.py +3 -0
  65. dissect/target/plugins/os/windows/regf/usb.py +3 -0
  66. dissect/target/plugins/os/windows/regf/userassist.py +8 -6
  67. dissect/target/plugins/os/windows/sam.py +7 -5
  68. dissect/target/plugins/os/windows/services.py +3 -0
  69. dissect/target/plugins/os/windows/task_helpers/tasks_job.py +3 -4
  70. dissect/target/plugins/os/windows/wer.py +3 -0
  71. dissect/target/target.py +6 -1
  72. dissect/target/tools/shell.py +30 -19
  73. {dissect.target-3.17.dev37.dist-info → dissect.target-3.18.dist-info}/METADATA +49 -24
  74. {dissect.target-3.17.dev37.dist-info → dissect.target-3.18.dist-info}/RECORD +79 -74
  75. {dissect.target-3.17.dev37.dist-info → dissect.target-3.18.dist-info}/WHEEL +1 -1
  76. {dissect.target-3.17.dev37.dist-info → dissect.target-3.18.dist-info}/COPYRIGHT +0 -0
  77. {dissect.target-3.17.dev37.dist-info → dissect.target-3.18.dist-info}/LICENSE +0 -0
  78. {dissect.target-3.17.dev37.dist-info → dissect.target-3.18.dist-info}/entry_points.txt +0 -0
  79. {dissect.target-3.17.dev37.dist-info → dissect.target-3.18.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,10 @@
1
+ from __future__ import annotations
2
+
3
+ import re
1
4
  from datetime import datetime, timezone
2
5
  from io import BytesIO
3
6
  from pathlib import Path
4
- from typing import Any, BinaryIO, Generator, Iterable, Iterator, Union
7
+ from typing import Any, BinaryIO, Generator, Iterable, Iterator, TextIO, Union
5
8
 
6
9
  import dissect.util.ts as ts
7
10
  from dissect.cstruct import Structure, cstruct
@@ -10,6 +13,27 @@ from flow.record import Record
10
13
  from dissect.target import plugin
11
14
  from dissect.target.exceptions import UnsupportedPluginError
12
15
  from dissect.target.helpers.record import TargetRecordDescriptor
16
+ from dissect.target.plugins.os.windows.defender_helpers.defender_patterns import (
17
+ DEFENDER_MPLOG_BLOCK_PATTERNS,
18
+ DEFENDER_MPLOG_LINE,
19
+ DEFENDER_MPLOG_PATTERNS,
20
+ )
21
+ from dissect.target.plugins.os.windows.defender_helpers.defender_records import (
22
+ DefenderMPLogBMTelemetryRecord,
23
+ DefenderMPLogDetectionAddRecord,
24
+ DefenderMPLogDetectionEventRecord,
25
+ DefenderMPLogEMSRecord,
26
+ DefenderMPLogExclusionRecord,
27
+ DefenderMPLogLowfiRecord,
28
+ DefenderMPLogMinFilBlockedFileRecord,
29
+ DefenderMPLogMinFilUSSRecord,
30
+ DefenderMPLogOriginalFileNameRecord,
31
+ DefenderMPLogProcessImageRecord,
32
+ DefenderMPLogResourceScanRecord,
33
+ DefenderMPLogRTPRecord,
34
+ DefenderMPLogThreatActionRecord,
35
+ DefenderMPLogThreatRecord,
36
+ )
13
37
 
14
38
  DEFENDER_EVTX_FIELDS = [
15
39
  ("datetime", "ts"),
@@ -73,6 +97,7 @@ DEFENDER_LOG_FILENAME_GLOB = "Microsoft-Windows-Windows Defender*"
73
97
  EVTX_PROVIDER_NAME = "Microsoft-Windows-Windows Defender"
74
98
 
75
99
  DEFENDER_QUARANTINE_DIR = "sysvol/programdata/microsoft/windows defender/quarantine"
100
+ DEFENDER_MPLOG_DIR = "sysvol/programdata/microsoft/windows defender/support"
76
101
  DEFENDER_KNOWN_DETECTION_TYPES = [b"internalbehavior", b"regkey", b"runkey"]
77
102
 
78
103
  DEFENDER_EXCLUSION_KEY = "HKLM\\SOFTWARE\\Microsoft\\Windows Defender\\Exclusions"
@@ -237,8 +262,7 @@ struct QuarantineEntryResourceField {
237
262
  };
238
263
  """
239
264
 
240
- c_defender = cstruct()
241
- c_defender.load(defender_def)
265
+ c_defender = cstruct().load(defender_def)
242
266
 
243
267
  STREAM_ID = c_defender.STREAM_ID
244
268
  STREAM_ATTRIBUTES = c_defender.STREAM_ATTRIBUTES
@@ -381,7 +405,7 @@ class QuarantineEntryResource:
381
405
  self.last_access_time = ts.wintimestamp(int.from_bytes(field.Data, "little"))
382
406
  elif field.Identifier == FIELD_IDENTIFIER.LastWriteTime:
383
407
  self.last_write_time = ts.wintimestamp(int.from_bytes(field.Data, "little"))
384
- elif field.Identifier not in FIELD_IDENTIFIER.values.values():
408
+ elif field.Identifier not in FIELD_IDENTIFIER:
385
409
  self.unknown_fields.append(field)
386
410
 
387
411
 
@@ -495,6 +519,198 @@ class MicrosoftDefenderPlugin(plugin.Plugin):
495
519
  value=exclusion_value,
496
520
  )
497
521
 
522
+ def _mplog_processimage(self, data: dict) -> Iterator[DefenderMPLogProcessImageRecord]:
523
+ yield DefenderMPLogProcessImageRecord(**data)
524
+
525
+ def _mplog_minfiluss(self, data: dict) -> Iterator[DefenderMPLogMinFilUSSRecord]:
526
+ yield DefenderMPLogMinFilUSSRecord(**data)
527
+
528
+ def _mplog_blockedfile(self, data: dict) -> Iterator[DefenderMPLogMinFilBlockedFileRecord]:
529
+ yield DefenderMPLogMinFilBlockedFileRecord(**data)
530
+
531
+ def _mplog_bmtelemetry(self, data: dict) -> Iterator[DefenderMPLogBMTelemetryRecord]:
532
+ data["ts"] = datetime.strptime(data["ts"], "%m-%d-%Y %H:%M:%S")
533
+ yield DefenderMPLogBMTelemetryRecord(**data)
534
+
535
+ def _mplog_ems(self, data: dict) -> Iterator[DefenderMPLogEMSRecord]:
536
+ yield DefenderMPLogEMSRecord(**data)
537
+
538
+ def _mplog_originalfilename(self, data: dict) -> Iterator[DefenderMPLogOriginalFileNameRecord]:
539
+ yield DefenderMPLogOriginalFileNameRecord(**data)
540
+
541
+ def _mplog_exclusion(self, data: dict) -> Iterator[DefenderMPLogExclusionRecord]:
542
+ yield DefenderMPLogExclusionRecord(**data)
543
+
544
+ def _mplog_lowfi(self, data: dict) -> Iterator[DefenderMPLogLowfiRecord]:
545
+ yield DefenderMPLogLowfiRecord(**data)
546
+
547
+ def _mplog_detectionadd(self, data: dict) -> Iterator[DefenderMPLogDetectionAddRecord]:
548
+ yield DefenderMPLogDetectionAddRecord(**data)
549
+
550
+ def _mplog_threat(self, data: dict) -> Iterator[DefenderMPLogThreatRecord]:
551
+ yield DefenderMPLogThreatRecord(**data)
552
+
553
+ def _mplog_resourcescan(self, data: dict) -> Iterator[DefenderMPLogResourceScanRecord]:
554
+ data["start_time"] = datetime.strptime(data["start_time"], "%m-%d-%Y %H:%M:%S")
555
+ data["end_time"] = datetime.strptime(data["end_time"], "%m-%d-%Y %H:%M:%S")
556
+ data["ts"] = data["start_time"]
557
+ rest = data.pop("rest")
558
+ yield DefenderMPLogResourceScanRecord(
559
+ threats=re.findall("Threat Name:([^\n]+)", rest),
560
+ resources=re.findall("Resource Path:([^\n]+)", rest),
561
+ **data,
562
+ )
563
+
564
+ def _mplog_threataction(self, data: dict) -> Iterator[DefenderMPLogThreatActionRecord]:
565
+ data["ts"] = datetime.strptime(data["ts"], "%m-%d-%Y %H:%M:%S")
566
+ rest = data.pop("rest")
567
+ yield DefenderMPLogThreatActionRecord(
568
+ threats=re.findall("Threat Name:([^\n]+)", rest),
569
+ resources=re.findall("(?:Path|File Name):([^\n]+)", rest),
570
+ actions=re.findall("Action:([^\n]+)", rest),
571
+ **data,
572
+ )
573
+
574
+ def _mplog_rtp_log(self, data: dict) -> Iterator[DefenderMPLogRTPRecord]:
575
+ times = {}
576
+ for dtkey in ["ts", "last_perf", "first_rtp_scan"]:
577
+ try:
578
+ times[dtkey] = datetime.strptime(data[dtkey], "%m-%d-%Y %H:%M:%S")
579
+ except ValueError:
580
+ pass
581
+
582
+ yield DefenderMPLogRTPRecord(
583
+ _target=self.target,
584
+ source_log=data["source_log"],
585
+ **times,
586
+ plugin_states=re.findall(r"^\s+(.*)$", data["plugin_states"])[0],
587
+ process_exclusions=re.findall(DEFENDER_MPLOG_LINE, data["process_exclusions"]),
588
+ path_exclusions=re.findall(DEFENDER_MPLOG_LINE, data["path_exclusions"]),
589
+ ext_exclusions=re.findall(DEFENDER_MPLOG_LINE, data["ext_exclusions"]),
590
+ )
591
+
592
+ def _mplog_detectionevent(self, data: dict) -> Iterator[DefenderMPLogDetectionEventRecord]:
593
+ yield DefenderMPLogDetectionEventRecord(**data)
594
+
595
+ def _mplog_line(
596
+ self, mplog_line: str, source: Path
597
+ ) -> Iterator[
598
+ DefenderMPLogProcessImageRecord
599
+ | DefenderMPLogMinFilUSSRecord
600
+ | DefenderMPLogMinFilBlockedFileRecord
601
+ | DefenderMPLogEMSRecord
602
+ | DefenderMPLogOriginalFileNameRecord
603
+ | DefenderMPLogExclusionRecord
604
+ | DefenderMPLogLowfiRecord
605
+ | DefenderMPLogDetectionAddRecord
606
+ | DefenderMPLogThreatRecord
607
+ | DefenderMPLogDetectionEventRecord
608
+ ]:
609
+ for pattern, record in DEFENDER_MPLOG_PATTERNS:
610
+ if match := pattern.match(mplog_line):
611
+ data = match.groupdict()
612
+ data["_target"] = self.target
613
+ data["source_log"] = source
614
+ yield from getattr(self, f"_mplog_{record.name.split('/')[-1:][0]}")(data)
615
+
616
+ def _mplog_block(
617
+ self, mplog_line: str, mplog: TextIO, source: Path
618
+ ) -> Iterator[DefenderMPLogResourceScanRecord | DefenderMPLogThreatActionRecord | DefenderMPLogRTPRecord]:
619
+ block = ""
620
+ for prefix, suffix, pattern, record in DEFENDER_MPLOG_BLOCK_PATTERNS:
621
+ if prefix.search(mplog_line):
622
+ block += mplog_line
623
+ break
624
+ if block:
625
+ while mplog_line := mplog.readline():
626
+ block += mplog_line
627
+ if suffix.search(mplog_line):
628
+ break
629
+ match = pattern.match(block)
630
+ data = match.groupdict()
631
+ data["_target"] = self.target
632
+ data["source_log"] = source
633
+ yield from getattr(self, f"_mplog_{record.name.split('/')[-1:][0]}")(data)
634
+
635
+ def _mplog(
636
+ self, mplog: TextIO, source: Path
637
+ ) -> Iterator[
638
+ DefenderMPLogProcessImageRecord
639
+ | DefenderMPLogMinFilUSSRecord
640
+ | DefenderMPLogMinFilBlockedFileRecord
641
+ | DefenderMPLogBMTelemetryRecord
642
+ | DefenderMPLogEMSRecord
643
+ | DefenderMPLogOriginalFileNameRecord
644
+ | DefenderMPLogExclusionRecord
645
+ | DefenderMPLogLowfiRecord
646
+ | DefenderMPLogDetectionAddRecord
647
+ | DefenderMPLogThreatRecord
648
+ | DefenderMPLogDetectionEventRecord
649
+ | DefenderMPLogResourceScanRecord
650
+ | DefenderMPLogThreatActionRecord
651
+ | DefenderMPLogRTPRecord
652
+ ]:
653
+ while mplog_line := mplog.readline():
654
+ yield from self._mplog_line(mplog_line, source)
655
+ yield from self._mplog_block(mplog_line, mplog, source)
656
+
657
+ @plugin.export(
658
+ record=[
659
+ DefenderMPLogProcessImageRecord,
660
+ DefenderMPLogMinFilUSSRecord,
661
+ DefenderMPLogMinFilBlockedFileRecord,
662
+ DefenderMPLogBMTelemetryRecord,
663
+ DefenderMPLogEMSRecord,
664
+ DefenderMPLogOriginalFileNameRecord,
665
+ DefenderMPLogExclusionRecord,
666
+ DefenderMPLogLowfiRecord,
667
+ DefenderMPLogDetectionAddRecord,
668
+ DefenderMPLogThreatRecord,
669
+ DefenderMPLogDetectionEventRecord,
670
+ DefenderMPLogResourceScanRecord,
671
+ DefenderMPLogThreatActionRecord,
672
+ DefenderMPLogRTPRecord,
673
+ ]
674
+ )
675
+ def mplog(
676
+ self,
677
+ ) -> Iterator[
678
+ DefenderMPLogProcessImageRecord
679
+ | DefenderMPLogMinFilUSSRecord
680
+ | DefenderMPLogMinFilBlockedFileRecord
681
+ | DefenderMPLogBMTelemetryRecord
682
+ | DefenderMPLogEMSRecord
683
+ | DefenderMPLogOriginalFileNameRecord
684
+ | DefenderMPLogExclusionRecord
685
+ | DefenderMPLogLowfiRecord
686
+ | DefenderMPLogDetectionAddRecord
687
+ | DefenderMPLogThreatRecord
688
+ | DefenderMPLogDetectionEventRecord
689
+ | DefenderMPLogResourceScanRecord
690
+ | DefenderMPLogThreatActionRecord
691
+ | DefenderMPLogRTPRecord
692
+ ]:
693
+ """Return the contents of the Defender MPLog file.
694
+
695
+ References:
696
+ - https://www.crowdstrike.com/blog/how-to-use-microsoft-protection-logging-for-forensic-investigations/
697
+ - https://www.intrinsec.com/hunt-mplogs/
698
+ - https://github.com/Intrinsec/mplog_parser
699
+ """
700
+ mplog_directory = self.target.fs.path(DEFENDER_MPLOG_DIR)
701
+
702
+ if not (mplog_directory.exists() and mplog_directory.is_dir()):
703
+ return
704
+
705
+ for mplog_file in mplog_directory.glob("MPLog-*"):
706
+ for encoding in ["UTF-16", "UTF-8"]:
707
+ try:
708
+ with mplog_file.open("rt", encoding=encoding) as mplog:
709
+ yield from self._mplog(mplog, self.target.fs.path(mplog_file))
710
+ break
711
+ except UnicodeError:
712
+ continue
713
+
498
714
  @plugin.arg(
499
715
  "--output",
500
716
  "-o",
@@ -526,7 +742,7 @@ class MicrosoftDefenderPlugin(plugin.Plugin):
526
742
  subdir = resource.resource_id[0:2]
527
743
  resourcedata_location = resourcedata_directory.joinpath(subdir).joinpath(resource.resource_id)
528
744
  if not resourcedata_location.exists():
529
- self.target.log.warning(f"Could not find a ResourceData file for {entry.resource_id}.")
745
+ self.target.log.warning(f"Could not find a ResourceData file for {resource.resource_id}.")
530
746
  continue
531
747
  if not resourcedata_location.is_file():
532
748
  self.target.log.warning(f"{resourcedata_location} is not a file!")
@@ -0,0 +1,282 @@
1
+ import re
2
+
3
+ from dissect.target.plugins.os.windows.defender_helpers.defender_records import (
4
+ DefenderMPLogBMTelemetryRecord,
5
+ DefenderMPLogDetectionAddRecord,
6
+ DefenderMPLogDetectionEventRecord,
7
+ DefenderMPLogEMSRecord,
8
+ DefenderMPLogExclusionRecord,
9
+ DefenderMPLogLowfiRecord,
10
+ DefenderMPLogMinFilBlockedFileRecord,
11
+ DefenderMPLogMinFilUSSRecord,
12
+ DefenderMPLogOriginalFileNameRecord,
13
+ DefenderMPLogProcessImageRecord,
14
+ DefenderMPLogResourceScanRecord,
15
+ DefenderMPLogRTPRecord,
16
+ DefenderMPLogThreatActionRecord,
17
+ DefenderMPLogThreatRecord,
18
+ )
19
+
20
+ DEFENDER_MPLOG_TS_PATTERN = r"(?P<ts>[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}Z) "
21
+
22
+ # Loosely based on https://github.com/Intrinsec/mplog_parser but feel free to add patterns
23
+
24
+ DEFENDER_MPLOG_PATTERNS = [
25
+ # Process Image
26
+ (
27
+ re.compile(
28
+ "".join(
29
+ [
30
+ DEFENDER_MPLOG_TS_PATTERN,
31
+ r"ProcessImageName: (?P<process_image_name>.*), ",
32
+ r"Pid: (?P<pid>\d*), ",
33
+ r"TotalTime: (?P<total_time>\d*), ",
34
+ r"Count: (?P<count>\d*), ",
35
+ r"MaxTime: (?P<max_time>\d*), ",
36
+ r"MaxTimeFile: (?P<max_time_file>.*), ",
37
+ r"EstimatedImpact: (?P<estimated_impact>\d*)",
38
+ ]
39
+ )
40
+ ),
41
+ DefenderMPLogProcessImageRecord,
42
+ ),
43
+ # Mini-filter Unsuccessful scan status
44
+ (
45
+ re.compile(
46
+ "".join(
47
+ [
48
+ DEFENDER_MPLOG_TS_PATTERN,
49
+ r"\[Mini-filter\] (Unsuccessful scan status)[^:]*: (?P<path>.+) ",
50
+ r"Process: (?P<process>.+), ",
51
+ r"Status: (?P<status>.+), ",
52
+ r"State: (?P<state>.+), ",
53
+ r"ScanRequest (?P<scan_request>.+), ",
54
+ r"FileId: (?P<file_id>.+), ",
55
+ r"Reason: (?P<reason>.+), ",
56
+ r"IoStatusBlockForNewFile: (?P<io_status_block_for_new_file>.+), ",
57
+ r"DesiredAccess:(?P<desired_access>.+), ",
58
+ r"FileAttributes:(?P<file_attributes>.+), ",
59
+ r"ScanAttributes:(?P<scan_attributes>.+), ",
60
+ r"AccessStateFlags:(?P<access_state_flags>.+), ",
61
+ r"BackingFileInfo: (?P<backing_file_info>.+)",
62
+ ]
63
+ )
64
+ ),
65
+ DefenderMPLogMinFilUSSRecord,
66
+ ),
67
+ # EMS Scan
68
+ (
69
+ re.compile(
70
+ "".join(
71
+ [
72
+ DEFENDER_MPLOG_TS_PATTERN,
73
+ r".*",
74
+ r"process: (?P<process>\w*) ",
75
+ r"pid: (?P<pid>\d*), ",
76
+ r"sigseq: (?P<sigseq>\w*), ",
77
+ r"sendMemoryScanReport: (?P<send_memory_scan_report>\d*), ",
78
+ r"source: (?P<source>\d*)",
79
+ ]
80
+ )
81
+ ),
82
+ DefenderMPLogEMSRecord,
83
+ ),
84
+ # Original filename
85
+ (
86
+ re.compile(
87
+ "".join(
88
+ [
89
+ DEFENDER_MPLOG_TS_PATTERN,
90
+ r".*",
91
+ r"original file name \"(?P<original_file_name>.*)\" ",
92
+ r"for \"(?P<full_path>.*)\", ",
93
+ r"hr=(?P<hr>\w*)",
94
+ ]
95
+ )
96
+ ),
97
+ DefenderMPLogOriginalFileNameRecord,
98
+ ),
99
+ # Mini-filter Blocked file
100
+ (
101
+ re.compile(
102
+ "".join(
103
+ [
104
+ DEFENDER_MPLOG_TS_PATTERN,
105
+ r".*",
106
+ r"\[Mini-filter\] Blocked file: (?P<blocked_file>.+) ",
107
+ r"Process: (?P<process>.+), ",
108
+ r"Status: (?P<status>.+), ",
109
+ r"State: (?P<state>.+), ",
110
+ r"ScanRequest (?P<scan_request>.+), ",
111
+ r"FileId: (?P<file_id>.+), ",
112
+ r"Reason: (?P<reason>.+), ",
113
+ r"IoStatusBlockForNewFile: (?P<io_status_block_for_new_file>.+), ",
114
+ r"DesiredAccess:(?P<desired_access>.+), ",
115
+ r"FileAttributes:(?P<file_attributes>.+), ",
116
+ r"ScanAttributes:(?P<scan_attributes>.+), ",
117
+ r"AccessStateFlags:(?P<access_state_flags>.+), ",
118
+ r"BackingFileInfo: (?P<backing_file_info>.+)",
119
+ ]
120
+ )
121
+ ),
122
+ DefenderMPLogMinFilBlockedFileRecord,
123
+ ),
124
+ # Exclusion
125
+ (
126
+ re.compile(
127
+ "".join(
128
+ [
129
+ DEFENDER_MPLOG_TS_PATTERN,
130
+ r"\[Exclusion\] (?P<full_path_with_drive_letter>.+) ",
131
+ r"-> (?P<full_path_with_device_path>.+)",
132
+ ]
133
+ )
134
+ ),
135
+ DefenderMPLogExclusionRecord,
136
+ ),
137
+ # Lowfi
138
+ (
139
+ re.compile(
140
+ "".join(
141
+ [
142
+ DEFENDER_MPLOG_TS_PATTERN,
143
+ r".*",
144
+ r"lowfi: (?P<lowfi>.+)",
145
+ ]
146
+ )
147
+ ),
148
+ DefenderMPLogLowfiRecord,
149
+ ),
150
+ # Detection add
151
+ (
152
+ re.compile(
153
+ "".join(
154
+ [
155
+ DEFENDER_MPLOG_TS_PATTERN,
156
+ r".*",
157
+ r"DETECTION_ADD\S* (?P<detection>.*)",
158
+ ]
159
+ )
160
+ ),
161
+ DefenderMPLogDetectionAddRecord,
162
+ ),
163
+ # Threat
164
+ (
165
+ re.compile(
166
+ "".join(
167
+ [
168
+ DEFENDER_MPLOG_TS_PATTERN,
169
+ r".*",
170
+ r"threat: (?P<threat>.*)",
171
+ ]
172
+ )
173
+ ),
174
+ DefenderMPLogThreatRecord,
175
+ ),
176
+ # Detection event
177
+ (
178
+ re.compile(
179
+ "".join(
180
+ [
181
+ DEFENDER_MPLOG_TS_PATTERN,
182
+ r".*",
183
+ r"DETECTIONEVENT MPSOURCE_\S+ HackTool:(?P<threat_type>.*) file:(?P<command>.*)",
184
+ ]
185
+ )
186
+ ),
187
+ DefenderMPLogDetectionEventRecord,
188
+ ),
189
+ ]
190
+
191
+
192
+ DEFENDER_MPLOG_BLOCK_PATTERNS = [
193
+ (
194
+ re.compile(r"Begin Resource Scan"),
195
+ re.compile(r"End Scan"),
196
+ re.compile(
197
+ "".join(
198
+ [
199
+ r"Begin Resource Scan.*\n",
200
+ r"Scan ID:(?P<scan_id>[^\n]+)\n",
201
+ r"Scan Source:(?P<scan_source>\d+)\n",
202
+ r"Start Time:(?P<start_time>[0-9\-\:\s]*)\n",
203
+ r"End Time:(?P<end_time>[0-9\-\:\s]*)\n",
204
+ r".*",
205
+ r"Resource Schema:(?P<resource_schema>[^\n]+)\n",
206
+ r"Resource Path:(?P<resource_path>[^\n]+)\n",
207
+ r"Result Count:(?P<result_count>\d+)\n",
208
+ r"(?P<rest>.*)\n",
209
+ r"End Scan",
210
+ ]
211
+ ),
212
+ re.MULTILINE | re.DOTALL,
213
+ ),
214
+ DefenderMPLogResourceScanRecord,
215
+ ),
216
+ # Threat actions
217
+ (
218
+ re.compile(r"Beginning threat actions"),
219
+ re.compile(r"Finished threat actions"),
220
+ re.compile(
221
+ "".join(
222
+ [
223
+ r"Beginning threat actions\n",
224
+ r"Start time:(?P<ts>[0-9\-\:\s]*)\n",
225
+ r"(?P<rest>.*)\n",
226
+ r"Finished threat actions",
227
+ ]
228
+ ),
229
+ re.MULTILINE | re.DOTALL,
230
+ ),
231
+ DefenderMPLogThreatActionRecord,
232
+ ),
233
+ # RTP
234
+ (
235
+ re.compile(r"\*\*RTP Perf Log\*\*"),
236
+ re.compile(r"\*\*END RTP Perf Log\*\*"),
237
+ re.compile(
238
+ "".join(
239
+ [
240
+ r"\*+RTP Perf Log\*+\n",
241
+ r"RTP Start:(?P<ts>.*)\n",
242
+ r"Last Perf:(?P<last_perf>.*)\n",
243
+ r"First RTP Scan:(?P<first_rtp_scan>.*)\n",
244
+ r"Plugin States:(?P<plugin_states>.*)\n",
245
+ r"Process Exclusions:\n(?P<process_exclusions>.*)",
246
+ r"Path Exclusions:\n(?P<path_exclusions>.*)",
247
+ r"Ext Exclusions:\n(?P<ext_exclusions>.*)",
248
+ r"Worker Threads",
249
+ ]
250
+ ),
251
+ re.MULTILINE | re.DOTALL,
252
+ ),
253
+ DefenderMPLogRTPRecord,
254
+ ),
255
+ # BM Telemetry (block)
256
+ (
257
+ re.compile(r"BEGIN BM telemetry"),
258
+ re.compile(r"END BM telemetry"),
259
+ re.compile(
260
+ "".join(
261
+ [
262
+ r"BEGIN BM telemetry\n",
263
+ r"(GUID):(?P<guid>.+)\n",
264
+ r"(SignatureID):(?P<signature_id>.+)\n",
265
+ r"(SigSha):(?P<sigsha>.+)\n",
266
+ r"(ThreatLevel):(?P<threat_level>.+)\n",
267
+ r"(ProcessID):(?P<process_id>.+)\n",
268
+ r"(ProcessCreationTime):(?P<process_creation_time>.+)\n",
269
+ r"(SessionID):(?P<session_id>.+)\n",
270
+ r"(CreationTime):(?P<ts>.+)\n",
271
+ r"(ImagePath):(?P<image_path>.+)\n",
272
+ r"(Taint Info):(?P<taint_info>.+)\n",
273
+ r"(Operations):(?P<operations>.+)\n",
274
+ r"END BM telemetry",
275
+ ]
276
+ )
277
+ ),
278
+ DefenderMPLogBMTelemetryRecord,
279
+ ),
280
+ ]
281
+
282
+ DEFENDER_MPLOG_LINE = re.compile(r"^\s+(.*)$", re.MULTILINE)