dissect.target 3.19.dev41__py3-none-any.whl → 3.19.dev42__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.
@@ -13,6 +13,17 @@ from dissect.target.helpers import fsutil
13
13
  log = logging.getLogger(__name__)
14
14
 
15
15
 
16
+ def findall(buf: bytes, needle: bytes) -> Iterator[int]:
17
+ offset = 0
18
+ while True:
19
+ offset = buf.find(needle, offset)
20
+ if offset == -1:
21
+ break
22
+
23
+ yield offset
24
+ offset += 1
25
+
26
+
16
27
  class StrEnum(str, Enum):
17
28
  """Sortable and serializible string-based enum"""
18
29
 
@@ -5,6 +5,7 @@ from flow.record.fieldtypes import digest
5
5
 
6
6
  from dissect.target.exceptions import UnsupportedPluginError
7
7
  from dissect.target.helpers.record import TargetRecordDescriptor
8
+ from dissect.target.helpers.utils import findall
8
9
  from dissect.target.plugin import Plugin, export
9
10
 
10
11
  try:
@@ -36,17 +37,6 @@ CatrootRecord = TargetRecordDescriptor(
36
37
  )
37
38
 
38
39
 
39
- def findall(buf: bytes, needle: bytes) -> Iterator[int]:
40
- offset = 0
41
- while True:
42
- offset = buf.find(needle, offset)
43
- if offset == -1:
44
- break
45
-
46
- yield offset
47
- offset += 1
48
-
49
-
50
40
  def _get_package_name(sequence: Sequence) -> str:
51
41
  """Parse sequences within a sequence and return the 'PackageName' value if it exists."""
52
42
  for value in sequence.native.values():
