dissect.target 3.19.dev41__py3-none-any.whl → 3.19.dev42__py3-none-any.whl

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