dissect.target 3.21.dev6__py3-none-any.whl → 3.21.dev8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -163,8 +163,10 @@ class ITunesBackup:
163
163
 
164
164
  def files(self) -> Iterator[FileInfo]:
165
165
  """Iterate all the files in this backup."""
166
- for row in self.manifest_db.table("Files").rows():
167
- yield FileInfo(self, row.fileID, row.domain, row.relativePath, row.flags, row.file)
166
+
167
+ if table := self.manifest_db.table("Files"):
168
+ for row in table.rows():
169
+ yield FileInfo(self, row.fileID, row.domain, row.relativePath, row.flags, row.file)
168
170
 
169
171
 
170
172
  class FileInfo:
@@ -36,14 +36,18 @@ class WebCache:
36
36
  All ``ContainerId`` values for the requested container name.
37
37
  """
38
38
  try:
39
- for container_record in self.db.table("Containers").records():
39
+ table = self.db.table("Containers")
40
+
41
+ for container_record in table.records():
40
42
  if record_name := container_record.get("Name"):
41
43
  record_name = record_name.rstrip("\00").lower()
42
44
  if record_name == name.lower():
43
45
  container_id = container_record.get("ContainerId")
44
46
  yield self.db.table(f"Container_{container_id}")
45
- except KeyError:
46
- pass
47
+
48
+ except KeyError as e:
49
+ self.target.log.warning("Exception while parsing EseDB Containers table")
50
+ self.target.log.debug("", exc_info=e)
47
51
 
48
52
  def _iter_records(self, name: str) -> Iterator[record.Record]:
49
53
  """Yield records from a Webcache container.
@@ -472,37 +472,39 @@ def parse_config_store(fh: BinaryIO) -> dict[str, Any]:
472
472
  db = sqlite3.SQLite3(fh)
473
473
 
474
474
  store = {}
475
- for row in db.table("Config").rows():
476
- component_name = row.Component
477
- config_group_name = row.ConfigGroup
478
- value_group_name = row.Name
479
- identifier_name = row.Identifier
480
-
481
- if component_name not in store:
482
- store[component_name] = {}
483
- component = store[component_name]
484
-
485
- if config_group_name not in component:
486
- component[config_group_name] = {}
487
- config_group = component[config_group_name]
488
-
489
- if value_group_name not in config_group:
490
- config_group[value_group_name] = {}
491
- value_group = config_group[value_group_name]
492
-
493
- if identifier_name not in value_group:
494
- value_group[identifier_name] = {}
495
- identifier = value_group[identifier_name]
496
-
497
- identifier["modified_time"] = row.ModifiedTime
498
- identifier["creation_time"] = row.CreationTime
499
- identifier["version"] = row.Version
500
- identifier["success"] = row.Success
501
- identifier["auto_conf_value"] = json.loads(row.AutoConfValue) if row.AutoConfValue else None
502
- identifier["user_value"] = json.loads(row.UserValue) if row.UserValue else None
503
- identifier["vital_value"] = json.loads(row.VitalValue) if row.VitalValue else None
504
- identifier["cached_value"] = json.loads(row.CachedValue) if row.CachedValue else None
505
- identifier["desired_value"] = json.loads(row.DesiredValue) if row.DesiredValue else None
506
- identifier["revision"] = row.Revision
475
+
476
+ if table := db.table("Config"):
477
+ for row in table.rows():
478
+ component_name = row.Component
479
+ config_group_name = row.ConfigGroup
480
+ value_group_name = row.Name
481
+ identifier_name = row.Identifier
482
+
483
+ if component_name not in store:
484
+ store[component_name] = {}
485
+ component = store[component_name]
486
+
487
+ if config_group_name not in component:
488
+ component[config_group_name] = {}
489
+ config_group = component[config_group_name]
490
+
491
+ if value_group_name not in config_group:
492
+ config_group[value_group_name] = {}
493
+ value_group = config_group[value_group_name]
494
+
495
+ if identifier_name not in value_group:
496
+ value_group[identifier_name] = {}
497
+ identifier = value_group[identifier_name]
498
+
499
+ identifier["modified_time"] = row.ModifiedTime
500
+ identifier["creation_time"] = row.CreationTime
501
+ identifier["version"] = row.Version
502
+ identifier["success"] = row.Success
503
+ identifier["auto_conf_value"] = json.loads(row.AutoConfValue) if row.AutoConfValue else None
504
+ identifier["user_value"] = json.loads(row.UserValue) if row.UserValue else None
505
+ identifier["vital_value"] = json.loads(row.VitalValue) if row.VitalValue else None
506
+ identifier["cached_value"] = json.loads(row.CachedValue) if row.CachedValue else None
507
+ identifier["desired_value"] = json.loads(row.DesiredValue) if row.DesiredValue else None
508
+ identifier["revision"] = row.Revision
507
509
 