@@ -0,0 +1,292 @@
1
+ from __future__ import annotations
2
+
3
+ import io
4
+ import logging
5
+ from struct import error as StructError
6
+ from typing import BinaryIO, Iterator
7
+
8
+ from dissect.cstruct import cstruct
9
+ from dissect.ole import OLE
10
+ from dissect.ole.exceptions import Error as OleError
11
+ from dissect.shellitem.lnk import Lnk
12
+
13
+ from dissect.target import Target
14
+ from dissect.target.exceptions import UnsupportedPluginError
15
+ from dissect.target.helpers.descriptor_extensions import UserRecordDescriptorExtension
16
+ from dissect.target.helpers.record import create_extended_descriptor
17
+ from dissect.target.helpers.shell_application_ids import APPLICATION_IDENTIFIERS
18
+ from dissect.target.helpers.utils import findall
19
+ from dissect.target.plugin import Plugin, export
20
+ from dissect.target.plugins.os.windows.lnk import LnkRecord, parse_lnk_file
21
+
22
+ log = logging.getLogger(__name__)
23
+
24
+ LNK_GUID = b"\x01\x14\x02\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\x46"
25
+
26
+ JumpListRecord = create_extended_descriptor([UserRecordDescriptorExtension])(
27
+ "windows/jumplist",
28
+ [
29
+ ("string", "type"),
30
+ ("string", "application_id"),
31
+ ("string", "application_name"),
32
+ *LnkRecord.target_fields,
33
+ ],
34
+ )
35
+
36
+
37
+ custom_destination_def = """
38
+ struct header {
39
+ int version;
40
+ int unknown1;
41
+ int unknown2;
42
+ int value_type;
43
+ }
44
+
45
+ struct header_end {
46
+ int number_of_entries;
47
+ }
48
+
49
+ struct header_end_0 {
50
+ uint16 name_length;
51
+ wchar name[name_length];
52
+ int number_of_entries;
53
+ }
54
+
55
+ struct footer {
56
+ char magic[4];
57
+ }
58
+ """
59
+
60
+ c_custom_destination = cstruct()
61
+ c_custom_destination.load(custom_destination_def)
62
+
63
+
64
+ class JumpListFile:
65
+ def __init__(self, fh: BinaryIO, file_name: str):
66
+ self.fh = fh
67
+ self.file_name = file_name
68
+
69
+ self.application_id, self.application_type = file_name.split(".")
70
+ self.application_type = self.application_type.split("-")[0]
71
+ self.application_name = APPLICATION_IDENTIFIERS.get(self.application_id)
72
+
73
+ def __iter__(self) -> Iterator[Lnk]:
74
+ raise NotImplementedError
75
+
76
+ @property
77
+ def name(self) -> str:
78
+ """Return the name of the application."""
79
+ return self.application_name
80
+
81
+ @property
82
+ def id(self) -> str:
83
+ """Return the application identifier."""
84
+ return self.application_id
85
+
86
+ @property
87
+ def type(self) -> str:
88
+ """Return the type of the Jump List file."""
89
+ return self.application_type
90
+
91
+
92
+ class AutomaticDestinationFile(JumpListFile):
93
+ """Parse Jump List AutomaticDestination file."""
94
+
95
+ def __init__(self, fh: BinaryIO, file_name: str):
96
+ super().__init__(fh, file_name)
97
+ self.ole = OLE(self.fh)
98
+
99
+ def __iter__(self) -> Iterator[Lnk]:
100
+ for dir_name in self.ole.root.listdir():
101
+ if dir_name == "DestList":
102
+ continue
103
+
104
+ dir = self.ole.get(dir_name)
105
+
106
+ for item in dir.open():
107
+ try:
108
+ yield Lnk(io.BytesIO(item))
109
+ except StructError:
110
+ continue
111
+ except Exception as e:
112
+ log.warning("Failed to parse LNK file from directory %s", dir_name)
113
+ log.debug("", exc_info=e)
114
+ continue
115
+
116
+
117
+ class CustomDestinationFile(JumpListFile):
118
+ """Parse Jump List CustomDestination file."""
119
+
120
+ MAGIC_FOOTER = 0xBABFFBAB
121
+ VERSIONS = [2]
122
+
123
+ def __init__(self, fh: BinaryIO, file_name: str):
124
+ super().__init__(fh, file_name)
125
+
126
+ self.fh.seek(-4, io.SEEK_END)
127
+ self.footer = c_custom_destination.footer(self.fh.read(4))
128
+ self.magic = int.from_bytes(self.footer.magic, "little")
129
+
130
+ self.fh.seek(0, io.SEEK_SET)
131
+ self.header = c_custom_destination.header(self.fh)
132
+ self.version = self.header.version
133
+
134
+ if self.header.value_type == 0:
135
+ self.header_end = c_custom_destination.header_end_0(self.fh)
136
+ elif self.header.value_type in [1, 2]:
137
+ self.header_end = c_custom_destination.header_end(self.fh)
138
+ else:
139
+ raise NotImplementedError(
140
+ f"The value_type ({self.header.value_type}) of the CustomDestination file is not implemented"
141
+ )
142
+
143
+ if self.version not in self.VERSIONS:
144
+ raise NotImplementedError(f"The CustomDestination file has an unsupported version: {self.version}")
145
+
146
+ if not self.MAGIC_FOOTER == self.magic:
147
+ raise ValueError(f"The CustomDestination file has an invalid magic footer: {self.magic}")
148
+
149
+ def __iter__(self) -> Iterator[Lnk]:
150
+ # Searches for all LNK GUID's because the number of entries in the header is not always correct.
151
+ buf = self.fh.read()
152
+
153
+ for offset in findall(buf, LNK_GUID):
154
+ try:
155
+ lnk = Lnk(io.BytesIO(buf[offset + len(LNK_GUID) :]))
156
+ yield lnk
157
+ except EOFError:
158
+ break
159
+ except Exception as e:
160
+ log.warning("Failed to parse LNK file from a CustomDestination file")
161
+ log.debug("", exc_info=e)
162
+ continue
163
+
164
+
165
+ class JumpListPlugin(Plugin):
166
+ """Jump List is a Windows feature introduced in Windows 7.
167
+
168
+ It stores information about recently accessed applications and files.
169
+
170
+ References:
171
+ - https://forensics.wiki/jump_lists
172
+ - https://github.com/libyal/dtformats/blob/main/documentation/Jump%20lists%20format.asciidoc
173
+ """
174
+
175
+ __namespace__ = "jumplist"
176
+
177
+ def __init__(self, target: Target):
178
+ super().__init__(target)
179
+ self.automatic_destinations = []
180
+ self.custom_destinations = []
181
+
182
+ for user_details in self.target.user_details.all_with_home():
183
+ for destination in user_details.home_path.glob(
184
+ "AppData/Roaming/Microsoft/Windows/Recent/CustomDestinations/*.customDestinations-ms"
185
+ ):
186
+ self.custom_destinations.append([destination, user_details.user])
187
+
188
+ for user_details in self.target.user_details.all_with_home():
189
+ for destination in user_details.home_path.glob(
190
+ "AppData/Roaming/Microsoft/Windows/Recent/AutomaticDestinations/*.automaticDestinations-ms"
191
+ ):
192
+ self.automatic_destinations.append([destination, user_details.user])
193
+
194
+ def check_compatible(self) -> None:
195
+ if not any([self.automatic_destinations, self.custom_destinations]):
196
+ raise UnsupportedPluginError("No Jump List files found")
197
+
198
+ @export(record=JumpListRecord)
199
+ def custom_destination(self) -> Iterator[JumpListRecord]:
200
+ """Return the content of CustomDestination Windows Jump Lists.
201
+
202
+ These are created when a user pins an application or a file in a Jump List.
203
+
204
+ Yields JumpListRecord with fields:
205
+
206
+ .. code-block:: text
207
+
208
+ type (string): Type of Jump List.
209
+ application_id (string): ID of the application.
210
+ application_name (string): Name of the application.
211
+ lnk_path (path): Path of the link (.lnk) file.
212
+ lnk_name (string): Name of the link (.lnk) file.
213
+ lnk_mtime (datetime): Modification time of the link (.lnk) file.
214
+ lnk_atime (datetime): Access time of the link (.lnk) file.
215
+ lnk_ctime (datetime): Creation time of the link (.lnk) file.
216
+ lnk_relativepath (path): Relative path of target file to the link (.lnk) file.
217
+ lnk_workdir (path): Path of the working directory the link (.lnk) file will execute from.
218
+ lnk_iconlocation (path): Path of the display icon used for the link (.lnk) file.
219
+ lnk_arguments (string): Command-line arguments passed to the target (linked) file.
220
+ local_base_path (string): Absolute path of the target (linked) file.
221
+ common_path_suffix (string): Suffix of the local_base_path.
222
+ lnk_full_path (string): Full path of the linked file. Made from local_base_path and common_path_suffix.
223
+ lnk_net_name (string): Specifies a server share path; for example, "\\\\server\\share".
224
+ lnk_device_name (string): Specifies a device; for example, the drive letter "D:"
225
+ machine_id (string): The NetBIOS name of the machine where the linked file was last known to reside.
226
+ target_mtime (datetime): Modification time of the target (linked) file.
227
+ target_atime (datetime): Access time of the target (linked) file.
228
+ target_ctime (datetime): Creation time of the target (linked) file.
229
+ """
230
+ yield from self._generate_records(self.custom_destinations, CustomDestinationFile)
231
+
232
+ @export(record=JumpListRecord)
233
+ def automatic_destination(self) -> Iterator[JumpListRecord]:
234
+ """Return the content of AutomaticDestination Windows Jump Lists.
235
+
236
+ These are created automatically when a user opens an application or file.
237
+
238
+ Yields JumpListRecord with fields:
239
+
240
+ .. code-block:: text
241
+
242
+ type (string): Type of Jump List.
243
+ application_id (string): ID of the application.
244
+ application_name (string): Name of the application.
245
+ lnk_path (path): Path of the link (.lnk) file.
246
+ lnk_name (string): Name of the link (.lnk) file.
247
+ lnk_mtime (datetime): Modification time of the link (.lnk) file.
248
+ lnk_atime (datetime): Access time of the link (.lnk) file.
249
+ lnk_ctime (datetime): Creation time of the link (.lnk) file.
250
+ lnk_relativepath (path): Relative path of target file to the link (.lnk) file.
251
+ lnk_workdir (path): Path of the working directory the link (.lnk) file will execute from.
252
+ lnk_iconlocation (path): Path of the display icon used for the link (.lnk) file.
253
+ lnk_arguments (string): Command-line arguments passed to the target (linked) file.
254
+ local_base_path (string): Absolute path of the target (linked) file.
255
+ common_path_suffix (string): Suffix of the local_base_path.
256
+ lnk_full_path (string): Full path of the linked file. Made from local_base_path and common_path_suffix.
257
+ lnk_net_name (string): Specifies a server share path; for example, "\\\\server\\share".
258
+ lnk_device_name (string): Specifies a device; for example, the drive letter "D:"
259
+ machine_id (string): The NetBIOS name of the machine where the linked file was last known to reside.
260
+ target_mtime (datetime): Modification time of the target (linked) file.
261
+ target_atime (datetime): Access time of the target (linked) file.
262
+ target_ctime (datetime): Creation time of the target (linked) file.
263
+ """
264
+ yield from self._generate_records(self.automatic_destinations, AutomaticDestinationFile)
265
+
266
+ def _generate_records(
267
+ self,
268
+ destinations: list,
269
+ destination_file: AutomaticDestinationFile | CustomDestinationFile,
270
+ ) -> Iterator[JumpListRecord]:
271
+ for destination, user in destinations:
272
+ fh = destination.open("rb")
273
+
274
+ try:
275
+ jumplist = destination_file(fh, destination.name)
276
+ except OleError:
277
+ continue
278
+ except Exception as e:
279
+ self.target.log.warning("Failed to parse Jump List file: %s", destination)
280
+ self.target.log.debug("", exc_info=e)
281
+ continue
282
+
283
+ for lnk in jumplist:
284
+ if lnk := parse_lnk_file(self.target, lnk, destination):
285
+ yield JumpListRecord(
286
+ type=jumplist.type,
287
+ application_name=jumplist.name,
288
+ application_id=jumplist.id,
289
+ **lnk._asdict(),
290
+ _user=user,
291
+ _target=self.target,
292
+ )
@@ -34,6 +34,89 @@ LnkRecord = TargetRecordDescriptor(
34
34
  )
