protected NtfsFileEntry(Ntfs ntfs, FileRecord record, AttributeFileName fileName) { this.ntfs = ntfs; MFTRecord = record; FileName = fileName; Init(); }
internal NtfsDirectory(NTFSWrapper ntfsWrapper, FileRecord record, AttributeFileName fileName) : base(ntfsWrapper, record, fileName) { Debug.Assert(record.Flags.HasFlag(FileEntryFlags.Directory)); PrepRecord(); }
protected NtfsFileEntry(NTFSWrapper ntfsWrapper, FileRecord record, AttributeFileName fileName) { NTFSWrapper = ntfsWrapper; MFTRecord = record; FileName = fileName; Init(); }
public static AttributeFileName GetPreferredDisplayName(FileRecord record) { AttributeFileName posix = null; AttributeFileName win32 = null; AttributeFileName dos = null; AttributeFileName win32AndDos = null; foreach (var a in record.Attributes) { if (a is AttributeFileName fileName) { switch (fileName.FilenameNamespace) { case FileNamespace.POSIX: posix = fileName; break; case FileNamespace.DOS: dos = fileName; break; case FileNamespace.Win32: win32 = fileName; break; case FileNamespace.Win32AndDOS: win32AndDos = fileName; break; } } } if (win32 != null) { return(win32); } if (win32AndDos != null) { return(win32AndDos); } if (posix != null) { return(posix); } if (dos != null) { return(dos); } throw new Exception("ntfs: invalid filename attribute"); }
internal static NtfsFileEntry CreateEntry(Ntfs ntfs, uint fileId, AttributeFileName fileName = null) { var record = ntfs.ReadMftRecord(fileId); if (fileName == null) { fileName = NtfsUtils.GetPreferredDisplayName(record); } if ((record.Flags & FileEntryFlags.Directory) != 0) { return(new NtfsDirectory(ntfs, record, fileName)); } return(new NtfsFile(ntfs, record, fileName)); }
public string BuildFileName(FileRecord record, string rootName = null) { // Get filename (and prefer the non-8dot3 variant) AttributeFileName fileName = NtfsUtils.GetPreferredDisplayName(record); if (fileName == null) { throw new NullReferenceException("Record has no FileName attribute"); } string path = fileName.FileName; if (record.Flags.HasFlag(FileEntryFlags.Directory)) { path += '\\'; } // Continue till we hit SpecialMFTFiles.RootDir FileRecord parentRecord; do { // Get parent parentRecord = ReadMFTRecord(fileName.ParentDirectory.FileId); if (parentRecord == null) { throw new NullReferenceException("A parent record was null"); } fileName = NtfsUtils.GetPreferredDisplayName(parentRecord); if (fileName == null) { throw new NullReferenceException("A parent record had no Filename attribute"); } if (parentRecord.FileReference.FileId == (uint)SpecialMFTFiles.RootDir) { path = rootName + '\\' + path; break; } path = fileName.FileName + '\\' + path; }while (true); return(path); }
internal NtfsDirectory(Ntfs ntfs, FileRecord record, AttributeFileName fileName) : base(ntfs, record, fileName) { }
private static void PrettyPrintAttribute(NTFSParser parser, Options options, FileRecord record, Attribute attrib, int indentCount) { string indent = ""; for (int i = 0; i < indentCount; i++) { indent += SingleIndent; } AwesomeConsole.Write(indent + attrib.Id + ": "); PrintType(attrib.Type); AwesomeConsole.Write(" "); PrintName(attrib.AttributeName, true, true); if (attrib.NonResidentFlag == ResidentFlag.NonResident) { AwesomeConsole.Write(" (NonResident)", ConsoleColor.Red); } AwesomeConsole.WriteLine(); indent += SingleIndent; switch (attrib.Type) { case AttributeType.STANDARD_INFORMATION: AttributeStandardInformation standardInformation = (AttributeStandardInformation)attrib; AwesomeConsole.WriteLine(indent + "Creation Time: " + standardInformation.TimeCreated + " " + standardInformation.TimeCreated.Kind); AwesomeConsole.WriteLine(indent + "Modified Time: " + standardInformation.TimeModified + " " + standardInformation.TimeModified.Kind); AwesomeConsole.WriteLine(indent + "Accessed Time: " + standardInformation.TimeAccessed + " " + standardInformation.TimeAccessed.Kind); AwesomeConsole.WriteLine(indent + "Mft Modified : " + standardInformation.TimeMftModified + " " + standardInformation.TimeMftModified.Kind); break; case AttributeType.ATTRIBUTE_LIST: AttributeList list = (AttributeList)attrib; foreach (AttributeListItem listItem in list.Items) { AwesomeConsole.Write(indent + listItem.AttributeId + ": "); PrintType(listItem.Type); AwesomeConsole.Write(" "); PrintName(listItem.Name, true, true); AwesomeConsole.Write(" "); if (record.FileReference == listItem.BaseFile) { AwesomeConsole.Write("(this record)", ConsoleColor.DarkGray); } else { PrintReference(listItem.BaseFile); } AwesomeConsole.WriteLine(); } break; case AttributeType.FILE_NAME: AttributeFileName fileName = (AttributeFileName)attrib; using (AwesomeConsole.BeginSequentialWrite()) { AwesomeConsole.Write(indent + "Parent dir: "); AwesomeConsole.WriteLine(fileName.ParentDirectory, ConsoleColor.Cyan); } AwesomeConsole.WriteLine(indent + "Namespace: " + fileName.FilenameNamespace); AwesomeConsole.Write(indent + "Flags: "); PrintEnums(fileName.FileFlags); AwesomeConsole.WriteLine(); AwesomeConsole.Write(indent + "Name: "); PrintName(fileName.FileName, false, true); AwesomeConsole.WriteLine(); AwesomeConsole.WriteLine(indent + "C Time: " + fileName.CTime + " " + fileName.CTime.Kind); AwesomeConsole.WriteLine(indent + "M Time: " + fileName.MTime + " " + fileName.MTime.Kind); AwesomeConsole.WriteLine(indent + "A Time: " + fileName.ATime + " " + fileName.ATime.Kind); AwesomeConsole.WriteLine(indent + "R Time: " + fileName.RTime + " " + fileName.RTime.Kind); break; case AttributeType.DATA: AttributeData data = (AttributeData)attrib; if (data.NonResidentFlag == ResidentFlag.Resident) { AwesomeConsole.WriteLine(indent + "Data length: {0:N0} Bytes", data.ResidentHeader.ContentLength); } else { AwesomeConsole.WriteLine(indent + "Data length: {0:N0} Bytes", data.NonResidentHeader.ContentSize); AwesomeConsole.Write(indent + "VCN: "); PrintRange(parser, options, data.NonResidentHeader.StartingVCN, data.NonResidentHeader.EndingVCN - data.NonResidentHeader.StartingVCN); AwesomeConsole.WriteLine(); AwesomeConsole.WriteLine(indent + "Fragments: {0:N0}", data.NonResidentHeader.Fragments.Length); AwesomeConsole.WriteLine(indent + SingleIndent + "LCN-range, cluster count, VCN-range", ConsoleColor.DarkGray); foreach (DataFragment fragment in data.NonResidentHeader.Fragments) { AwesomeConsole.Write(indent + SingleIndent); PrintRange(parser, options, fragment.LCN, fragment.Clusters); AwesomeConsole.Write(SingleIndent); PrintSize(parser, options, fragment.Clusters); AwesomeConsole.Write(SingleIndent); PrintRange(parser, options, fragment.StartingVCN, fragment.Clusters); if (fragment.IsCompressed) { AwesomeConsole.Write(" (Compressed)"); } if (fragment.IsSparseFragment) { AwesomeConsole.Write(" (Sparse)"); } AwesomeConsole.WriteLine(); } } break; case AttributeType.OBJECT_ID: AttributeObjectId objectId = (AttributeObjectId)attrib; AwesomeConsole.Write(indent + "ObjectId : "); PrintGUID(objectId.ObjectId); AwesomeConsole.WriteLine(); AwesomeConsole.Write(indent + "BithVolumeId: "); PrintGUID(objectId.BithVolumeId); AwesomeConsole.WriteLine(); AwesomeConsole.Write(indent + "BithObjectId: "); PrintGUID(objectId.BithObjectId); AwesomeConsole.WriteLine(); AwesomeConsole.Write(indent + "DomainId : "); PrintGUID(objectId.DomainId); AwesomeConsole.WriteLine(); break; case AttributeType.SECURITY_DESCRIPTOR: AttributeSecurityDescriptor securityDescriptor = (AttributeSecurityDescriptor)attrib; AwesomeConsole.Write(indent + "SID: "); PrintSID(securityDescriptor.UserSID); AwesomeConsole.WriteLine(); AwesomeConsole.Write(indent + "GID: "); PrintSID(securityDescriptor.GroupSID); AwesomeConsole.WriteLine(); AwesomeConsole.Write(indent + "Flags: "); PrintEnums(securityDescriptor.ControlFlags); AwesomeConsole.WriteLine(); AwesomeConsole.WriteLine(); AwesomeConsole.WriteLine(indent + "SACL: " + (securityDescriptor.SACL == null ? 0 : securityDescriptor.SACL.ACECount)); if (securityDescriptor.SACL == null) { AwesomeConsole.WriteLine(indent + SingleIndent + "Not present", ConsoleColor.Red); } else { foreach (ACE ace in securityDescriptor.SACL.ACEs) { PrintACE(indent, ace); } } AwesomeConsole.WriteLine(indent + "DACL: " + (securityDescriptor.DACL == null ? 0 : securityDescriptor.DACL.ACECount)); if (securityDescriptor.DACL == null) { AwesomeConsole.WriteLine(indent + SingleIndent + "Not present", ConsoleColor.Red); } else { foreach (ACE ace in securityDescriptor.DACL.ACEs) { PrintACE(indent, ace); } } break; case AttributeType.VOLUME_NAME: AttributeVolumeName volumeName = (AttributeVolumeName)attrib; AwesomeConsole.Write(indent + "Name: "); PrintName(volumeName.VolumeName); AwesomeConsole.WriteLine(); break; case AttributeType.VOLUME_INFORMATION: AttributeVolumeInformation volumeInformation = (AttributeVolumeInformation)attrib; AwesomeConsole.WriteLine(indent + "Reserved: " + volumeInformation.Reserved); AwesomeConsole.WriteLine(indent + "MajorVersion: " + volumeInformation.MajorVersion + "." + volumeInformation.MinorVersion); AwesomeConsole.Write(indent + "VolumeInformationFlag: "); PrintEnums(volumeInformation.VolumeInformationFlag); AwesomeConsole.WriteLine(); break; case AttributeType.INDEX_ROOT: AttributeIndexRoot indexRoot = (AttributeIndexRoot)attrib; AwesomeConsole.WriteLine(indent + "IndexType: " + indexRoot.IndexType); AwesomeConsole.WriteLine(indent + "CollationRule: " + indexRoot.CollationRule); AwesomeConsole.WriteLine(indent + "IndexAllocationSize: " + indexRoot.IndexAllocationSize); AwesomeConsole.WriteLine(indent + "ClustersPrIndexRecord: " + indexRoot.ClustersPrIndexRecord); AwesomeConsole.WriteLine(); AwesomeConsole.WriteLine(indent + "SizeOfIndexTotal: " + indexRoot.SizeOfIndexTotal); AwesomeConsole.WriteLine(indent + "IndexFlags: " + indexRoot.IndexFlags); AwesomeConsole.WriteLine(indent + "Entries: " + indexRoot.Entries.Length); foreach (IndexEntry entry in indexRoot.Entries) { AwesomeConsole.Write(indent + SingleIndent); PrintReference(entry.FileRefence); if (entry.ChildFileName != null) { AwesomeConsole.Write(" "); PrintName(entry.ChildFileName.FileName, true); AwesomeConsole.Write(" "); PrintEnums(entry.ChildFileName.FileFlags); } AwesomeConsole.WriteLine(); } break; case AttributeType.INDEX_ALLOCATION: AttributeIndexAllocation indexAllocation = (AttributeIndexAllocation)attrib; AwesomeConsole.WriteLine(indent + "Chunks: " + indexAllocation.Indexes.Length); for (int i = 0; i < indexAllocation.Indexes.Length; i++) { IndexAllocationChunk chunk = indexAllocation.Indexes[i]; AwesomeConsole.WriteLine(indent + SingleIndent + string.Format("{0:N0}: {1:N0} of {2:N0} Bytes used", i, chunk.SizeOfIndexTotal, chunk.SizeOfIndexAllocated)); } AwesomeConsole.WriteLine(indent + "Entries: " + indexAllocation.Entries.Length); foreach (IndexEntry entry in indexAllocation.Entries) { AwesomeConsole.Write(indent + SingleIndent); PrintReference(entry.FileRefence); if (entry.ChildFileName != null) { AwesomeConsole.Write(" "); PrintName(entry.ChildFileName.FileName, true); AwesomeConsole.Write(" "); PrintEnums(entry.ChildFileName.FileFlags); } AwesomeConsole.WriteLine(); } break; case AttributeType.BITMAP: AttributeBitmap bitmap = (AttributeBitmap)attrib; AwesomeConsole.WriteLine(indent + "Bitfield Size: {0:N0} ({1:N0} bytes)", bitmap.Bitfield.Length, bitmap.Bitfield.Length / 8); // Print out 4 lines of 64 bits const int bitsPrLine = 64; for (int line = 0; line < 4; line++) { if (bitmap.Bitfield.Length <= line * bitsPrLine) { break; } AwesomeConsole.Write(indent + "{0,-6}", (line * bitsPrLine) + ":"); for (int offset = line * bitsPrLine; offset < line * bitsPrLine + bitsPrLine; offset += 8) { if (bitmap.Bitfield.Length <= offset) { break; } for (int j = offset; j < offset + 8; j++) { if (bitmap.Bitfield.Length <= j) { break; } AwesomeConsole.Write(bitmap.Bitfield[j] ? "1" : "0"); } AwesomeConsole.Write(" "); } AwesomeConsole.WriteLine(); } if (bitmap.Bitfield.Length > 256) { PrintError(indent + "Bitfield was longer than 256 bits, so the rest wasn't printed."); AwesomeConsole.WriteLine(); } break; case AttributeType.LOGGED_UTILITY_STREAM: AttributeLoggedUtilityStream loggedUtilityStream = (AttributeLoggedUtilityStream)attrib; AwesomeConsole.WriteLine(indent + "Data: {0:N0} Bytes", loggedUtilityStream.Data.Length); break; default: if (Debugger.IsAttached) { Debugger.Break(); } PrintError(attrib.Type + " not supported"); break; } }
static void Main(string[] args) { const char driveLetter = 'E'; RawDisk disk = new RawDisk(driveLetter); using (Stream stream = disk.CreateDiskStream()) using (Stream streama = disk.CreateDiskStream()) { NTFSParser parser = new NTFSParser(stream); NTFSParser parsera = new NTFSParser(streama); int longest = 0; foreach (FileRecord record in parser.GetRecords(true)) { int count = record.Attributes.Count; if (count > longest) { longest = count; Console.WriteLine(record.FileReference + " - " + count); } } } NTFSDiskProvider provider = new NTFSDiskProvider(disk); NTFSWrapper ntfsWrapper = new NTFSWrapper(provider, 524288); ntfsWrapper.InitializeCommon(); Console.WriteLine("Read NTFS. Version: " + ntfsWrapper.NTFSVersion); // Filerecord bitmap ntfsWrapper.ParseNonResidentAttribute(ntfsWrapper.FileMFT.Attributes.OfType <AttributeBitmap>().Single()); BitArray bitmapData = ntfsWrapper.FileMFT.Attributes.OfType <AttributeBitmap>().Single().Bitfield; HashSet <AttributeType> types = new HashSet <AttributeType>(); // Read fragmented file for (uint i = 0; i < ntfsWrapper.FileRecordCount; i++) { if (!ntfsWrapper.InRawDiskCache(i)) { ntfsWrapper.PrepRawDiskCache(i); } if (!bitmapData[(int)i]) { continue; } FileRecord record = ntfsWrapper.ReadMFTRecord(i); if (record.Flags.HasFlag(FileEntryFlags.FileInUse)) { ntfsWrapper.ParseNonResidentAttributes(record); } Console.Write("Read {0:N0} of {1:N0} - ({2:N0} bytes {3:N0} allocated)", i, ntfsWrapper.FileRecordCount, record.SizeOfFileRecord, record.SizeOfFileRecordAllocated); if (record.Flags.HasFlag(FileEntryFlags.FileInUse)) { Console.ForegroundColor = ConsoleColor.Magenta; Console.Write(" (InUse)"); Console.ForegroundColor = ConsoleColor.Gray; } else { Console.ForegroundColor = ConsoleColor.DarkMagenta; Console.Write(" (Not InUse)"); Console.ForegroundColor = ConsoleColor.Gray; } if (bitmapData[(int)i]) { Console.ForegroundColor = ConsoleColor.Magenta; Console.Write(" (Bitmap:InUse)"); Console.ForegroundColor = ConsoleColor.Gray; } else { Console.ForegroundColor = ConsoleColor.DarkMagenta; Console.Write(" (Bitmap:Not InUse)"); Console.ForegroundColor = ConsoleColor.Gray; } if (record.Flags.HasFlag(FileEntryFlags.Directory)) { Console.ForegroundColor = ConsoleColor.Yellow; Console.Write(" (dir)"); Console.ForegroundColor = ConsoleColor.Gray; } if (record.BaseFile.FileId != 0) { Console.ForegroundColor = ConsoleColor.Yellow; Console.Write(" (base: {0})", record.BaseFile); Console.ForegroundColor = ConsoleColor.Gray; } if (Enum.IsDefined(typeof(SpecialMFTFiles), record.FileReference.FileId)) { Console.ForegroundColor = ConsoleColor.Green; Console.Write(" ({0})", (SpecialMFTFiles)record.FileReference.FileId); Console.ForegroundColor = ConsoleColor.Gray; } Console.WriteLine(); foreach (Attribute attribute in record.Attributes.Concat(record.ExternalAttributes).OrderBy(s => s.Id)) { bool wasNew = types.Add(attribute.Type); if (wasNew) { File.AppendAllLines("out.txt", new[] { record.FileReference + ": " + attribute.Type }); Debugger.Break(); } string name = string.IsNullOrWhiteSpace(attribute.AttributeName) ? string.Empty : " '" + attribute.AttributeName + "'"; Console.Write(" " + attribute.Id + " (" + attribute.Type); if (name != string.Empty) { Console.ForegroundColor = ConsoleColor.Green; Console.Write(name); Console.ForegroundColor = ConsoleColor.Gray; } Console.Write(")"); AttributeFileName attributeFileName = attribute as AttributeFileName; if (attributeFileName != null) { Console.ForegroundColor = ConsoleColor.Red; Console.Write(" '{0}'", attributeFileName.FileName); Console.ForegroundColor = ConsoleColor.Gray; } AttributeData attributeData = attribute as AttributeData; if (attributeData != null) { Console.ForegroundColor = ConsoleColor.Red; Console.Write(" {0}", attributeData.NonResidentFlag); Console.ForegroundColor = ConsoleColor.Green; Console.Write(" ({0:N0} bytes)", attributeData.NonResidentFlag == ResidentFlag.NonResident ? attributeData.NonResidentHeader.ContentSize : (ulong)attributeData.DataBytes.Length); if (attributeData.NonResidentFlag == ResidentFlag.Resident) { Console.ForegroundColor = ConsoleColor.Red; Console.Write(" ('{0}')", Encoding.ASCII.GetString(attributeData.DataBytes, 0, Math.Min(attributeData.DataBytes.Length, 30))); } else { Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine(); foreach (DataFragment fragment in attributeData.DataFragments) { Console.Write(" LCN: {0:N0} ({1:N0} clusters) ", fragment.LCN, fragment.Clusters); if (fragment.IsCompressed) { Console.ForegroundColor = ConsoleColor.Blue; Console.Write(" (Compressed)"); Console.ForegroundColor = ConsoleColor.Cyan; } if (fragment.IsSparseFragment) { Console.ForegroundColor = ConsoleColor.Blue; Console.Write(" (Sparse)"); Console.ForegroundColor = ConsoleColor.Cyan; } Console.WriteLine(); } } Console.ForegroundColor = ConsoleColor.Gray; } Console.WriteLine(); } Console.WriteLine(); } Console.WriteLine("Done."); Console.ReadLine(); }
internal NtfsFileEntry CreateEntry(uint fileId, AttributeFileName fileName = null) { return(CreateEntry(ntfs, fileId, fileName)); }
internal static NtfsFileEntry CreateEntry(NTFSWrapper ntfsWrapper, uint fileId, AttributeFileName fileName = null) { if (fileName == null) { // Dig up a preferred name FileRecord tmpRecord = ntfsWrapper.ReadMFTRecord(fileId); fileName = NtfsUtils.GetPreferredDisplayName(tmpRecord); } NtfsFileEntry entry = ntfsWrapper.FileCache.Get(fileId, fileName.FileName.GetHashCode()); if (entry != null) { Debug.WriteLine("Got from cache: " + fileId + ":" + fileName.Id); return(entry); } // Create it FileRecord record = ntfsWrapper.ReadMFTRecord(fileId); if (record.Flags.HasFlag(FileEntryFlags.Directory)) { entry = new NtfsDirectory(ntfsWrapper, record, fileName); } else { entry = new NtfsFile(ntfsWrapper, record, fileName); } ntfsWrapper.FileCache.Set(fileId, fileName.Id, entry); return(entry); }