508
510
  return store
@@ -567,7 +567,7 @@ def parse_unix_dhcp_log_messages(target: Target, iter_all: bool = False) -> set[
567
567
  continue
568
568
 
569
569
  # Debian and CentOS dhclient
570
- if hasattr(record, "daemon") and record.daemon == "dhclient" and "bound to" in line:
570
+ if hasattr(record, "service") and record.service == "dhclient" and "bound to" in line:
571
571
  ip = line.split("bound to")[1].split(" ")[1].strip()
572
572
  ips.add(ip)
573
573
  continue
@@ -1,6 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- import itertools
4
3
  import logging
5
4
  import re
6
5
  from abc import ABC, abstractmethod
@@ -12,24 +11,18 @@ from typing import Any, Iterator
12
11
 
13
12
  from dissect.target import Target
14
13
  from dissect.target.exceptions import UnsupportedPluginError
15
- from dissect.target.helpers.fsutil import open_decompress
16
14
  from dissect.target.helpers.record import DynamicDescriptor, TargetRecordDescriptor
17
15
  from dissect.target.helpers.utils import year_rollover_helper
18
16
  from dissect.target.plugin import Plugin, alias, export
17
+ from dissect.target.plugins.os.unix.log.helpers import (
18
+ RE_LINE,
19
+ RE_TS,
20
+ is_iso_fmt,
21
+ iso_readlines,
22
+ )
19
23
 
20
24
  log = logging.getLogger(__name__)
21
25
 
22
- RE_TS = re.compile(r"^[A-Za-z]{3}\s*\d{1,2}\s\d{1,2}:\d{2}:\d{2}")
23
- RE_TS_ISO = re.compile(r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}\+\d{2}:\d{2}")
24
- RE_LINE = re.compile(
25
- r"""
26
- \d{2}:\d{2}\s # First match on the similar ending of the different timestamps
27
- (?P<hostname>\S+)\s # The hostname
28
- (?P<service>\S+?)(\[(?P<pid>\d+)\])?: # The service with optionally the PID between brackets
29
- \s*(?P<message>.+?)\s*$ # The log message stripped from spaces left and right
30
- """,
31
- re.VERBOSE,
32
- )
33
26
 
34
27
  # Generic regular expressions
35
28
  RE_IPV4_ADDRESS = re.compile(
@@ -347,27 +340,3 @@ class AuthPlugin(Plugin):
347
340
 
348
341
  for ts, line in iterable:
349
342
  yield self._auth_log_builder.build_record(ts, auth_file, line)
350
-
351
-
352
- def iso_readlines(file: Path) -> Iterator[tuple[datetime, str]]:
353
- """Iterator reading the provided auth log file in ISO format. Mimics ``year_rollover_helper`` behaviour."""
354
- with open_decompress(file, "rt") as fh:
355
- for line in fh:
356
- if not (match := RE_TS_ISO.match(line)):
357
- log.warning("No timestamp found in one of the lines in %s!", file)
358
- log.debug("Skipping line: %s", line)
359
- continue
360
-
361
- try:
362
- ts = datetime.strptime(match[0], "%Y-%m-%dT%H:%M:%S.%f%z")
363
- except ValueError as e:
364
- log.warning("Unable to parse ISO timestamp in line: %s", line)
365
- log.debug("", exc_info=e)
366
- continue
367
-
368
- yield ts, line
369
-
370
-
371
- def is_iso_fmt(file: Path) -> bool:
372
- """Determine if the provided auth log file uses new ISO format logging or not."""
373
- return any(itertools.islice(iso_readlines(file), 0, 2))
@@ -0,0 +1,46 @@
1
+ import itertools
2
+ import logging
3
+ import re
4
+ from datetime import datetime
5
+ from pathlib import Path
6
+ from typing import Iterator
7
+
8
+ from dissect.target.helpers.fsutil import open_decompress
9
+
10
+ log = logging.getLogger(__name__)
11
+
12
+ RE_TS = re.compile(r"^[A-Za-z]{3}\s*\d{1,2}\s\d{1,2}:\d{2}:\d{2}")
13
+ RE_TS_ISO = re.compile(r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}\+\d{2}:\d{2}")
14
+ RE_LINE = re.compile(
15
+ r"""
16
+ \d{2}:\d{2}\s # First match on the similar ending of the different timestamps
17
+ (?:\S+)\s # The hostname, but do not capture it
18
+ (?P<service>\S+?)(\[(?P<pid>\d+)\])?: # The service / daemon with optionally the PID between brackets
19
+ \s*(?P<message>.+?)\s*$ # The log message stripped from spaces left and right
20
+ """,
21
+ re.VERBOSE,
22
+ )
23
+
24
+
25
+ def iso_readlines(file: Path) -> Iterator[tuple[datetime, str]]:
26
+ """Iterator reading the provided log file in ISO format. Mimics ``year_rollover_helper`` behaviour."""
27
+ with open_decompress(file, "rt") as fh:
28
+ for line in fh:
29
+ if not (match := RE_TS_ISO.match(line)):
30
+ log.warning("No timestamp found in one of the lines in %s!", file)
31
+ log.debug("Skipping line: %s", line)
32
+ continue
33
+
34
+ try:
35
+ ts = datetime.strptime(match[0], "%Y-%m-%dT%H:%M:%S.%f%z")
36
+ except ValueError as e:
37
+ log.warning("Unable to parse ISO timestamp in line: %s", line)
38
+ log.debug("", exc_info=e)
39
+ continue
40
+
41
+ yield ts, line
42
+
43
+
44
+ def is_iso_fmt(file: Path) -> bool:
45
+ """Determine if the provided log file uses ISO 8601 timestamp format logging or not."""
46
+ return any(itertools.islice(iso_readlines(file), 0, 2))
@@ -11,12 +11,18 @@ from dissect.target.helpers.fsutil import open_decompress
11
11
  from dissect.target.helpers.record import TargetRecordDescriptor
12
12
  from dissect.target.helpers.utils import year_rollover_helper
13
13
  from dissect.target.plugin import Plugin, alias, export
14
+ from dissect.target.plugins.os.unix.log.helpers import (
15
+ RE_LINE,
16
+ RE_TS,
17
+ is_iso_fmt,
18
+ iso_readlines,
19
+ )
14
20
 
15
21
  MessagesRecord = TargetRecordDescriptor(
16
22
  "linux/log/messages",
17
23
  [
18
24
  ("datetime", "ts"),
19
- ("string", "daemon"),
25
+ ("string", "service"),
20
26
  ("varint", "pid"),
21
27
  ("string", "message"),
22
28
  ("path", "source"),
@@ -24,12 +30,8 @@ MessagesRecord = TargetRecordDescriptor(
24
30
  )
25
31
 
26
32
  DEFAULT_TS_LOG_FORMAT = "%b %d %H:%M:%S"
27
- RE_TS = re.compile(r"(\w+\s{1,2}\d+\s\d{2}:\d{2}:\d{2})")
28
- RE_DAEMON = re.compile(r"^[^:]+:\d+:\d+[^\[\]:]+\s([^\[:]+)[\[|:]{1}")
29
- RE_PID = re.compile(r"\w\[(\d+)\]")
30
- RE_MSG = re.compile(r"[^:]+:\d+:\d+[^:]+:\s(.*)$")
31
33
  RE_CLOUD_INIT_LINE = re.compile(
32
- r"^(?P<ts>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3}) - (?P<daemon>.*)\[(?P<log_level>\w+)\]\: (?P<message>.*)$"
34
+ r"^(?P<ts>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3}) - (?P<service>.*)\[(?P<log_level>\w+)\]\: (?P<message>.*)$"
33
35
  )
34
36
 
35
37
 
@@ -56,7 +58,7 @@ class MessagesPlugin(Plugin):
56
58
  def messages(self) -> Iterator[MessagesRecord]:
57
59
  """Return contents of /var/log/messages*, /var/log/syslog* and cloud-init logs.
58
60
 
59
- Due to year rollover detection, the contents of the files are returned in reverse.
61
+ Due to year rollover detection, the log contents could be returned in reversed or mixed chronological order.
60
62
 
61
63
  The messages log file holds information about a variety of events such as the system error messages, system
62
64
  startups and shutdowns, change in the network configuration, etc. Aims to store valuable, non-debug and
@@ -75,16 +77,23 @@ class MessagesPlugin(Plugin):
75
77
  yield from self._parse_cloud_init_log(log_file, tzinfo)
76
78
  continue
77
79
 
78
- for ts, line in year_rollover_helper(log_file, RE_TS, DEFAULT_TS_LOG_FORMAT, tzinfo):
79
- daemon = dict(enumerate(RE_DAEMON.findall(line))).get(0)
80
- pid = dict(enumerate(RE_PID.findall(line))).get(0)
81
- message = dict(enumerate(RE_MSG.findall(line))).get(0, line)
80
+ if is_iso_fmt(log_file):
81
+ iterable = iso_readlines(log_file)
82
+
83
+ else:
84
+ iterable = year_rollover_helper(log_file, RE_TS, DEFAULT_TS_LOG_FORMAT, tzinfo)
85
+
86
+ for ts, line in iterable:
87
+ match = RE_LINE.search(line)
88
+
89
+ if not match:
90
+ self.target.log.warning("Unable to parse message line in %s", log_file)
91
+ self.target.log.debug("Line %s", line)
92
+ continue
82
93
 
83
94
  yield MessagesRecord(
84
95
  ts=ts,
85
- daemon=daemon,
86
- pid=pid,
87
- message=message,
96
+ **match.groupdict(),
88
97
  source=log_file,
89
98
  _target=self.target,
90
99
  )
@@ -134,7 +143,7 @@ class MessagesPlugin(Plugin):
134
143
 
135
144
  yield MessagesRecord(
136
145
  ts=ts,
137
- daemon=values["daemon"],
146
+ service=values["service"],
138
147
  pid=None,
139
148
  message=values["message"],
140
149
  source=log_file,
@@ -116,36 +116,38 @@ class ActivitiesCachePlugin(Plugin):
116
116
  for user, cache_file in self.cachefiles:
117
117
  fh = cache_file.open()
118
118
  db = sqlite3.SQLite3(fh)
119
- for r in db.table("Activity").rows():
120
- yield ActivitiesCacheRecord(
121
- start_time=mkts(r["[StartTime]"]),
122
- end_time=mkts(r["[EndTime]"]),
123
- last_modified_time=mkts(r["[LastModifiedTime]"]),
124
- last_modified_on_client=mkts(r["[LastModifiedOnClient]"]),
125
- original_last_modified_on_client=mkts(r["[OriginalLastModifiedOnClient]"]),
126
- expiration_time=mkts(r["[ExpirationTime]"]),
127
- app_id=r["[AppId]"],
128
- enterprise_id=r["[EnterpriseId]"],
129
- app_activity_id=r["[AppActivityId]"],
130
- group_app_activity_id=r["[GroupAppActivityId]"],
131
- group=r["[Group]"],
132
- activity_type=r["[ActivityType]"],
133
- activity_status=r["[ActivityStatus]"],
134
- priority=r["[Priority]"],
135
- match_id=r["[MatchId]"],
136
- etag=r["[ETag]"],
137
- tag=r["[Tag]"],
138
- is_local_only=r["[IsLocalOnly]"],
139
- created_in_cloud=r["[CreatedInCloud]"],
140
- platform_device_id=r["[PlatformDeviceId]"],
141
- package_id_hash=r["[PackageIdHash]"],
142
- id=r["[Id]"],
143
- payload=r["[Payload]"],
144
- original_payload=r["[OriginalPayload]"],
145
- clipboard_payload=r["[ClipboardPayload]"],
146
- _target=self.target,
147
- _user=user,
148
- )
119
+
120
+ if table := db.table("Activity"):
121
+ for r in table.rows():
122
+ yield ActivitiesCacheRecord(
123
+ start_time=mkts(r["[StartTime]"]),
124
+ end_time=mkts(r["[EndTime]"]),
125
+ last_modified_time=mkts(r["[LastModifiedTime]"]),
126
+ last_modified_on_client=mkts(r["[LastModifiedOnClient]"]),
127
+ original_last_modified_on_client=mkts(r["[OriginalLastModifiedOnClient]"]),
128
+ expiration_time=mkts(r["[ExpirationTime]"]),
129
+ app_id=r["[AppId]"],
130
+ enterprise_id=r["[EnterpriseId]"],
131
+ app_activity_id=r["[AppActivityId]"],
132
+ group_app_activity_id=r["[GroupAppActivityId]"],
133
+ group=r["[Group]"],
134
+ activity_type=r["[ActivityType]"],
135
+ activity_status=r["[ActivityStatus]"],
136
+ priority=r["[Priority]"],
137
+ match_id=r["[MatchId]"],
138
+ etag=r["[ETag]"],
139
+ tag=r["[Tag]"],
140
+ is_local_only=r["[IsLocalOnly]"],
141
+ created_in_cloud=r["[CreatedInCloud]"],
142
+ platform_device_id=r["[PlatformDeviceId]"],
143
+ package_id_hash=r["[PackageIdHash]"],
144
+ id=r["[Id]"],
145
+ payload=r["[Payload]"],
146
+ original_payload=r["[OriginalPayload]"],
147
+ clipboard_payload=r["[ClipboardPayload]"],
148
+ _target=self.target,
149
+ _user=user,
150
+ )
149
151
 
150
152
 
151
153
  def mkts(ts: int) -> datetime | None:
@@ -217,12 +217,15 @@ class CatrootPlugin(Plugin):
217
217
  with ese_file.open("rb") as fh:
218
218
  ese_db = EseDB(fh)
219
219
 
220
- tables = [table.name for table in ese_db.tables()]
221
220
  for hash_type, table_name in [("sha256", "HashCatNameTableSHA256"), ("sha1", "HashCatNameTableSHA1")]:
222
- if table_name not in tables:
221
+ try:
222
+ table = ese_db.table(table_name)
223
+ except KeyError as e:
224
+ self.target.log.warning("EseDB %s has no table %s", ese_file, table_name)
225
+ self.target.log.debug("", exc_info=e)
223
226
  continue
224
227
 
225
- for record in ese_db.table(table_name).records():
228
+ for record in table.records():
226
229
  file_digest = digest()
227
230
  setattr(file_digest, hash_type, record.get("HashCatNameTable_HashCol").hex())
228
231
  catroot_names = record.get("HashCatNameTable_CatNameCol").decode().rstrip("|").split("|")
@@ -442,43 +442,45 @@ class NotificationsPlugin(Plugin):
442
442
  """
443
443
  for user, wpndatabase in self.wpndb_files:
444
444
  db = sqlite3.SQLite3(wpndatabase.open())
445
-
446
445
  handlers = {}
447
- for row in db.table("NotificationHandler").rows():
448
- handlers[row["[RecordId]"]] = WpnDatabaseNotificationHandlerRecord(
449
- created_time=datetime.datetime.strptime(row["[CreatedTime]"], "%Y-%m-%d %H:%M:%S"),
450
- modified_time=datetime.datetime.strptime(row["[ModifiedTime]"], "%Y-%m-%d %H:%M:%S"),
451
- id=row["[RecordId]"],
452
- primary_id=row["[PrimaryId]"],
453
- wns_id=row["[WNSId]"],
454
- handler_type=row["[HandlerType]"],
455
- wnf_event_name=row["[WNFEventName]"],
456
- system_data_property_set=row["[SystemDataPropertySet]"],
457
- _target=self.target,
458
- _user=user,
459
- )
460
-
461
- for row in db.table("Notification").rows():
462
- record = WpnDatabaseNotificationRecord(
463
- arrival_time=wintimestamp(row["[ArrivalTime]"]),
464
- expiry_time=wintimestamp(row["[ExpiryTime]"]),
465
- order=row["[Order]"],
466
- id=row["[Id]"],
467
- handler_id=row["[HandlerId]"],
468
- activity_id=UUID(bytes=row["[ActivityId]"]),
469
- type=row["[Type]"],
470
- payload=row["[Payload]"],
471
- payload_type=row["[PayloadType]"],
472
- tag=row["[Tag]"],
473
- group=row["[Group]"],
474
- boot_id=row["[BootId]"],
475
- expires_on_reboot=row["[ExpiresOnReboot]"] != "FALSE",
476
- _target=self.target,
477
- _user=user,
478
- )
479
- handler = handlers.get(row["[HandlerId]"])
480
446
 
481
- if handler:
482
- yield GroupedRecord("windows/notification/wpndatabase/grouped", [record, handler])
483
- else:
484
- yield record
447
+ if table := db.table("NotificationHandler"):
448
+ for row in table.rows():
449
+ handlers[row["[RecordId]"]] = WpnDatabaseNotificationHandlerRecord(
450
+ created_time=datetime.datetime.strptime(row["[CreatedTime]"], "%Y-%m-%d %H:%M:%S"),
451
+ modified_time=datetime.datetime.strptime(row["[ModifiedTime]"], "%Y-%m-%d %H:%M:%S"),
452
+ id=row["[RecordId]"],
453
+ primary_id=row["[PrimaryId]"],
454
+ wns_id=row["[WNSId]"],
455
+ handler_type=row["[HandlerType]"],
456
+ wnf_event_name=row["[WNFEventName]"],
457
+ system_data_property_set=row["[SystemDataPropertySet]"],
458
+ _target=self.target,
459
+ _user=user,
460
+ )
461
+
462
+ if table := db.table("Notification"):
463
+ for row in table.rows():
464
+ record = WpnDatabaseNotificationRecord(
465
+ arrival_time=wintimestamp(row["[ArrivalTime]"]),
466
+ expiry_time=wintimestamp(row["[ExpiryTime]"]),
467
+ order=row["[Order]"],
468
+ id=row["[Id]"],
469
+ handler_id=row["[HandlerId]"],
470
+ activity_id=UUID(bytes=row["[ActivityId]"]),
471
+ type=row["[Type]"],
472
+ payload=row["[Payload]"],
473
+ payload_type=row["[PayloadType]"],
474
+ tag=row["[Tag]"],
475
+ group=row["[Group]"],
476
+ boot_id=row["[BootId]"],
477
+ expires_on_reboot=row["[ExpiresOnReboot]"] != "FALSE",
478
+ _target=self.target,
479
+ _user=user,
480
+ )
481
+ handler = handlers.get(row["[HandlerId]"])
482
+
483
+ if handler:
484
+ yield GroupedRecord("windows/notification/wpndatabase/grouped", [record, handler])
485
+ else:
486
+ yield record
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dissect.target
3
- Version: 3.21.dev6
3
+ Version: 3.21.dev8
4
4
  Summary: This module ties all other Dissect modules together, it provides a programming API and command line tools which allow easy access to various data sources inside disk images or file collections (a.k.a. targets)
5
5
  Author-email: Dissect Team <dissect@fox-it.com>
6
6
  License: Affero General Public License v3
@@ -81,7 +81,7 @@ dissect/target/loaders/cb.py,sha256=EGhdytBKBdofTd89juavDZZbmupEZmMBadeUXvVIK20,
81
81
  dissect/target/loaders/cyber.py,sha256=Ip2hI7L98ZP7gUZuHQr0GxBdmbTzD-PntXmLJ5KpBuQ,1533
82
82
  dissect/target/loaders/dir.py,sha256=F-PgvBw82XmL0rdKyBxznUkDc5Oct6-_Y9xM4fhvA6I,5791
83
83
  dissect/target/loaders/hyperv.py,sha256=_IOUJEO0BXaCBZ6sjIX0DZTkG9UNW5Vs9VcNHYv073w,5928
84
- dissect/target/loaders/itunes.py,sha256=rKOhlDRypQBGkuSZudMDS1Mlb9XV6BD5FRvM7tGq9jU,13128
84
+ dissect/target/loaders/itunes.py,sha256=MQZKWjs7ZKZnARAmzMVGyod0vgOvDZuximjKyMRiwKM,13164
85
85
  dissect/target/loaders/kape.py,sha256=t5TfrGLqPeIpUUpXzIl6aHsqXMEGDqJ5YwDCs07DiBA,1237
86
86
  dissect/target/loaders/libvirt.py,sha256=_3EFIytMGbiLMISHx4QXVrDebsRO6J6sMkE3TH68qsg,1374
87
87
  dissect/target/loaders/local.py,sha256=Ul-LCd_fY7SyWOVR6nH-NqbkuNpxoZVmffwrkvQElU8,16453
@@ -125,7 +125,7 @@ dissect/target/plugins/apps/browser/chrome.py,sha256=DMONTYE95sI_jcmyQOapHwWQWwr
125
125
  dissect/target/plugins/apps/browser/chromium.py,sha256=A4aJDJnngFBiIJ4pC10HMykEh1VLu2Xf_bvGG1o9LTM,28549
126
126
  dissect/target/plugins/apps/browser/edge.py,sha256=tuuIbm4s8nNstA6nIOEfU0LG0jt20a8gf3rve2SXtdM,2953
127
127
  dissect/target/plugins/apps/browser/firefox.py,sha256=mZBBagFfIdiz9kUyK4Hi989I4g3CWrClBbmpaGMRKxg,32472
128
- dissect/target/plugins/apps/browser/iexplore.py,sha256=g_xw0toaiyjevxO8g9XPCOqc-CXZp39FVquRhPFGdTE,8801
128
+ dissect/target/plugins/apps/browser/iexplore.py,sha256=5WkExNl7VoY72Y3SZNZAqxpX_9HXsQIlxFf58ur63zA,8953
129
129
  dissect/target/plugins/apps/container/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
130
130
  dissect/target/plugins/apps/container/docker.py,sha256=LTsZplaECSfO1Ysp_Y-9WsnNocsreu_iHO8fbSif3g0,16221
131
131
  dissect/target/plugins/apps/database/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -223,7 +223,7 @@ dissect/target/plugins/os/unix/bsd/osx/_os.py,sha256=hNFB1rwahLwgZD1kc3T4xalFusT
223
223
  dissect/target/plugins/os/unix/bsd/osx/network.py,sha256=3m71T-T-DnZFVidrokuHpr89lZOe_4drt-Xwam1ebfw,3767
224
224
  dissect/target/plugins/os/unix/bsd/osx/user.py,sha256=5rsGhsntBW9IXYIOrLpfYpSsJcBDL61QJkuZ456lXlE,2411
225
225
  dissect/target/plugins/os/unix/esxi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
226
- dissect/target/plugins/os/unix/esxi/_os.py,sha256=s6pAgUyfHh3QcY6sgvk5uVMmLvqK1tIHWR7MSbrFn8w,17789
226
+ dissect/target/plugins/os/unix/esxi/_os.py,sha256=eTI6zVubEmdx02mMDyTpmf2J53IzhWFT0UEt990b9OM,17921
227
227
  dissect/target/plugins/os/unix/etc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
228
228
  dissect/target/plugins/os/unix/etc/etc.py,sha256=YSCRZZfQvmzaR5VWhTJhB8pIGliL6Nw5ruhdfvYKYaM,2783
229
229
  dissect/target/plugins/os/unix/linux/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -234,7 +234,7 @@ dissect/target/plugins/os/unix/linux/iptables.py,sha256=qTzY5PHHXA33WnPYb5NESgoS
234
234
  dissect/target/plugins/os/unix/linux/modules.py,sha256=-LThb5mcKtngVfIICpdOGLtgJPc99WQ8Qufwddt8YgQ,2500
235
235
  dissect/target/plugins/os/unix/linux/netstat.py,sha256=EBpbK4BD3pZ0fKCR3ZMmVip4eQ0f6x_9yumA8vsUKPw,1691
236
236
  dissect/target/plugins/os/unix/linux/network.py,sha256=KfGfYhtrzpHHefaHjTpdbGSLu6IN4anweYt3V02D9zU,14392
237
- dissect/target/plugins/os/unix/linux/network_managers.py,sha256=nr0gA3hBqsvP9k6xAYmRYwGRB1kMtXB1k0pe78jWdFI,25768
237
+ dissect/target/plugins/os/unix/linux/network_managers.py,sha256=atvcHPXFHVeCD5ipygqpR8pOgSexCGKIvVZz3Z8ITLA,25770
238
238
  dissect/target/plugins/os/unix/linux/proc.py,sha256=jm35fAasnNbObN2tpflwQuCfVYLDkTP2EDrzYG42ZSk,23354
239
239
  dissect/target/plugins/os/unix/linux/processes.py,sha256=xAJswf06HZsY8JhQ11xfJw1OLTZ1q9XZbu7_a7k2UpY,2019
240
240
  dissect/target/plugins/os/unix/linux/services.py,sha256=cZWmoVImbl7foKQfBpiKjeC2kjvfRUpM-ympFQorwHI,4128
@@ -270,17 +270,18 @@ dissect/target/plugins/os/unix/locate/plocate.py,sha256=0p7ibPPrDlQuJNjJbV4rU0fJ
270
270
  dissect/target/plugins/os/unix/log/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
271
271
  dissect/target/plugins/os/unix/log/atop.py,sha256=zjG5eKS-X0mpBXs-Sg2f7RfQvtjt0T8JcteNd9DB_ok,16361
272
272
  dissect/target/plugins/os/unix/log/audit.py,sha256=rZwxC90Q0FOB5BZxplTJwCTIp0hdVpaps1e3C1fRYaM,3754
273
- dissect/target/plugins/os/unix/log/auth.py,sha256=9NJvlo7Vbsp_ENJFpKd04PH_sUuOy6ueSBwQqY0MtKo,14546
273
+ dissect/target/plugins/os/unix/log/auth.py,sha256=MNfPoGo_pGFMizbF5ZyW6bi-QWCxuaB7OVAeIJAAC6M,13068
274
+ dissect/target/plugins/os/unix/log/helpers.py,sha256=3_UNw36isxlmIRs0EreU4Oe5UrKOPl-mApjvfRXmYtQ,1775
274
275
  dissect/target/plugins/os/unix/log/journal.py,sha256=hhsvKs78BPv0vJN360fKVHqyBCdLUWxdv6ZUa4tqpD8,17795
275
276
  dissect/target/plugins/os/unix/log/lastlog.py,sha256=Wr3-2n1-GwckN9mSx-yM55N6_L0PQyx6TGHoEvuc6c0,2515
276
- dissect/target/plugins/os/unix/log/messages.py,sha256=XtjZ0a2budgQm_K5JT3fMf7JcjuD0AelcD3zOFN2xpI,5732
277
+ dissect/target/plugins/os/unix/log/messages.py,sha256=GjHqbbyoqXxIlD6cxK552Gv00LK399dU3u9NISGIVno,5787
277
278
  dissect/target/plugins/os/unix/log/utmp.py,sha256=k2A69s2qUT2JunJrH8GO6nQ0zMDotXMTaj8OzQ7ljj8,7336
278
279
  dissect/target/plugins/os/windows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
279
280
  dissect/target/plugins/os/windows/_os.py,sha256=SUTfCPEVi2ADfjsQQJad6dEsnKUzRtsKJXOlEuiT9Xk,12462
280
- dissect/target/plugins/os/windows/activitiescache.py,sha256=BbGD-vETHm1IRMoazVer_vqSJIoQxxhWcJ_xlBeOMds,6899
281
+ dissect/target/plugins/os/windows/activitiescache.py,sha256=_I-rc7hAKRgqfFexsJq5nkIAV3E31byG4KeBQeDBehg,7051
281
282
  dissect/target/plugins/os/windows/adpolicy.py,sha256=ul8lKlG9ExABnd6yVLMPFFgVxN74CG4T3MvcRuBLHJc,7158
282
283
  dissect/target/plugins/os/windows/amcache.py,sha256=1jq-S80_FIzGegrqQ6HqrjmaAPTyxyn69HxnbRBlaUc,27608
283
- dissect/target/plugins/os/windows/catroot.py,sha256=QVwMF5nuMzCkWnoOMs5BkwYoKN61HKmlxo8mKMoD3w8,10937
284
+ dissect/target/plugins/os/windows/catroot.py,sha256=bB-UE5QGuo-aHm1YU4qKHwt6ypW9FvxV9X0_0VplKts,11086
284
285
  dissect/target/plugins/os/windows/cim.py,sha256=jsrpu6TZpBUh7VWI9AV2Ib5bebTwsvqOwRfa5gjJd7c,3056
285
286
  dissect/target/plugins/os/windows/clfs.py,sha256=begVsZ-CY97Ksh6S1g03LjyBgu8ERY2hfNDWYPj0GXI,4872
286
287
  dissect/target/plugins/os/windows/datetime.py,sha256=YKHUZU6lkKJocq15y0yCwvIIOb1Ej-kfvEBmHbrdIGw,9467
@@ -291,7 +292,7 @@ dissect/target/plugins/os/windows/jumplist.py,sha256=3gZk6O1B3lKK2Jxe0B-HapOCEeh
291
292
  dissect/target/plugins/os/windows/lnk.py,sha256=KTqhw0JMW-KjAxe4xlRDNSRSx-th-_nPVgTGyBaKmW0,7891
292
293
  dissect/target/plugins/os/windows/locale.py,sha256=QiLWGgWrGBGHiXgep5iSOo6VNim4YC-xd4MdW0BUJPA,2486
293
294
  dissect/target/plugins/os/windows/network.py,sha256=epbRPt_Aa6xPV_fCd2tbHpbHAi_JG1jWrtHsDrqCrlM,11507
294
- dissect/target/plugins/os/windows/notifications.py,sha256=xxfMEY_noDxMVqvT3QS1a3j-X3qAYikOtT6v2owxuCY,17480
295
+ dissect/target/plugins/os/windows/notifications.py,sha256=3sL4x9AvaRfP_IBYncu4TNesSSuZP1FemgF1EH9RtJw,17686
295
296
  dissect/target/plugins/os/windows/prefetch.py,sha256=wbbYoy05gWbJfRsM2ci4wPG7kM58OocVwXD3hkQlbRw,10647
296
297
  dissect/target/plugins/os/windows/recyclebin.py,sha256=zx58hDCvcrD_eJl9nJmr_i80krSN03ya8nQzWFr2Tw0,4917
297
298
  dissect/target/plugins/os/windows/registry.py,sha256=f6ka__6KXvdqRMRRJzlCAYaIpTZhVLANXQX_-wZQKPA,13235
@@ -381,10 +382,10 @@ dissect/target/volumes/luks.py,sha256=OmCMsw6rCUXG1_plnLVLTpsvE1n_6WtoRUGQbpmu1z
381
382
  dissect/target/volumes/lvm.py,sha256=wwQVR9I3G9YzmY6UxFsH2Y4MXGBcKL9aayWGCDTiWMU,2269
382
383
  dissect/target/volumes/md.py,sha256=7ShPtusuLGaIv27SvEETtgsuoQyAa4iAAeOR1NEaajI,1689
383
384
  dissect/target/volumes/vmfs.py,sha256=-LoUbn9WNwTtLi_4K34uV_-wDw2W5hgaqxZNj4UmqAQ,1730
384
- dissect.target-3.21.dev6.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
385
- dissect.target-3.21.dev6.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
386
- dissect.target-3.21.dev6.dist-info/METADATA,sha256=y20uM3xEziZVCXj48rhG1H4o0gITbJyiu6gQ4gBDTiE,13186
387
- dissect.target-3.21.dev6.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
388
- dissect.target-3.21.dev6.dist-info/entry_points.txt,sha256=BWuxAb_6AvUAQpIQOQU0IMTlaF6TDht2AIZK8bHd-zE,492
389
- dissect.target-3.21.dev6.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
390
- dissect.target-3.21.dev6.dist-info/RECORD,,
385
+ dissect.target-3.21.dev8.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
386
+ dissect.target-3.21.dev8.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
387
+ dissect.target-3.21.dev8.dist-info/METADATA,sha256=HUElMGCd6uXoyl2UOs5_wEXae0KhByPqu-CqetFqYCU,13186
388
+ dissect.target-3.21.dev8.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
389
+ dissect.target-3.21.dev8.dist-info/entry_points.txt,sha256=BWuxAb_6AvUAQpIQOQU0IMTlaF6TDht2AIZK8bHd-zE,492
390
+ dissect.target-3.21.dev8.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
391
+ dissect.target-3.21.dev8.dist-info/RECORD,,