35
35
 
36
36
 
37
+ def parse_lnk_file(target: Target, lnk_file: Lnk, lnk_path: TargetPath) -> Iterator[LnkRecord]:
38
+ # we need to get the active codepage from the system to properly decode some values
39
+ codepage = target.codepage or "ascii"
40
+
41
+ lnk_net_name = lnk_device_name = None
42
+
43
+ if lnk_file.link_header:
44
+ lnk_name = lnk_file.stringdata.name_string.string if lnk_file.flag("has_name") else None
45
+
46
+ lnk_mtime = ts.from_unix(lnk_path.stat().st_mtime)
47
+ lnk_atime = ts.from_unix(lnk_path.stat().st_atime)
48
+ lnk_ctime = ts.from_unix(lnk_path.stat().st_ctime)
49
+
50
+ lnk_relativepath = (
51
+ target.fs.path(lnk_file.stringdata.relative_path.string) if lnk_file.flag("has_relative_path") else None
52
+ )
53
+ lnk_workdir = (
54
+ target.fs.path(lnk_file.stringdata.working_dir.string) if lnk_file.flag("has_working_dir") else None
55
+ )
56
+ lnk_iconlocation = (
57
+ target.fs.path(lnk_file.stringdata.icon_location.string) if lnk_file.flag("has_icon_location") else None
58
+ )
59
+ lnk_arguments = lnk_file.stringdata.command_line_arguments.string if lnk_file.flag("has_arguments") else None
60
+ local_base_path = (
61
+ lnk_file.linkinfo.local_base_path.decode(codepage)
62
+ if lnk_file.flag("has_link_info") and lnk_file.linkinfo.flag("volumeid_and_local_basepath")
63
+ else None
64
+ )
65
+ common_path_suffix = (
66
+ lnk_file.linkinfo.common_path_suffix.decode(codepage) if lnk_file.flag("has_link_info") else None
67
+ )
68
+
69
+ if local_base_path and common_path_suffix:
70
+ lnk_full_path = target.fs.path(local_base_path + common_path_suffix)
71
+ elif local_base_path and not common_path_suffix:
72
+ lnk_full_path = target.fs.path(local_base_path)
73
+ else:
74
+ lnk_full_path = None
75
+
76
+ if lnk_file.flag("has_link_info"):
77
+ if lnk_file.linkinfo.flag("common_network_relative_link_and_pathsuffix"):
78
+ lnk_net_name = (
79
+ lnk_file.linkinfo.common_network_relative_link.net_name.decode()
80
+ if lnk_file.linkinfo.common_network_relative_link.net_name
81
+ else None
82
+ )
83
+ lnk_device_name = (
84
+ lnk_file.linkinfo.common_network_relative_link.device_name.decode()
85
+ if lnk_file.linkinfo.common_network_relative_link.device_name
86
+ else None
87
+ )
88
+ try:
89
+ machine_id = lnk_file.extradata.TRACKER_PROPS.machine_id.decode(codepage).strip("\x00")
90
+ except AttributeError:
91
+ machine_id = None
92
+
93
+ target_mtime = ts.wintimestamp(lnk_file.link_header.write_time)
94
+ target_atime = ts.wintimestamp(lnk_file.link_header.access_time)
95
+ target_ctime = ts.wintimestamp(lnk_file.link_header.creation_time)
96
+
97
+ return LnkRecord(
98
+ lnk_path=lnk_path,
99
+ lnk_name=lnk_name,
100
+ lnk_mtime=lnk_mtime,
101
+ lnk_atime=lnk_atime,
102
+ lnk_ctime=lnk_ctime,
103
+ lnk_relativepath=lnk_relativepath,
104
+ lnk_workdir=lnk_workdir,
105
+ lnk_iconlocation=lnk_iconlocation,
106
+ lnk_arguments=lnk_arguments,
107
+ local_base_path=local_base_path,
108
+ common_path_suffix=common_path_suffix,
109
+ lnk_full_path=lnk_full_path,
110
+ lnk_net_name=lnk_net_name,
111
+ lnk_device_name=lnk_device_name,
112
+ machine_id=machine_id,
113
+ target_mtime=target_mtime,
114
+ target_atime=target_atime,
115
+ target_ctime=target_ctime,
116
+ _target=target,
117
+ )
118
+
119
+
37
120
  class LnkPlugin(Plugin):
