//------------------------------------------------ //--- 010 Editor v8.0.1 Binary Template // // File: MFT.bt // Authors: Eric R. Zimmerman // Version: 0.1 // Purpose: Parse a file containing NTFS MFT FILE records. // Category: Drives // File Mask: *MFT* // ID Bytes: 46 49 4C 45 //FILE // History: // 0.1 2018-06-30 Eric R. Zimmerman: Initial release //------------------------------------------------ LittleEndian(); typedef enum { Free = 0, InUse = 1 } HeaderFlags; typedef enum { IsResident = 0, NonResident = 1 } ResidentFlag; typedef enum { Posix = 0x0, Windows = 0x1, Dos = 0x2, DosWindows = 0x3 } FileNameType; typedef enum { ReadOnly = 0x01, Hidden = 0x02, System = 0x04, VolumeLabel = 0x08, Directory = 0x010, Archive = 0x020, Device = 0x040, Normal = 0x080, Temporary = 0x0100, SparseFile = 0x0200, ReparsePoint_ = 0x0400, Compressed = 0x0800, Offline = 0x01000, NotContentIndexed = 0x02000, Encrypted = 0x04000, IntegrityStream = 0x08000, Virtual = 0x010000, NoScrubData = 0x020000, HasEa = 0x040000, IsDirectory = 0x10000000, IsIndexView = 0x20000000 } AttributeFlag; typedef enum { EndOfAttributes = -0x1, Unused = 0x0, StandardInformation = 0x10, AttributeList = 0x20, FileName = 0x30, VolumeVersionObjectId = 0x40, SecurityDescriptor = 0x50, VolumeName = 0x60, VolumeInformation = 0x70, Data = 0x80, IndexRoot = 0x90, IndexAllocation = 0xa0, Bitmap = 0xb0, ReparsePoint = 0xc0, EaInformation = 0xd0, Ea = 0xe0, PropertySet = 0xf0, LoggedUtilityStream = 0x100, UserDefinedAttribute = 0x1000 } AttribType; typedef struct (int recordSize) { local int startPosition = FTell(); AttribType AttributeType ; int RecordSize ; FSeek(startPosition); FSkip(recordSize); } Attribute; typedef struct (int recordSize) { AttribType AttributeType ; } END_OF_ATTRIBUTES; typedef struct (int recordSize) { local int startPosition = FTell(); AttribType AttributeType ; int RecordSize ; FSeek(startPosition); FSkip(recordSize); } SECURITY_DESCRIPTOR; typedef struct (int recordSize) { AttribType AttributeType ; int RecordSize ; ResidentFlag Resident ; byte NameSize ; short NameOffset ; short Unknown; short AttributeId ; int ContentLength ; short ContentOffset ; short Padding; FILETIME CreationTime ; FILETIME ContentModifiedTime ; FILETIME MetadataModifiedTime ; FILETIME LastAccessedTime ; AttributeFlag Flags ; //TODO make this look right with the actual flags int MaxVersions ; int VersionNumber ; int ClassId ; int OwnerId ; int SecurityId ; uint64 QuoataCharged ; uint64 UpdateSequenceNumber ; } STANDARD_INFO; typedef struct (int recordSize) { local int startPosition = FTell(); AttribType AttributeType ; int RecordSize ; ResidentFlag Resident; byte NameSize; short NameOffset; short Unknown; short AttributeId; int ContentLength; short ContentOffset; short Padding; uint64 ParentMFTReference; FILETIME CreationTime ; FILETIME ContentModifiedTime ; FILETIME MetadataModifiedTime ; FILETIME LastAccessedTime ; uint64 PhysicalSize; uint64 LogicalSize; AttributeFlag Flags; //TODO make this look right with the actual flags int ExtendedAttributeSize; byte NameLength; FileNameType NameType; wchar_t Filename [NameLength]; FSeek(startPosition); FSkip(recordSize); } FILE_NAME; typedef struct (int recordSize) { local int startPosition = FTell(); AttribType AttributeType ; int RecordSize ; FSeek(startPosition); FSkip(recordSize); } BITMAP; typedef struct (int recordSize) { local int startPosition = FTell(); AttribType AttributeType ; int RecordSize ; ResidentFlag Resident; byte NameSize; short NameOffset; short Unknown; short AttributeId; if (Resident == NonResident) { uint64 StartingVirtualClusterNumber; uint64 EndingVirtualClusterNumber; short OffsetToDataRuns; FSkip(6); uint64 AllocatedSize; uint64 TrueSize; uint64 InitializedSize; if (NameSize > 0) { local wstring Name = ReadWString(startPosition + NameOffset,NameSize);// [NameSize]; //wstring ReadWString( int64 pos, int maxLen=-1 ) } //data runs here TODO // local byte dataRunInfo = ReadByte(); // while (dataRunInfo != 0) // { // dataRunInfo = ReadByte(); // } } else { int ContentLength; short ContentOffset; short Padding; if (NameSize > 0) { wchar_t Name [NameSize]; byte PaddingName[ContentOffset - NameSize]; } byte Content[ContentLength]; } //temp for now FSeek(startPosition); FSkip(recordSize); } DATA; typedef struct { char Signature[4] ; short OFfsetToFixupArray ; short NumberOfFixupBytePairs ; uint64 LogfileSequenceNumber ; short SequenceNumber ; short HardLinkCount ; short OffsetToFirstAttribute ; HeaderFlags Flags ; uint ActualRecordSize ; uint AllocatedRecordSize ; uint64 FileReferenceToBaseRecord ; short NextAvailableAttributeId ; short Unknown; uint EntryNumber ; short FixupExpected ; local int i; local int expectedPairs = NumberOfFixupBytePairs - 1; for( i = 0; i < expectedPairs; i++ ) { ushort FixUpActual ; } short Padding; //start attributes local AttribType attribType = ReadInt(FTell()); local int attributeSize = ReadInt(FTell()+4); local int EndFound = 0; while( EndFound !=1) { if (attribType == SecurityDescriptor) { break; } switch( attribType ) { case StandardInformation : STANDARD_INFO StandardInfo (attributeSize); break; case FileName : FILE_NAME FileName (attributeSize); break; case Data: DATA Data (attributeSize); break; case Bitmap: BITMAP Bitmap (attributeSize); break; case SecurityDescriptor: SECURITY_DESCRIPTOR SecDesc (attributeSize); break; case EndOfAttributes: END_OF_ATTRIBUTES EndOfAttributes(4); EndFound=1; break; default : Printf( "unknown attr at FTell = %d\n", FTell() ); Attribute attr(attributeSize); break; } if (EndFound == 1) { break; } attribType = ReadInt(FTell()); attributeSize = ReadInt(FTell() + 4); } byte Slack[AllocatedRecordSize - ActualRecordSize + 4]; } FileEntry ; while (!FEof()) { FileEntry entry ; }