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; } }
private static void PrintFull(NTFSParser parser, Options options, uint mftnumber) { HashSet <FileReference> otherRecords = new HashSet <FileReference>(); parser.CurrentMftRecordNumber = mftnumber; FileRecord record = parser.ParseNextRecord(); using (AwesomeConsole.BeginSequentialWrite()) { AwesomeConsole.Write("Record Id: "); PrintReference(record.FileReference); AwesomeConsole.Write(" Attributes: "); AwesomeConsole.Write(record.Attributes.Count.ToString("N0")); if (record.Flags.HasFlag(FileEntryFlags.FileInUse)) { AwesomeConsole.Write(" (InUse)", ConsoleColor.Magenta); } else { AwesomeConsole.Write(" (Not InUse)", ConsoleColor.Red); } if (record.Flags.HasFlag(FileEntryFlags.Directory)) { AwesomeConsole.Write(" (Directory)", ConsoleColor.Yellow); } if (Enum.IsDefined(typeof(SpecialMFTFiles), record.MFTNumber)) { AwesomeConsole.Write(" (Special MFT Record: " + (SpecialMFTFiles)record.MFTNumber + ")", ConsoleColor.White); } } if (record.BaseFile.FileId != 0) { AwesomeConsole.Write(" (BaseFile: ", ConsoleColor.Cyan); PrintReference(record.BaseFile); AwesomeConsole.Write(")", ConsoleColor.Cyan); } AwesomeConsole.WriteLine(); foreach (Attribute attribute in record.Attributes) { if (attribute.NonResidentFlag == ResidentFlag.NonResident && (attribute.Type == AttributeType.ATTRIBUTE_LIST || attribute.Type == AttributeType.INDEX_ALLOCATION || attribute.Type == AttributeType.SECURITY_DESCRIPTOR || attribute.Type == AttributeType.BITMAP)) { parser.ParseNonResidentAttribute(attribute); } PrettyPrintAttribute(parser, options, record, attribute, 1); if (attribute.Type == AttributeType.ATTRIBUTE_LIST) { foreach (FileReference otherFile in ((AttributeList)attribute).Items.Select(s => s.BaseFile)) { otherRecords.Add(otherFile); } } AwesomeConsole.WriteLine(); } // Don't go into infinite loops otherRecords.RemoveWhere(s => s.FileId == record.MFTNumber); foreach (FileReference fileReference in otherRecords) { AwesomeConsole.WriteLine(); PrintFull(parser, options, fileReference.FileId); } }
static void Main(string[] args) { Options opts = new Options(); bool success = opts.Parse(args); if (!success) { AwesomeConsole.WriteLine("Unable to parse the commandline:"); PrintError(opts.ErrorDetails); AwesomeConsole.WriteLine(); AwesomeConsole.WriteLine("Try --help for more informations"); return; } if (opts.ActionType == ActionType.ShowHelp) { opts.DisplayHelp(); return; } // Work with the options if (opts.ActionType == ActionType.ShowFull || opts.ActionType == ActionType.ShowExtents) { uint mftId = 0; if (opts.PathType == PathType.File || opts.PathType == PathType.Directory) { mftId = FindPathMftId(opts); } else if (opts.PathType == PathType.MftId) { mftId = opts.MftId; } using (RawDisk disk = new RawDisk(opts.Drive)) using (Stream stream = disk.CreateDiskStream()) { NTFSParser parser = new NTFSParser(stream); if (parser.FileRecordCount < mftId) { PrintError("The given path or MftID didn't exist"); AwesomeConsole.WriteLine(); switch (opts.PathType) { case PathType.Directory: case PathType.File: PrintError("Specified " + opts.PathType + ": " + opts.PathArgument); break; case PathType.MftId: PrintError("Specified type: MftId, id: " + opts.MftId); break; } AwesomeConsole.WriteLine(); return; } if (opts.ActionType == ActionType.ShowFull) { PrintFull(parser, opts, mftId); } else if (opts.ActionType == ActionType.ShowExtents) { PrintExtents(parser, opts, mftId); } } } else if (opts.ActionType == ActionType.Path) { using (RawDisk disk = new RawDisk(opts.Drive)) { PrintPaths(disk, opts); } } if (Debugger.IsAttached) { Console.ReadLine(); } }
private static void PrintExtents(NTFSParser parser, Options options, uint mftnumber) { // Read record List <FileRecord> records = new List <FileRecord>(); parser.CurrentMftRecordNumber = mftnumber; records.Add(parser.ParseNextRecord()); // Parse all references for (int i = 0; i < records.Count; i++) { List <AttributeList> lists = records[i].Attributes.OfType <AttributeList>().ToList(); foreach (AttributeList attr in lists) { if (attr.NonResidentFlag == ResidentFlag.NonResident) { parser.ParseNonResidentAttribute(attr); } foreach (AttributeListItem attributeListItem in attr.Items) { uint otherRecId = attributeListItem.BaseFile.FileId; // Is new? if (records.All(s => s.MFTNumber != otherRecId)) { parser.CurrentMftRecordNumber = otherRecId; records.Add(parser.ParseNextRecord()); } } } } // Combine all streams List <Attribute> attributes = records.SelectMany(x => x.Attributes.Where(s => s.NonResidentFlag == ResidentFlag.NonResident)).ToList(); var groups = attributes.GroupBy(s => new { s.Type, s.AttributeName }).OrderBy(s => s.Key.Type).ThenBy(s => s.Key.AttributeName).ToList(); foreach (var @group in groups) { List <DataFragment> fragments = @group.SelectMany(s => s.NonResidentHeader.Fragments).OrderBy(s => s.StartingVCN).ToList(); PrintType(group.Key.Type); AwesomeConsole.Write(" "); PrintName(group.Key.AttributeName, true, true); AwesomeConsole.Write(" "); AwesomeConsole.Write("{0:N0} fragments", fragments.Count); AwesomeConsole.WriteLine(); foreach (DataFragment fragment in fragments) { AwesomeConsole.Write(SingleIndent); PrintRange(parser, options, fragment.LCN, fragment.Clusters); AwesomeConsole.Write(" "); PrintSize(parser, options, fragment.Clusters); AwesomeConsole.WriteLine(); } AwesomeConsole.WriteLine(); } }
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(); }