Create attribute iterator method

Moves logic for iterating through `MFTEntry` attributes into a new
`attributes()` method on the extension class.
This commit is contained in:
David McDonald
2025-04-03 10:40:05 -05:00
parent e84036c5a6
commit 4492da0263
2 changed files with 33 additions and 26 deletions
@@ -114,7 +114,6 @@ class MFTScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface):
# get each of the individual Field Sets
mft_object_type_name = symbol_table + constants.BANG + "MFT_ENTRY"
attribute_object_type_name = symbol_table + constants.BANG + "ATTRIBUTE"
record_map: DefaultDict[str, MFTRecord] = DefaultDict(MFTRecord)
@@ -127,30 +126,9 @@ class MFTScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface):
mft_object_type_name, offset=offset, layer_name=layer.name
)
# We will update this on each pass in the next loop and use it as the new offset.
attr_base_offset = mft_record.FirstAttrOffset
attr: mft.MFTAttribute = context.object(
attribute_object_type_name,
offset=offset + attr_base_offset,
layer_name=layer.name,
)
# There is no field that has a count of Attributes
# Keep Attempting to read attributes until we get an invalid attr_header.AttrType
while attr.Attr_Header.AttrType.is_valid_choice:
yield from attr_callback(record_map, mft_record, attr, symbol_table)
# If there's no advancement the loop will never end, so break it now
if attr.Attr_Header.Length == 0:
break
# Update the base offset to point to the next attribute
attr_base_offset += attr.Attr_Header.Length
# Get the next attribute
attr: mft.MFTAttribute = context.object(
attribute_object_type_name,
offset=offset + attr_base_offset,
layer_name=layer.name,
for attribute in mft_record.attributes(symbol_table):
yield from attr_callback(
record_map, mft_record, attribute, symbol_table
)
@classmethod
@@ -2,7 +2,7 @@
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
#
from typing import Optional
from typing import Optional, Iterator
from volatility3.framework import objects, constants, exceptions
@@ -14,6 +14,35 @@ class MFTEntry(objects.StructType):
signature = self.Signature.cast("string", max_length=4, encoding="latin-1")
return signature
def attributes(self, symbol_table_name: str) -> Iterator["MFTAttribute"]:
# We will update this on each pass in the next loop and use it as the new offset.
attr_base_offset = self.FirstAttrOffset
attribute_object_type_name = symbol_table_name + constants.BANG + "ATTRIBUTE"
attr: MFTAttribute = self._context.object(
attribute_object_type_name,
offset=self.vol.offset + attr_base_offset,
layer_name=self.vol.layer_name,
)
# There is no field that has a count of Attributes
# Keep Attempting to read attributes until we get an invalid attr_header.AttrType
while attr.Attr_Header.AttrType.is_valid_choice:
yield attr
# If there's no advancement the loop will never end, so break it now
if attr.Attr_Header.Length == 0:
break
# Update the base offset to point to the next attribute
attr_base_offset += attr.Attr_Header.Length
# Get the next attribute
attr: MFTAttribute = self._context.object(
attribute_object_type_name,
offset=self.vol.offset + attr_base_offset,
layer_name=self.vol.layer_name,
)
class MFTFileName(objects.StructType):
"""This represents an MFT $FILE_NAME Attribute"""