private void PreVerifyMft(File file) { int recordLength = _context.BiosParameterBlock.MftRecordSize; int bytesPerSector = _context.BiosParameterBlock.BytesPerSector; // Check out the MFT's clusters foreach (Range<long, long> range in file.GetAttribute(AttributeType.Data, null).GetClusters()) { if (!VerifyClusterRange(range)) { ReportError("Corrupt cluster range in MFT data attribute {0}", range.ToString()); Abort(); } } foreach (Range<long, long> range in file.GetAttribute(AttributeType.Bitmap, null).GetClusters()) { if (!VerifyClusterRange(range)) { ReportError("Corrupt cluster range in MFT bitmap attribute {0}", range.ToString()); Abort(); } } using (Stream mftStream = file.OpenStream(AttributeType.Data, null, FileAccess.Read)) using (Stream bitmapStream = file.OpenStream(AttributeType.Bitmap, null, FileAccess.Read)) { Bitmap bitmap = new Bitmap(bitmapStream, long.MaxValue); long index = 0; while (mftStream.Position < mftStream.Length) { byte[] recordData = StreamUtilities.ReadExact(mftStream, recordLength); string magic = EndianUtilities.BytesToString(recordData, 0, 4); if (magic != "FILE") { if (bitmap.IsPresent(index)) { ReportError("Invalid MFT record magic at index {0} - was ({2},{3},{4},{5}) \"{1}\"", index, magic.Trim('\0'), (int)magic[0], (int)magic[1], (int)magic[2], (int)magic[3]); } } else { if (!VerifyMftRecord(recordData, bitmap.IsPresent(index), bytesPerSector)) { ReportError("Invalid MFT record at index {0}", index); StringBuilder bldr = new StringBuilder(); for (int i = 0; i < recordData.Length; ++i) { bldr.Append(string.Format(CultureInfo.InvariantCulture, " {0:X2}", recordData[i])); } ReportInfo("MFT record binary data for index {0}:{1}", index, bldr.ToString()); } } index++; } } }
private void DoCheck() { _context.RawStream.Position = 0; byte[] bytes = StreamUtilities.ReadExact(_context.RawStream, 512); _context.BiosParameterBlock = BiosParameterBlock.FromBytes(bytes, 0); //----------------------------------------------------------------------- // MASTER FILE TABLE // // Bootstrap the Master File Table _context.Mft = new MasterFileTable(_context); File mftFile = new File(_context, _context.Mft.GetBootstrapRecord()); // Verify basic MFT records before initializing the Master File Table PreVerifyMft(mftFile); _context.Mft.Initialize(mftFile); // Now the MFT is up and running, do more detailed analysis of it's contents - double-accounted clusters, etc VerifyMft(); _context.Mft.Dump(_report, "INFO: "); //----------------------------------------------------------------------- // INDEXES // // Need UpperCase in order to verify some indexes (i.e. directories). File ucFile = new File(_context, _context.Mft.GetRecord(MasterFileTable.UpCaseIndex, false)); _context.UpperCase = new UpperCase(ucFile); SelfCheckIndexes(); //----------------------------------------------------------------------- // DIRECTORIES // VerifyDirectories(); //----------------------------------------------------------------------- // WELL KNOWN FILES // VerifyWellKnownFilesExist(); //----------------------------------------------------------------------- // OBJECT IDS // VerifyObjectIds(); //----------------------------------------------------------------------- // FINISHED // // Temporary... using (NtfsFileSystem fs = new NtfsFileSystem(_context.RawStream)) { if ((_reportLevels & ReportLevels.Information) != 0) { ReportDump(fs); } } }