dissect.target 3.19.dev23__py3-none-any.whl → 3.19.dev25__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.
@@ -1,9 +1,10 @@
1
1
  import logging
2
- from typing import Callable
2
+ from typing import Callable, Iterator
3
3
 
4
4
  from dissect.ntfs.attr import Attribute
5
5
  from dissect.ntfs.c_ntfs import FILE_RECORD_SEGMENT_IN_USE
6
6
  from dissect.ntfs.mft import MftRecord
7
+ from flow.record import Record
7
8
  from flow.record.fieldtypes import windows_path
8
9
 
9
10
  from dissect.target.exceptions import UnsupportedPluginError
@@ -53,7 +54,6 @@ FilesystemStdRecord = TargetRecordDescriptor(
53
54
  ],
54
55
  )
55
56
 
56
-
57
57
  FilesystemFilenameCompactRecord = TargetRecordDescriptor(
58
58
  "filesystem/ntfs/mft/filename/compact",
59
59
  [
@@ -90,6 +90,21 @@ FilesystemFilenameRecord = TargetRecordDescriptor(
90
90
  ],
91
91
  )
92
92
 
93
+ FilesystemMACBRecord = TargetRecordDescriptor(
94
+ "filesystem/ntfs/mft/macb",
95
+ [
96
+ ("datetime", "ts"),
97
+ ("string", "macb"),
98
+ ("uint32", "filename_index"),
99
+ ("uint32", "segment"),
100
+ ("path", "path"),
101
+ ("string", "owner"),
102
+ ("filesize", "filesize"),
103
+ ("boolean", "resident"),
104
+ ("boolean", "inuse"),
105
+ ("string", "volume_uuid"),
106
+ ],
107
+ )
93
108
 
94
109
  RECORD_TYPES = {
95
110
  InformationType.STANDARD_INFORMATION: FilesystemStdRecord,
@@ -118,7 +133,12 @@ class MftPlugin(Plugin):
118
133
  ]
119
134
  )
120
135
  @arg("--compact", action="store_true", help="compacts the MFT entry timestamps into a single record")
121
- def mft(self, compact: bool = False):
136
+ @arg(
137
+ "--macb",
138
+ action="store_true",
139
+ help="compacts the MFT entry timestamps into aggregated records with MACB bitfield",
140
+ )
141
+ def mft(self, compact: bool = False, macb: bool = False):
122
142
  """Return the MFT records of all NTFS filesystems.
123
143
 
124
144
  The Master File Table (MFT) contains primarily metadata about every file and folder on a NFTS filesystem.
@@ -133,10 +153,19 @@ class MftPlugin(Plugin):
133
153
  - https://docs.microsoft.com/en-us/windows/win32/fileio/master-file-table
134
154
  """
135
155
 
136
- if compact:
156
+ record_formatter = formatter
157
+
158
+ def noaggr(records: list[Record]) -> Iterator[Record]:
159
+ yield from records
160
+
161
+ aggr = noaggr
162
+
163
+ if compact and macb:
164
+ raise ValueError("--macb and --compact are mutually exclusive")
165
+ elif compact:
137
166
  record_formatter = compacted_formatter
138
- else:
139
- record_formatter = formatter
167
+ elif macb:
168
+ aggr = macb_aggr
140
169
 
141
170
  for fs in self.target.filesystems:
142
171
  if fs.__type__ != "ntfs":
@@ -167,17 +196,19 @@ class MftPlugin(Plugin):
167
196
 
168
197
  for path in record.full_paths():
169
198
  path = f"{drive_letter}{path}"
