dissect.target 3.19.dev35__py3-none-any.whl → 3.19.dev36__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import logging
2
4
  from typing import Callable, Iterator
3
5
 
@@ -8,6 +10,7 @@ from flow.record import Record
8
10
  from flow.record.fieldtypes import windows_path
9
11
 
10
12
  from dissect.target.exceptions import UnsupportedPluginError
13
+ from dissect.target.filesystems.ntfs import NtfsFilesystem
11
14
  from dissect.target.helpers.record import TargetRecordDescriptor
12
15
  from dissect.target.plugin import Plugin, arg, export
13
16
  from dissect.target.plugins.filesystem.ntfs.utils import (
@@ -119,9 +122,12 @@ COMPACT_RECORD_TYPES = {
119
122
 
120
123
 
121
124
  class MftPlugin(Plugin):
125
+ def __init__(self, target):
126
+ super().__init__(target)
127
+ self.ntfs_filesystems = {index: fs for index, fs in enumerate(self.target.filesystems) if fs.__type__ == "ntfs"}
128
+
122
129
  def check_compatible(self) -> None:
123
- ntfs_filesystems = [fs for fs in self.target.filesystems if fs.__type__ == "ntfs"]
124
- if not len(ntfs_filesystems):
130
+ if not len(self.ntfs_filesystems):
125
131
  raise UnsupportedPluginError("No NTFS filesystems found")
126
132
 
127
133
  @export(
@@ -133,12 +139,17 @@ class MftPlugin(Plugin):
133
139
  ]
134
140
  )
135
141
  @arg("--compact", action="store_true", help="compacts the MFT entry timestamps into a single record")
142
+ @arg("--fs", type=int, default=None, help="optional filesystem index, zero indexed")
143
+ @arg("--start", type=int, default=0, help="the first MFT segment number")
144
+ @arg("--end", type=int, default=-1, help="the last MFT segment number")
136
145
  @arg(
137
146
  "--macb",
138
147
  action="store_true",
139
148
  help="compacts the MFT entry timestamps into aggregated records with MACB bitfield",
140
149
  )
141
- def mft(self, compact: bool = False, macb: bool = False):
150
+ def mft(
151
+ self, compact: bool = False, fs: int | None = None, start: int = 0, end: int = -1, macb: bool = False
152
+ ) -> Iterator[Record]:
142
153
  """Return the MFT records of all NTFS filesystems.
143
154
 
144
155
  The Master File Table (MFT) contains primarily metadata about every file and folder on a NFTS filesystem.
@@ -167,55 +178,66 @@ class MftPlugin(Plugin):
167
178
  elif macb:
168
179
  aggr = macb_aggr
169
180
 
170
- for fs in self.target.filesystems:
171
- if fs.__type__ != "ntfs":
172
- continue
173
-
174
- # If this filesystem is a "fake" NTFS filesystem, used to enhance a
175
- # VirtualFilesystem, The driveletter (more accurate mount point)
176
- # returned will be that of the VirtualFilesystem. This makes sure
177
- # the paths returned in the records are actually reachable.
178
- drive_letter = get_drive_letter(self.target, fs)
179
- volume_uuid = get_volume_identifier(fs)
180
-
181
+ if fs is not None:
181
182
  try:
182
- for record in fs.ntfs.mft.segments():
183
- try:
184
- inuse = bool(record.header.Flags & FILE_RECORD_SEGMENT_IN_USE)
185
- owner, _ = get_owner_and_group(record, fs)
186
- resident = False
187
- size = None
188
-
189
- if not record.is_dir():
190
- for data_attribute in record.attributes.DATA:
191
- if data_attribute.name == "":
192
- resident = data_attribute.resident
193
- break
194
-
195
- size = get_record_size(record)
196
-
197
- for path in record.full_paths():
198
- path = f"{drive_letter}{path}"
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
- )
183
+ filesystem = self.ntfs_filesystems[fs]
184
+ except KeyError:
185
+ self.target.log.error("NTFS filesystem with index number %s does not exist", fs)
186
+ return
187
+
188
+ yield from self.segments(filesystem, record_formatter, aggr, start, end)
189
+ else:
190
+ for filesystem in self.ntfs_filesystems.values():
191
+ yield from self.segments(filesystem, record_formatter, aggr, start, end)
192
+
193
+ def segments(
194
+ self, fs: NtfsFilesystem, record_formatter: Callable, aggr: Callable, start: int, end: int
195
+ ) -> Iterator[Record]:
196
+ # If this filesystem is a "fake" NTFS filesystem, used to enhance a
197
+ # VirtualFilesystem, The driveletter (more accurate mount point)
198
+ # returned will be that of the VirtualFilesystem. This makes sure
199
+ # the paths returned in the records are actually reachable.
200
+ drive_letter = get_drive_letter(self.target, fs)
201
+ volume_uuid = get_volume_identifier(fs)
202
+
203
+ try:
204
+ for record in fs.ntfs.mft.segments(start, end):
205
+ try:
206
+ inuse = bool(record.header.Flags & FILE_RECORD_SEGMENT_IN_USE)
207
+ owner, _ = get_owner_and_group(record, fs)
208
+ resident = None
209
+ size = None
210
+
211
+ if not record.is_dir():
212
+ for data_attribute in record.attributes.DATA:
213
+ if data_attribute.name == "":
214
+ resident = data_attribute.resident
215
+ break
216
+
217
+ size = get_record_size(record)
218
+
219
+ for path in record.full_paths():
220
+ path = f"{drive_letter}{path}"
221
+ yield from aggr(
222
+ self.mft_records(
223
+ drive_letter=drive_letter,
224
+ record=record,
225
+ segment=record.segment,
226
+ path=path,
227
+ owner=owner,
228
+ size=size,
229
+ resident=resident,
230
+ inuse=inuse,
231
+ volume_uuid=volume_uuid,
232
+ record_formatter=record_formatter,
212
233
  )
213
- except Exception as e:
214
- self.target.log.warning("An error occured parsing MFT segment %d: %s", record.segment, str(e))
215
- self.target.log.debug("", exc_info=e)
234
+ )
235
+ except Exception as e:
236
+ self.target.log.warning("An error occured parsing MFT segment %d: %s", record.segment, str(e))
237
+ self.target.log.debug("", exc_info=e)
216
238
 
217
- except Exception:
218
- log.exception("An error occured constructing FilesystemRecords")
239
+ except Exception:
240
+ log.exception("An error occured constructing FilesystemRecords")
219
241
 
220
242
  def mft_records(
221
243
  self,
@@ -229,7 +251,7 @@ class MftPlugin(Plugin):
229
251
  inuse: bool,
230
252
  volume_uuid: str,
231
253
  record_formatter: Callable,
232
- ):
254
+ ) -> Iterator[Record]:
233
255
  for attr in record.attributes.STANDARD_INFORMATION:
234
256
  yield from record_formatter(
235
257
  attr=attr,
@@ -286,7 +308,7 @@ class MftPlugin(Plugin):
286
308
  )
287
309
 
288
310
 
289
- def compacted_formatter(attr: Attribute, record_type: InformationType, **kwargs):
311
+ def compacted_formatter(attr: Attribute, record_type: InformationType, **kwargs) -> Iterator[Record]:
290
312
  record_desc = COMPACT_RECORD_TYPES.get(record_type)
291
313
  yield record_desc(
292
314
  creation_time=attr.creation_time,
@@ -297,7 +319,7 @@ def compacted_formatter(attr: Attribute, record_type: InformationType, **kwargs)
297
319
  )
298
320
 
299
321
 
300
- def formatter(attr: Attribute, record_type: InformationType, **kwargs):
322
+ def formatter(attr: Attribute, record_type: InformationType, **kwargs) -> Iterator[Record]:
301
323
  record_desc = RECORD_TYPES.get(record_type)
302
324
  for type, timestamp in [
303
325
  ("B", attr.creation_time),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dissect.target
3
- Version: 3.19.dev35
3
+ Version: 3.19.dev36
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=zh4hU3L_egddLqDeaHDVuCWYhTlNzPYPVak36Q6IMxI,6621
168
168
  dissect/target/plugins/filesystem/ntfs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
169
- dissect/target/plugins/filesystem/ntfs/mft.py,sha256=2ibCLJA7yUrZshFSPKdjoNt3TpfwTtk-DaErghe91CM,11445
169
+ dissect/target/plugins/filesystem/ntfs/mft.py,sha256=WzvKSlH4egvDsuonRQ3AjYS59t9jjFX_-GOsAPLUeSk,12418
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
@@ -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=7ShPtusuLGaIv27SvEETtgsuoQyAa4iAAeOR1NEaajI,1689
348
348
  dissect/target/volumes/vmfs.py,sha256=-LoUbn9WNwTtLi_4K34uV_-wDw2W5hgaqxZNj4UmqAQ,1730
349
- dissect.target-3.19.dev35.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
350
- dissect.target-3.19.dev35.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
351
- dissect.target-3.19.dev35.dist-info/METADATA,sha256=3ApP47TWFjPe5wV6_fuejtFbpr7YL-bwmvPePNKfN1M,12719
352
- dissect.target-3.19.dev35.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
353
- dissect.target-3.19.dev35.dist-info/entry_points.txt,sha256=BWuxAb_6AvUAQpIQOQU0IMTlaF6TDht2AIZK8bHd-zE,492
354
- dissect.target-3.19.dev35.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
355
- dissect.target-3.19.dev35.dist-info/RECORD,,
349
+ dissect.target-3.19.dev36.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
350
+ dissect.target-3.19.dev36.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
351
+ dissect.target-3.19.dev36.dist-info/METADATA,sha256=MWrzVxs5DUZf35Z7ZkNFIJ7s3CIJdFUM-b5aQiko0HU,12719
352
+ dissect.target-3.19.dev36.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
353
+ dissect.target-3.19.dev36.dist-info/entry_points.txt,sha256=BWuxAb_6AvUAQpIQOQU0IMTlaF6TDht2AIZK8bHd-zE,492
354
+ dissect.target-3.19.dev36.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
355
+ dissect.target-3.19.dev36.dist-info/RECORD,,