From 1c6cd0fb528b02e8f35ac65f1173241ff84dfe26 Mon Sep 17 00:00:00 2001 From: KevTheHermit Date: Sat, 15 Jan 2022 15:53:35 +0000 Subject: [PATCH] Move mftscan enums to ISF file. --- .../framework/plugins/windows/mftscan.py | 33 +++++--- .../symbols/windows/extensions/mft.py | 77 ------------------- .../framework/symbols/windows/mft.json | 70 ++++++++++++++++- 3 files changed, 93 insertions(+), 87 deletions(-) diff --git a/volatility3/framework/plugins/windows/mftscan.py b/volatility3/framework/plugins/windows/mftscan.py index 616c0d738..991191d5b 100644 --- a/volatility3/framework/plugins/windows/mftscan.py +++ b/volatility3/framework/plugins/windows/mftscan.py @@ -11,7 +11,6 @@ from volatility3.framework import constants, renderers, interfaces from volatility3.framework.configuration import requirements from volatility3.framework import exceptions from volatility3.framework.renderers import conversion, format_hints -from volatility3.framework.symbols.windows.extensions.mft import AttributeTypes, NameSpace, PermissionFlags, MFTFlags from volatility3.framework.symbols.windows.mft import MFTIntermedSymbols from volatility3.plugins import timeliner, yarascan @@ -53,6 +52,12 @@ class MFTScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface): header_object = symbol_table + constants.BANG + "ATTR_HEADER" si_object = symbol_table + constants.BANG + "STANDARD_INFORMATION_ENTRY" fn_object = symbol_table + constants.BANG + "FILE_NAME_ENTRY" + + # Get the Enums + attr_types = self.context.symbol_space.get_enumeration(symbol_table + constants.BANG + "AttrTypeEnum") + namespave_enum = self.context.symbol_space.get_enumeration(symbol_table + constants.BANG + "NameSpaceEnum") + mft_flags = self.context.symbol_space.get_enumeration(symbol_table + constants.BANG + "MFTFlagsEnum") + permission_flags = self.context.symbol_space.get_enumeration(symbol_table + constants.BANG + "PermissionFlagEnum") # Scan the layer for Raw MFT records and parse the fields for offset, rule_name, name, value in layer.scan(context = self.context, scanner = yarascan.YaraScanner(rules = rules)): @@ -70,14 +75,20 @@ class MFTScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface): vollog.debug(f"Attr Type: {attr_header.AttrType}") # If this is not a valid type then exit the loop - if not AttributeTypes(attr_header.AttrType).value: + if attr_header.AttrType not in attr_types.choices.values(): break # Offset past the headers to the attribute data attr_data_offset = offset+attr_base_offset+24 + + # MFT Flags determine the file type or dir + if mft_record.Flags in mft_flags.choices.values(): + mft_flag = mft_flags.lookup(mft_record.Flags) + else: + mft_flag = hex(mft_record.Flags) # Standard Information Attribute - if attr_header.AttrType == 0x10: + if attr_header.AttrType == attr_types.choices.get('STANDARD_INFORMATION'): attr_data = self.context.object(si_object, offset=attr_data_offset, layer_name=layer.name) yield 0, ( @@ -85,9 +96,9 @@ class MFTScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface): mft_record.get_signature(), mft_record.RecordNumber, mft_record.LinkCount, - MFTFlags(mft_record.Flags).name, + mft_flag, renderers.NotApplicableValue(), - AttributeTypes(attr_header.AttrType).name, + attr_types.lookup(attr_header.AttrType), conversion.wintime_to_datetime(attr_data.CreationTime), conversion.wintime_to_datetime(attr_data.ModifiedTime), conversion.wintime_to_datetime(attr_data.UpdatedTime), @@ -96,18 +107,22 @@ class MFTScan(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface): ) # File Name Attribute - if attr_header.AttrType == 0x30: + if attr_header.AttrType == attr_types.choices.get('FILE_NAME'): attr_data = self.context.object(fn_object, offset=attr_data_offset, layer_name=layer.name) file_name = attr_data.get_full_name() + if attr_data.Flags in permission_flags.choices.values(): + permissions = permission_flags.lookup(attr_data.Flags) + else: + permissions = hex(attr_data.Flags) yield 1, ( format_hints.Hex(attr_data_offset), mft_record.get_signature(), mft_record.RecordNumber, mft_record.LinkCount, - MFTFlags(mft_record.Flags).name, - PermissionFlags(attr_data.Flags).name, - AttributeTypes(attr_header.AttrType).name, + mft_flag, + permissions, + attr_types.lookup(attr_header.AttrType), conversion.wintime_to_datetime(attr_data.CreationTime), conversion.wintime_to_datetime(attr_data.ModifiedTime), conversion.wintime_to_datetime(attr_data.UpdatedTime), diff --git a/volatility3/framework/symbols/windows/extensions/mft.py b/volatility3/framework/symbols/windows/extensions/mft.py index 09f6346cc..0713c969a 100644 --- a/volatility3/framework/symbols/windows/extensions/mft.py +++ b/volatility3/framework/symbols/windows/extensions/mft.py @@ -8,80 +8,6 @@ from volatility3.framework import exceptions, objects, renderers from volatility3.framework.objects import utility -class AttributeTypes(enum.Enum): - STANDARD_INFORMATION = 0x10 - ATTRIBUTE_LIST = 0x20 - FILE_NAME = 0x30 - OBJECT_ID = 0x40 - SECURITY_DESCRIPTOR = 0x50 - VOLUME_NAME = 0x60 - VOLUME_INFORMATION = 0x70 - DATA = 0x80 - INDEX_ROOT = 0x90 - INDEX_ALLOCATION = 0xa0 - BITMAP = 0xb0 - REPARSE_POINT = 0xc0 - EA_INFORMATION = 0xd0 - EA = 0xe0 - PROPERTY_SET = 0xf0 - LOGGED_UTILITY_STREAM = 0x100 - Unknown = None - - @classmethod - def _missing_(cls, value): - return cls(AttributeTypes.Unknown) - -class NameSpace(enum.Enum): - POSIX = 0x0 - Win32 = 0x1 - DOS = 0x2 - Win32DOS = 0x3 - Unknown = None - - @classmethod - def _missing_(cls, value): - return cls(NameSpace.Unknown) - - -class MFTFlags(enum.Enum): - Removed = 0x00 - File = 0x1 - Directory = 0x2 - DirInUse = 0x3 - Unknown = None - - @classmethod - def _missing_(cls, value): - return cls(MFTFlags.Unknown) - - -class PermissionFlags(enum.Enum): - ReadOnly = 0x1 - Hidden = 0x2 - System = 0x4 - Archive = 0x20 - ArchiveHidden = 0x22 - ArchiveSystem = 0x24 - ArchiveHiddenSystem = 0x26 - Device = 0x40 - Normal = 0x80 - Temporary = 0x100 - TempArchive = 0x120 - SparseFile = 0x200 - ReparsePoint = 0x400 - Compressed = 0x800 - Offline = 0x1000 - NotIndexed = 0x2000 - Encrypted = 0x4000 - Directory = 0x10000000 - IndexView = 0x20000000 - unknown = None - - @classmethod - def _missing_(cls, value): - return cls(PermissionFlags.unknown) - - class MFTEntry(objects.StructType): """This represents the base MFT Record""" @@ -99,6 +25,3 @@ class MFTFileName(objects.StructType): max_length = self.NameLength*2, errors = "replace") return output - - def get_file_namespace(self) -> str: - pass diff --git a/volatility3/framework/symbols/windows/mft.json b/volatility3/framework/symbols/windows/mft.json index e045ed0fc..a99b82e9e 100644 --- a/volatility3/framework/symbols/windows/mft.json +++ b/volatility3/framework/symbols/windows/mft.json @@ -53,7 +53,75 @@ } }, "symbols": {}, - "enums": {}, + "enums": { + "AttrTypeEnum": { + "base": "unsigned char", + "constants": { + "STANDARD_INFORMATION": 16, + "ATTRIBUTE_LIST": 32, + "FILE_NAME": 48, + "OBJECT_ID": 64, + "SECURITY_DESCRIPTOR": 80, + "VOLUME_NAME": 96, + "VOLUME_INFORMATION": 112, + "DATA": 128, + "INDEX_ROOT": 114, + "INDEX_ALLOCATION": 160, + "BITMAP": 176, + "REPARSE_POINT": 192, + "EA_INFORMATION": 208, + "EA": 224, + "PROPERTY_SET": 240, + "LOGGED_UTILITY_STREAM": 256 + }, + "size": 1 + }, + "NameSpaceEnum": { + "base":"unsigned char", + "constants": { + "POSIX": 0, + "Win32": 1, + "DOS": 2, + "Win32 DOS": 3 + }, + "size": 1 + }, + "MFTFlagsEnum": { + "base":"unsigned char", + "constants": { + "Removed": 0, + "File": 1, + "Directory": 2, + "DirInUse": 3 + }, + "size": 1 + }, + "PermissionFlagEnum": { + "base":"unsigned char", + "constants": { + "ReadOnly": 1, + "Hidden": 2, + "System": 4, + "Archive": 32, + "ArchiveHidden": 34, + "ArchiveSystem": 36, + "ArchiveHiddenSystem": 38, + "Device": 60, + "Normal": 128, + "Temporary": 256, + "TempArchive": 288, + "SparseFile": 512, + "ReparsePoint": 1024, + "Compressed": 2048, + "Offline": 4096, + "NotIndexed": 8192, + "Encrypted": 16384, + "Directory": 268435456, + "IndexView": 536870912 + }, + "size": 1 + } + }, "user_types": { "MFT_ENTRY": { "fields": {