170
- yield from self.mft_records(
171
- drive_letter=drive_letter,
172
- record=record,
173
- segment=record.segment,
174
- path=path,
175
- owner=owner,
176
- size=size,
177
- resident=resident,
178
- inuse=inuse,
179
- volume_uuid=volume_uuid,
180
- record_formatter=record_formatter,
199
+ yield from aggr(
200
+ self.mft_records(
201
+ drive_letter=drive_letter,
202
+ record=record,
203
+ segment=record.segment,
204
+ path=path,
205
+ owner=owner,
206
+ size=size,
207
+ resident=resident,
208
+ inuse=inuse,
209
+ volume_uuid=volume_uuid,
210
+ record_formatter=record_formatter,
211
+ )
181
212
  )
182
213
  except Exception as e:
183
214
  self.target.log.warning("An error occured parsing MFT segment %d: %s", record.segment, str(e))
@@ -275,3 +306,33 @@ def formatter(attr: Attribute, record_type: InformationType, **kwargs):
275
306
  ("A", attr.last_access_time),
276
307
  ]:
277
308
  yield record_desc(ts=timestamp, ts_type=type, **kwargs)
309
+
310
+
311
+ def macb_aggr(records: list[Record]) -> Iterator[Record]:
312
+ def macb_set(bitfield, index, letter):
313
+ return bitfield[:index] + letter + bitfield[index + 1 :]
314
+
315
+ macbs = []
316
+ for record in records:
317
+ found = False
318
+
319
+ offset_std = int(record._desc.name == "filesystem/ntfs/mft/std") * 5
320
+ offset_ads = (int(record.ads) * 10) if offset_std == 0 else 0
321
+
322
+ field = "MACB".find(record.ts_type) + offset_std + offset_ads
323
+ for macb in macbs:
324
+ if macb.ts == record.ts:
325
+ macb.macb = macb_set(macb.macb, field, record.ts_type)
326
+ found = True
327
+ break
328
+
329
+ if found:
330
+ continue
331
+
332
+ macb = FilesystemMACBRecord.init_from_record(record)
333
+ macb.macb = "..../..../...."
334
+ macb.macb = macb_set(macb.macb, field, record.ts_type)
335
+
336
+ macbs.append(macb)
337
+
338
+ yield from macbs
@@ -1,29 +1,38 @@
1
+ from __future__ import annotations
2
+
3
+ import re
1
4
  import struct
5
+ from typing import Iterator
2
6
 
3
7
  from dissect.util.ts import wintimestamp
4
8
 
5
- from dissect.target.exceptions import RegistryValueNotFoundError, UnsupportedPluginError
9
+ from dissect.target.exceptions import (
10
+ RegistryKeyNotFoundError,
11
+ RegistryValueNotFoundError,
12
+ UnsupportedPluginError,
13
+ )
6
14
  from dissect.target.helpers.record import TargetRecordDescriptor
7
- from dissect.target.plugin import Plugin, export, internal
15
+ from dissect.target.helpers.regutil import VirtualKey
16
+ from dissect.target.plugin import Plugin, export
8
17
 
9
18
  UsbRegistryRecord = TargetRecordDescriptor(
10
19
  "windows/registry/usb",
11
20
  [
12
- ("string", "device_type"),
21
+ ("string", "type"),
13
22
  ("string", "serial"),
14
- ("string", "vid"),
15
- ("string", "pid"),
16
- ("string", "rev"),
17
- ("string", "containerid"),
23
+ ("string", "container_id"),
18
24
  ("string", "vendor"),
19
25
  ("string", "product"),
20
- ("string", "version"),
21
- ("string", "friendlyname"),
26
+ ("string", "revision"),
27
+ ("string", "friendly_name"),
22
28
  ("datetime", "first_insert"),
23
29
  ("datetime", "first_install"),
24
30
  ("datetime", "last_insert"),
25
31
  ("datetime", "last_removal"),
26
- ("string", "info_origin"),
32
+ ("string[]", "volumes"),
33
+ ("string[]", "mounts"),
34
+ ("string[]", "users"),
35
+ ("path", "source"),
27
36
  ],
28
37
  )
29
38
 