38
121
  def __init__(self, target: Target) -> None:
39
122
  super().__init__(target)
@@ -74,97 +157,9 @@ class LnkPlugin(Plugin):
74
157
  target_ctime (datetime): Creation time of the target (linked) file.
75
158
  """
76
159
 
77
- # we need to get the active codepage from the system to properly decode some values
78
- codepage = self.target.codepage or "ascii"
79
-
80
160
  for entry in self.lnk_entries(path):
81
161
  lnk_file = Lnk(entry.open())
82
- lnk_net_name = lnk_device_name = None
83
-
84
- if lnk_file.link_header:
85
- lnk_path = entry
86
- lnk_name = lnk_file.stringdata.name_string.string if lnk_file.flag("has_name") else None
87
-
88
- lnk_mtime = ts.from_unix(entry.stat().st_mtime)
89
- lnk_atime = ts.from_unix(entry.stat().st_atime)
90
- lnk_ctime = ts.from_unix(entry.stat().st_ctime)
91
-
92
- lnk_relativepath = (
93
- self.target.fs.path(lnk_file.stringdata.relative_path.string)
94
- if lnk_file.flag("has_relative_path")
95
- else None
96
- )
97
- lnk_workdir = (
98
- self.target.fs.path(lnk_file.stringdata.working_dir.string)
99
- if lnk_file.flag("has_working_dir")
100
- else None
101
- )
102
- lnk_iconlocation = (
103
- self.target.fs.path(lnk_file.stringdata.icon_location.string)
104
- if lnk_file.flag("has_icon_location")
105
- else None
106
- )
107
- lnk_arguments = (
108
- lnk_file.stringdata.command_line_arguments.string if lnk_file.flag("has_arguments") else None
109
- )
110
- local_base_path = (
111
- lnk_file.linkinfo.local_base_path.decode(codepage)
112
- if lnk_file.flag("has_link_info") and lnk_file.linkinfo.flag("volumeid_and_local_basepath")
113
- else None
114
- )
115
- common_path_suffix = (
116
- lnk_file.linkinfo.common_path_suffix.decode(codepage) if lnk_file.flag("has_link_info") else None
117
- )
118
-
119
- if local_base_path and common_path_suffix:
120
- lnk_full_path = self.target.fs.path(local_base_path + common_path_suffix)
121
- elif local_base_path and not common_path_suffix:
122
- lnk_full_path = self.target.fs.path(local_base_path)
123
- else:
124
- lnk_full_path = None
125
-
126
- if lnk_file.flag("has_link_info"):
127
- if lnk_file.linkinfo.flag("common_network_relative_link_and_pathsuffix"):
128
- lnk_net_name = (
129
- lnk_file.linkinfo.common_network_relative_link.net_name.decode()
130
- if lnk_file.linkinfo.common_network_relative_link.net_name
131
- else None
132
- )
133
- lnk_device_name = (
134
- lnk_file.linkinfo.common_network_relative_link.device_name.decode()
135
- if lnk_file.linkinfo.common_network_relative_link.device_name
136
- else None
137
- )
138
- try:
139
- machine_id = lnk_file.extradata.TRACKER_PROPS.machine_id.decode(codepage).strip("\x00")
140
- except AttributeError:
141
- machine_id = None
142
-
143
- target_mtime = ts.wintimestamp(lnk_file.link_header.write_time)
144
- target_atime = ts.wintimestamp(lnk_file.link_header.access_time)
145
- target_ctime = ts.wintimestamp(lnk_file.link_header.creation_time)
146
-
147
- yield LnkRecord(
148
- lnk_path=lnk_path,
149
- lnk_name=lnk_name,
150
- lnk_mtime=lnk_mtime,
151
- lnk_atime=lnk_atime,
152
- lnk_ctime=lnk_ctime,
153
- lnk_relativepath=lnk_relativepath,
154
- lnk_workdir=lnk_workdir,
155
- lnk_iconlocation=lnk_iconlocation,
156
- lnk_arguments=lnk_arguments,
157
- local_base_path=local_base_path,
158
- common_path_suffix=common_path_suffix,
159
- lnk_full_path=lnk_full_path,
160
- lnk_net_name=lnk_net_name,
161
- lnk_device_name=lnk_device_name,
162
- machine_id=machine_id,
163
- target_mtime=target_mtime,
164
- target_atime=target_atime,
165
- target_ctime=target_ctime,
166
- _target=self.target,
167
- )
162
+ yield parse_lnk_file(self.target, lnk_file, entry)
168
163
 
169
164
  def lnk_entries(self, path: Optional[str] = None) -> Iterator[TargetPath]:
170
165
  if path:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dissect.target
3
- Version: 3.19.dev41
3
+ Version: 3.19.dev42
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
@@ -72,6 +72,7 @@ Requires-Dist: dissect.extfs <4,>=3 ; extra == 'full'
72
72
  Requires-Dist: dissect.fat <4,>=3 ; extra == 'full'
73
73
  Requires-Dist: dissect.ffs <4,>=3 ; extra == 'full'
74
74
  Requires-Dist: dissect.jffs <2,>=1 ; extra == 'full'
75
+ Requires-Dist: dissect.ole <4,>=3 ; extra == 'full'
75
76
  Requires-Dist: dissect.shellitem <4,>=3 ; extra == 'full'
76
77
  Requires-Dist: dissect.squashfs <2,>=1 ; extra == 'full'
77
78
  Requires-Dist: dissect.sql <4,>=3 ; extra == 'full'
@@ -64,9 +64,10 @@ dissect/target/helpers/protobuf.py,sha256=b4DsnqrRLrefcDjx7rQno-_LBcwtJXxuKf5RdO
64
64
  dissect/target/helpers/record.py,sha256=zwqEnFSgxgX6JdhhF4zycMMZK09crCTWWEFzRxZSuC8,5658
65
65
  dissect/target/helpers/record_modifier.py,sha256=3I_rC5jqvl0TsW3V8OQ6Dltz_D8J4PU1uhhzbJGKm9c,3245
66
66
  dissect/target/helpers/regutil.py,sha256=kX-sSZbW8Qkg29Dn_9zYbaQrwLumrr4Y8zJ1EhHXIAM,27337
67
+ dissect/target/helpers/shell_application_ids.py,sha256=hYxrP-YtHK7ZM0ectJFHfoMB8QUXLbYNKmKXMWLZRlA,38132
67
68
  dissect/target/helpers/shell_folder_ids.py,sha256=Behhb8oh0kMxrEk6YYKYigCDZe8Hw5QS6iK_d2hTs2Y,24978
68
69
  dissect/target/helpers/targetd.py,sha256=ELhUulzQ4OgXgHsWhsLgM14vut8Wm6btr7qTynlwKaE,1812
69
- dissect/target/helpers/utils.py,sha256=r36Bn0UL0E6Z8ajmQrHzC6RyUxTRdwJ1PNsd904Lmzs,4027
70
+ dissect/target/helpers/utils.py,sha256=K3xVq9D0FwIhTBAuiWN8ph7Pq2GABgG3hOz-3AmKuEA,4244
70
71
  dissect/target/helpers/compat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
72
  dissect/target/helpers/compat/path_310.py,sha256=PsLDIodlp3Hv5u-w7GDl6_LnTtchBYcRjz2MicX1egg,16982
72
73
  dissect/target/helpers/compat/path_311.py,sha256=2aydxCMWu1pN8PTBCo8HUbHRMC1xO-hj013j4QxaogE,18182
@@ -262,7 +263,7 @@ dissect/target/plugins/os/windows/_os.py,sha256=uBa0dVkFxDsxHAU3T23UEIOCgAx5R6cI
262
263
  dissect/target/plugins/os/windows/activitiescache.py,sha256=Q2aILnhJ2rp2AwEbWwyBuSLjMbGqaYJTsavSbfkcFKE,6741
263
264
  dissect/target/plugins/os/windows/adpolicy.py,sha256=fULRFO_I_QxAn6G9SCwlLL-TLVliS13JEGnGotf7lSA,6983
264
265
  dissect/target/plugins/os/windows/amcache.py,sha256=ZZNOs3bILTf0AGkDkhoatndl0j39DXkstN7oOyxJECU,27188
265
- dissect/target/plugins/os/windows/catroot.py,sha256=wHW_p4M0aFonZJ2xZFIbgLbJopdCIXO9jVrGPHLsMLc,11105
266
+ dissect/target/plugins/os/windows/catroot.py,sha256=QVwMF5nuMzCkWnoOMs5BkwYoKN61HKmlxo8mKMoD3w8,10937
266
267
  dissect/target/plugins/os/windows/cim.py,sha256=jsrpu6TZpBUh7VWI9AV2Ib5bebTwsvqOwRfa5gjJd7c,3056
267
268
  dissect/target/plugins/os/windows/clfs.py,sha256=begVsZ-CY97Ksh6S1g03LjyBgu8ERY2hfNDWYPj0GXI,4872
268
269
  dissect/target/plugins/os/windows/credhist.py,sha256=YSjuyd53Augdy_lKKzZHtx5Ozt0HzF6LDYIOb-8P1Pw,7058
@@ -270,7 +271,8 @@ dissect/target/plugins/os/windows/datetime.py,sha256=YKHUZU6lkKJocq15y0yCwvIIOb1
270
271
  dissect/target/plugins/os/windows/defender.py,sha256=zh3brEvJmknD5ef0PGuLZ1G95Fgdh-dlgi-ZEbADKXo,32716
271
272
  dissect/target/plugins/os/windows/env.py,sha256=-u9F9xWy6PUbQmu5Tv_MDoVmy6YB-7CbHokIK_T3S44,13891
272
273
  dissect/target/plugins/os/windows/generic.py,sha256=BSvDPfB9faU0uquMj0guw5tnR_97Nn0XAEE4k05BFSQ,22273
273
- dissect/target/plugins/os/windows/lnk.py,sha256=2zpzpPbxL1qrxdbiZfhOGWKNujcj9tMy75_KrBXB1QE,8485
274
+ dissect/target/plugins/os/windows/jumplist.py,sha256=3gZk6O1B3lKK2Jxe0B-HapOCEehk94CYNvCVDpQC9nQ,11773
275
+ dissect/target/plugins/os/windows/lnk.py,sha256=toEZV00CESLUsF7UmN65-ivWk0Ijg-ZPST0qyD-antY,7860
274
276
  dissect/target/plugins/os/windows/locale.py,sha256=yXVdclpUqss9h8Nq7N4kg3OHwWGDfjdfiLiUZR3wqv8,2324
275
277
  dissect/target/plugins/os/windows/notifications.py,sha256=T1CIvQgpW__qDR0Rq5zpeWmRWwjNDpvdMnvJJ_6tZXs,17378
276
278
  dissect/target/plugins/os/windows/prefetch.py,sha256=v4OgSKMwcihz0SOuA0o0Ec8wsAKuiuEmJolqZmHFgJA,10491
@@ -350,10 +352,10 @@ dissect/target/volumes/luks.py,sha256=OmCMsw6rCUXG1_plnLVLTpsvE1n_6WtoRUGQbpmu1z
350
352
  dissect/target/volumes/lvm.py,sha256=wwQVR9I3G9YzmY6UxFsH2Y4MXGBcKL9aayWGCDTiWMU,2269
351
353
  dissect/target/volumes/md.py,sha256=7ShPtusuLGaIv27SvEETtgsuoQyAa4iAAeOR1NEaajI,1689
352
354
  dissect/target/volumes/vmfs.py,sha256=-LoUbn9WNwTtLi_4K34uV_-wDw2W5hgaqxZNj4UmqAQ,1730
353
- dissect.target-3.19.dev41.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
354
- dissect.target-3.19.dev41.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
355
- dissect.target-3.19.dev41.dist-info/METADATA,sha256=6k7QjO0aOrwuszOsHAU-DZhDHHRAq_EhsQloJ_AdgMY,12845
356
- dissect.target-3.19.dev41.dist-info/WHEEL,sha256=HiCZjzuy6Dw0hdX5R3LCFPDmFS4BWl8H-8W39XfmgX4,91
357
- dissect.target-3.19.dev41.dist-info/entry_points.txt,sha256=BWuxAb_6AvUAQpIQOQU0IMTlaF6TDht2AIZK8bHd-zE,492
358
- dissect.target-3.19.dev41.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
359
- dissect.target-3.19.dev41.dist-info/RECORD,,
355
+ dissect.target-3.19.dev42.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
356
+ dissect.target-3.19.dev42.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
357
+ dissect.target-3.19.dev42.dist-info/METADATA,sha256=XF7DS_1vdvBgQLUXWDQ8JfwXd5FAffF06CNgi2LA0DM,12897
358
+ dissect.target-3.19.dev42.dist-info/WHEEL,sha256=HiCZjzuy6Dw0hdX5R3LCFPDmFS4BWl8H-8W39XfmgX4,91
359
+ dissect.target-3.19.dev42.dist-info/entry_points.txt,sha256=BWuxAb_6AvUAQpIQOQU0IMTlaF6TDht2AIZK8bHd-zE,492
360
+ dissect.target-3.19.dev42.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
361
+ dissect.target-3.19.dev42.dist-info/RECORD,,