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

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,,