@@ -34,128 +43,184 @@ USB_DEVICE_PROPERTY_KEYS = {
34
43
  "last_removal": ("0067", "00000067"), # Windows 8 and higer. USB device last removal date.
35
44
  }
36
45
 
46
+ RE_DEVICE_NAME = re.compile(r"^(?P<type>.+?)&Ven_(?P<vendor>.+?)&Prod_(?P<product>.+?)(&Rev_(?P<revision>.+?))?$")
47
+
37
48
 
38
49
  class UsbPlugin(Plugin):
39
- """USB plugin."""
50
+ """Windows USB history plugin.
51
+
52
+ Parses Windows registry data about attached USB devices. Does not parse EVTX EventIDs
53
+ or ``C:\\Windows\\inf\\setupapi(.dev).log``.
40
54
 
41
- # USB device locations
55
+ To get a full picture of the USB history on a Windows machine, you should parse the
56
+ relevant EventIDs using the evtx plugin. For more research on event log USB forensics, see:
57
+ - https://www.researchgate.net/publication/318514858
58
+ - https://dfir.pubpub.org/pub/h78di10n/release/2
59
+ - https://www.senturean.com/posts/19_08_03_usb_storage_forensics_1/#1-system-events
60
+
61
+ Resources:
62
+ - https://hatsoffsecurity.com/2014/06/05/usb-forensics-pt-1-serial-number/
63
+ - http://www.swiftforensics.com/2013/11/windows-8-new-registry-artifacts-part-1.html
64
+ - https://www.sans.org/blog/the-truth-about-usb-device-serial-numbers/
65
+ """
66
+
67
+ # Stores history of mounted USB devices
42
68
  USB_STOR = "HKLM\\SYSTEM\\CurrentControlSet\\Enum\\USBSTOR"
43
- # DeviceContainers holds all USB information. Only present in windows 8 or higher
44
- DEVICE_CONTAINERS = "HKLM\\SYSTEM\\CurrentControlSet\\Control\\DeviceContainers"
45
- USB = "HKLM\\SYSTEM\\CurrentControlSet\\Enum\\USB"
46
- HID = "HKLM\\SYSTEM\\CurrentControlSet\\Enum\\HID"
47
- SCSI = "HKLM\\SYSTEM\\CurrentControlSet\\Enum\\SCSI"
48
69
 
49
- def check_compatible(self) -> None:
50
- if not len(list(self.target.registry.keys(self.USB_STOR))) > 0:
51
- raise UnsupportedPluginError(f"Registry key not found: {self.USB_STOR}")
70
+ # Stores the relation between a USB container_id and the FriendlyName of mounted volume(s) (Windows 7 and up)
71
+ PORTABLE_DEVICES = "HKLM\\SOFTWARE\\Microsoft\\Windows Portable Devices\\Devices"
52
72
 
53
- @internal
54
- def unpack_timestamps(self, usb_reg_properties):
55
- """
56
- Params:
57
- usb_reg_properties (Regf): A registry object with USB properties
58
- Returns:
59
- timestamps (Dict): A dict containing parsed timestamps within passed registry object
60
- """
61
- usb_reg_properties = usb_reg_properties.subkey("{83da6326-97a6-4088-9453-a1923f573b29}")
62
- timestamps = {}
63
-
64
- for device_property, usbstor_values in USB_DEVICE_PROPERTY_KEYS.items():
65
- for usb_val in usbstor_values:
66
- if usb_val in [x.name for x in usb_reg_properties.subkeys()]:
67
- version_key = usb_reg_properties.subkey(usb_val)
68
- if "00000000" in version_key.subkeys():
69
- data_value = version_key.subkey("00000000").value("Data").value
70
- else:
71
- data_value = version_key.value("(Default)").value
72
- timestamps[device_property] = wintimestamp(struct.unpack("<Q", data_value)[0])
73
- break
74
- else:
75
- timestamps[device_property] = None
76
- return timestamps
73
+ # Stores the most recent mapping of a mount letter and a container_id
74
+ MOUNT_LETTER_MAP = "HKLM\\SYSTEM\\MountedDevices"
77
75
 
78
- @internal
79
- def parse_device_name(self, device_name):
80
- device_info = device_name.split("&")
81
- device_type = device_info[0]
82
- vendor = device_info[1].split("Ven_")[1]
83
- product = device_info[2].split("Prod_")[1]
84
- version = None if len(device_info) < 4 else device_info[3].split("Rev_")[1]
76
+ # User history of mount points accesses in explorer.exe
77
+ USER_MOUNTS = "HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Mountpoints2"
85
78
 
86
- return dict(device_type=device_type, vendor=vendor, product=product, version=version)
79
+ # Other artifacts we currently do not parse:
80
+ # - "sysvol\Windows\inf\setupapi(.dev).log"
81
+ # - "HKLM\\SYSTEM\\CurrentControlSet\\Enum\\USB"
82
+ # - "HKLM\\SYSTEM\\CurrentControlSet\\Enum\\HID"
83
+ # - "HKLM\\SYSTEM\\CurrentControlSet\\Enum\\SCSI"
84
+ # - "HKLM\\SYSTEM\\CurrentControlSet\\Control\\DeviceContainers"
85
+ # - "SOFTWARE\Microsoft\Windows NT\CurrentVersion\EMDMgmt"
86
+
87
+ def check_compatible(self) -> None:
88
+ if not list(self.target.registry.keys(self.USB_STOR)):
89
+ raise UnsupportedPluginError(f"Registry key not found: {self.USB_STOR}")
87
90
 
88
91
  @export(record=UsbRegistryRecord)
89
- def usb(self):
90
- """Return information about attached USB devices.
91
-
92
- Use the registry to find information about USB devices that have been attached to the system, for example the
93
- HKLM\\SYSTEM\\CurrentControlSet\\Enum\\USBSTOR registry key.
94
-
95
- Yields UsbRegistryRecord with fields:
96
-
97
- .. code-block:: text
98
-
99
- hostname (string): The target hostname
100
- domain (string): The target domain
101
- type (string): Type of USB device
102
- serial (string): Serial number of USB storage device
103
- vid (string): Vendor ID of USB storage device
104
- pid (string): Product ID of the USB storage device
105
- rev (string): Version of the USB storage device
106
- containerid (string):
107
- friendlyname (string): Display name of the USB storage device
108
- first_insert (datetime): First insertion date of USB storage device
109
- first_install (datetime): First instalation date of USB storage device
110
- last_insert (datetime): Most recent insertion (arrival) date of USB storage device
111
- last_removal (datetime): Most recent removal (unplug) date of USB storage device
112
- info_origin (string): Location of info present in output
92
+ def usb(self) -> Iterator[UsbRegistryRecord]:
93
+ """Yields information about (historically) attached USB storage devices on Windows.
94
+
95
+ Uses the registry to find information about USB storage devices that have been attached to the system.
96
+ Also tries to find the past volume name and mount letters of the USB device and what user(s) interacted
97
+ with them using ``explorer.exe``.
113
98
  """
114
99
 
115
- for k in self.target.registry.keys(self.USB_STOR):
116
- info_origin = "\\".join((k.path, k.name))
117
- usb_stor = k.subkeys()
100
+ for key in self.target.registry.keys(self.USB_STOR):
101
+ for usb_type in key.subkeys():
102
+ try:
103
+ device_info = parse_device_name(usb_type.name)
104
+ except ValueError:
105
+ self.target.log.warning("Unable to parse USB device name: %s", usb_type.name)
106
+ device_info = {"type": None, "vendor": None, "product": None, "revision": None}
118
107
 
119
- for usb_type in usb_stor:
120
- device_info = self.parse_device_name(usb_type.name)
121
- usb_devices = usb_type.subkeys()
122
- for usb_device in usb_devices:
123
- properties = list(usb_device.subkeys())
108
+ for usb_device in usb_type.subkeys():
124
109
  serial = usb_device.name
110
+ friendly_name = None
111
+ container_id = None
112
+ timestamps = {
113
+ "first_install": None,
114
+ "first_insert": None,
115
+ "last_insert": None,
116
+ "last_removal": None,
117
+ }
118
+
125
119
  try:
126
- friendlyname = usb_device.value("FriendlyName").value
127
- # NOTE: make this more gracefull, windows 10 does not have the LogConf subkey
128
- timestamps = (
129
- self.unpack_timestamps(properties[2])
130
- if len(properties) == 3
131
- else self.unpack_timestamps(properties[1])
132
- )
133
- # ContainerIDs can be found back in USB and WdpBusEnumRoot
134
- containerid = usb_device.value("ContainerID").value
120
+ friendly_name = usb_device.value("FriendlyName").value
135
121
  except RegistryValueNotFoundError:
136
- friendlyname = None
137
- timestamps = {
138
- "first_install": None,
139
- "first_insert": None,
140
- "last_insert": None,
141
- "last_removal": None,
142
- }
143
- containerid = None
122
+ self.target.log.warning("No FriendlyName for USB with serial: %s", serial)
123
+ pass
124
+
125
+ try:
126
+ container_id = usb_device.value("ContainerID").value
127
+ except RegistryValueNotFoundError:
128
+ self.target.log.warning("No ContainerID for USB with serial: %s", serial)
129
+
130
+ try:
131
+ timestamps = unpack_timestamps(usb_device.subkey("Properties"))
132
+ except RegistryValueNotFoundError as e:
133
+ self.target.log.warning("Unable to parse USBSTOR registry properties for serial: %s", serial)
134
+ self.target.log.debug("", exc_info=e)
135
+
136
+ # We can check if any HKCU hive(s) are populated with the Volume GUID of the USB storage device.
137
+ # If a user has interacted with the mounted volume using explorer.exe we will get a match.
138
+ volumes = list(self.find_volumes(serial))
139
+ mounts = list(self.find_mounts(serial))
140
+ users = [
141
+ u.user.name for u in self.find_users([m[10:] for m in mounts if m.startswith("\\??\\Volume{")])
142
+ ]
144
143
 
145
144
  yield UsbRegistryRecord(
146
- device_type=device_info["device_type"],
147
- friendlyname=friendlyname,
145
+ friendly_name=friendly_name,
148
146
  serial=serial,
149
- vid=None,
150
- pid=None,
151
- vendor=device_info["vendor"],
152
- product=device_info["product"],
153
- version=device_info["version"],
154
- containerid=containerid,
155
- first_install=timestamps["first_install"],
156
- first_insert=timestamps["first_insert"],
157
- last_insert=timestamps["last_insert"], # AKA first arrival
158
- last_removal=timestamps["last_removal"],
159
- info_origin=info_origin,
147
+ container_id=container_id,
148
+ **device_info,
149
+ **timestamps,
150
+ volumes=volumes,
151
+ mounts=mounts,
152
+ users=users,
153
+ source=self.USB_STOR,
160
154
  _target=self.target,
161
155
  )
156
+
157
+ def find_volumes(self, serial: str) -> Iterator[str]:
158
+ """Attempts to find mounted volume names for the given serial."""
159
+ serial = serial.lower()
160
+ try:
161
+ for device in self.target.registry.key(self.PORTABLE_DEVICES).subkeys():
162
+ if serial in device.name.lower():
163
+ yield device.value("FriendlyName").value
164
+ except RegistryKeyNotFoundError:
165
+ pass
166
+
167
+ def find_mounts(self, serial: str) -> Iterator[str]:
168
+ """Attempts to find drive letters the given serial has been mounted on."""
169
+ serial = serial.lower()
170
+ try:
171
+ for mount in self.target.registry.key(self.MOUNT_LETTER_MAP).values():
172
+ try:
173
+ if serial in mount.value.decode("utf-16-le").lower():
174
+ yield mount.name.replace("\\DosDevices\\", "")
175
+ except UnicodeDecodeError:
176
+ pass
177
+ except RegistryKeyNotFoundError:
178
+ pass
179
+
180
+ def find_users(self, volume_guids: list[str]) -> Iterator[str]:
181
+ """Attempt to find Windows users that have interacted with the given volume GUIDs."""
182
+
183
+ for volume_guid in volume_guids:
184
+ try:
185
+ for key in self.target.registry.key(self.USER_MOUNTS + "\\" + volume_guid):
186
+ yield self.target.registry.get_user_details(key)
187
+ except RegistryKeyNotFoundError:
188
+ pass
189
+
190
+
191
+ def unpack_timestamps(usb_reg_properties: VirtualKey) -> dict[str, int]:
192
+ """Unpack relevant Windows timestamps from the provided USB registry properties subkey.
193
+
194
+ Args:
195
+ usb_reg_properties: A registry object with USB properties.
196
+
197
+ Returns:
198
+ A dict containing parsed timestamps within passed registry object.
199
+ """
200
+
201
+ usb_reg_properties = usb_reg_properties.subkey("{83da6326-97a6-4088-9453-a1923f573b29}")
202
+ timestamps = {}
203
+
204
+ for device_property, usbstor_values in USB_DEVICE_PROPERTY_KEYS.items():
205
+ for usb_val in usbstor_values:
206
+ if usb_val in [x.name for x in usb_reg_properties.subkeys()]:
207
+ version_key = usb_reg_properties.subkey(usb_val)
208
+ if "00000000" in version_key.subkeys():
209
+ data_value = version_key.subkey("00000000").value("Data").value
210
+ else:
211
+ data_value = version_key.value("(Default)").value
212
+ timestamps[device_property] = wintimestamp(struct.unpack("<Q", data_value)[0])
213
+ break
214
+ else:
215
+ timestamps[device_property] = None
216
+ return timestamps
217
+
218
+
219
+ def parse_device_name(device_name: str) -> dict[str, str]:
220
+ """Parse a registry device name into components."""
221
+
222
+ match = RE_DEVICE_NAME.match(device_name)
223
+ if not match:
224
+ raise ValueError(f"Unable to parse USB device name: {device_name}")
225
+
226
+ return match.groupdict()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dissect.target
3
- Version: 3.19.dev23
3
+ Version: 3.19.dev25
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
@@ -166,7 +166,7 @@ dissect/target/plugins/filesystem/resolver.py,sha256=HfyASUFV4F9uD-yFXilFpPTORAs
166
166
  dissect/target/plugins/filesystem/walkfs.py,sha256=e8HEZcV5Wiua26FGWL3xgiQ_PIhcNvGI5KCdsAx2Nmo,2298
167
167
  dissect/target/plugins/filesystem/yara.py,sha256=JdWqbqDBhKrht3fTroqX7NpBU9khEQUWyMcDgLv2l2g,6686
168
168
  dissect/target/plugins/filesystem/ntfs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
169
- dissect/target/plugins/filesystem/ntfs/mft.py,sha256=AD3w2FIjDAf8x2KEbBhz2NeOA_lxIAmw353w6J3ObYU,9565
169
+ dissect/target/plugins/filesystem/ntfs/mft.py,sha256=2ibCLJA7yUrZshFSPKdjoNt3TpfwTtk-DaErghe91CM,11445
170
170
  dissect/target/plugins/filesystem/ntfs/mft_timeline.py,sha256=vvNFAZbr7s3X2OTYf4ES_L6-XsouTXcTymfxnHfZ1Rw,6791
171
171
  dissect/target/plugins/filesystem/ntfs/usnjrnl.py,sha256=uiT1ipmcAo__6VIUi8R_vvIu22vdnjMACKwLSAbzYjs,3704
172
172
  dissect/target/plugins/filesystem/ntfs/utils.py,sha256=xG7Lgw9NX4tDDrZVRm0vycFVJTOM7j-HrjqzDh0f4uA,3136
@@ -316,7 +316,7 @@ dissect/target/plugins/os/windows/regf/runkeys.py,sha256=-2HcdnVytzCt1xwgAI8rHDn
316
316
  dissect/target/plugins/os/windows/regf/shellbags.py,sha256=hXAqThFkHmGPmhNRSXwMNzw25kAyIC6OOZivgpPEwTQ,25679
317
317
  dissect/target/plugins/os/windows/regf/shimcache.py,sha256=no78i0nxbnfgDJ5TpDZNAJggCigD_zLrXNYss7gdg2Q,9994
318
318
  dissect/target/plugins/os/windows/regf/trusteddocs.py,sha256=3yvpBDM-Asg0rvGN2TwALGRm9DYogG6TxRau9D6FBbw,3700
319
- dissect/target/plugins/os/windows/regf/usb.py,sha256=hR5fnqy_sint1YyWgm1-AMhGQ4MxJOH_Wz0vbYzr9p4,7213
319
+ dissect/target/plugins/os/windows/regf/usb.py,sha256=nSAHB4Cdd0wF2C1EK_XYOfWCyqOgTZCLfDhuSmr7rdM,9709
320
320
  dissect/target/plugins/os/windows/regf/userassist.py,sha256=bSioEQdqUxdGwkdgMUfDIY2_pzrl9PdxPjmzmMaIwHs,5490
321
321
  dissect/target/plugins/os/windows/task_helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
322
322
  dissect/target/plugins/os/windows/task_helpers/tasks_job.py,sha256=7w3UGOiTAUQkP3xQ3sj4X3MTgHUJmmfdgiEadWmYquI,21197
@@ -346,10 +346,10 @@ dissect/target/volumes/luks.py,sha256=OmCMsw6rCUXG1_plnLVLTpsvE1n_6WtoRUGQbpmu1z
346
346
  dissect/target/volumes/lvm.py,sha256=wwQVR9I3G9YzmY6UxFsH2Y4MXGBcKL9aayWGCDTiWMU,2269
347
347
  dissect/target/volumes/md.py,sha256=j1K1iKmspl0C_OJFc7-Q1BMWN2OCC5EVANIgVlJ_fIE,1673
348
348
  dissect/target/volumes/vmfs.py,sha256=-LoUbn9WNwTtLi_4K34uV_-wDw2W5hgaqxZNj4UmqAQ,1730
349
- dissect.target-3.19.dev23.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
350
- dissect.target-3.19.dev23.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
351
- dissect.target-3.19.dev23.dist-info/METADATA,sha256=c2q_-Jvv4xRoYAE0jWyTGNV-oOKAD73yjU9Rk5-mavY,12719
352
- dissect.target-3.19.dev23.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
353
- dissect.target-3.19.dev23.dist-info/entry_points.txt,sha256=BWuxAb_6AvUAQpIQOQU0IMTlaF6TDht2AIZK8bHd-zE,492
354
- dissect.target-3.19.dev23.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
355
- dissect.target-3.19.dev23.dist-info/RECORD,,
349
+ dissect.target-3.19.dev25.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
350
+ dissect.target-3.19.dev25.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
351
+ dissect.target-3.19.dev25.dist-info/METADATA,sha256=7Zg79geLIProzjOZaFpDxr0Zfurfq0EgleNkmo8sI5E,12719
352
+ dissect.target-3.19.dev25.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
353
+ dissect.target-3.19.dev25.dist-info/entry_points.txt,sha256=BWuxAb_6AvUAQpIQOQU0IMTlaF6TDht2AIZK8bHd-zE,492
354
+ dissect.target-3.19.dev25.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
355
+ dissect.target-3.19.dev25.dist-info/RECORD,,