public Index(File file, string name, BiosParameterBlock bpb, UpperCase upCase) { _file = file; _name = name; _bpb = bpb; _isFileIndex = name == "$I30"; _blockCache = new ObjectCache <long, IndexBlock>(); _root = _file.GetStream(AttributeType.IndexRoot, _name).GetContent <IndexRoot>(); _comparer = _root.GetCollator(upCase); using (Stream s = _file.OpenStream(AttributeType.IndexRoot, _name, FileAccess.Read)) { byte[] buffer = Utilities.ReadFully(s, (int)s.Length); _rootNode = new IndexNode(WriteRootNodeToDisk, 0, this, true, buffer, IndexRoot.HeaderOffset); // Give the attribute some room to breathe, so long as it doesn't squeeze others out // BROKEN, BROKEN, BROKEN - how to figure this out? Query at the point of adding entries to the root node? _rootNode.TotalSpaceAvailable += _file.MftRecordFreeSpace(AttributeType.IndexRoot, _name) - 100; } if (_file.StreamExists(AttributeType.IndexAllocation, _name)) { _indexStream = _file.OpenStream(AttributeType.IndexAllocation, _name, FileAccess.ReadWrite); } if (_file.StreamExists(AttributeType.Bitmap, _name)) { _indexBitmap = new Bitmap(_file.OpenStream(AttributeType.Bitmap, _name, FileAccess.ReadWrite), long.MaxValue); } }
internal static BiosParameterBlock Initialized(Geometry diskGeometry, int clusterSize, uint partitionStartLba, long partitionSizeLba, int mftRecordSize, int indexBufferSize) { BiosParameterBlock bpb = new BiosParameterBlock(); bpb.OemId = "NTFS "; bpb.BytesPerSector = Sizes.Sector; bpb.SectorsPerCluster = (byte)(clusterSize / bpb.BytesPerSector); bpb.ReservedSectors = 0; bpb.NumFats = 0; bpb.FatRootEntriesCount = 0; bpb.TotalSectors16 = 0; bpb.Media = 0xF8; bpb.FatSize16 = 0; bpb.SectorsPerTrack = (ushort)diskGeometry.SectorsPerTrack; bpb.NumHeads = (ushort)diskGeometry.HeadsPerCylinder; bpb.HiddenSectors = partitionStartLba; bpb.TotalSectors32 = 0; bpb.BiosDriveNumber = 0x80; bpb.ChkDskFlags = 0; bpb.SignatureByte = 0x80; bpb.PaddingByte = 0; bpb.TotalSectors64 = partitionSizeLba - 1; bpb.RawMftRecordSize = bpb.CodeRecordSize(mftRecordSize); bpb.RawIndexBufferSize = bpb.CodeRecordSize(indexBufferSize); bpb.VolumeSerialNumber = GenSerialNumber(); return(bpb); }
internal static BiosParameterBlock FromBytes(byte[] bytes, int offset) { BiosParameterBlock bpb = new BiosParameterBlock(); bpb.OemId = Utilities.BytesToString(bytes, offset + 0x03, 8); bpb.BytesPerSector = Utilities.ToUInt16LittleEndian(bytes, offset + 0x0B); bpb.SectorsPerCluster = bytes[offset + 0x0D]; bpb.ReservedSectors = Utilities.ToUInt16LittleEndian(bytes, offset + 0x0E); bpb.NumFats = bytes[offset + 0x10]; bpb.FatRootEntriesCount = Utilities.ToUInt16LittleEndian(bytes, offset + 0x11); bpb.TotalSectors16 = Utilities.ToUInt16LittleEndian(bytes, offset + 0x13); bpb.Media = bytes[offset + 0x15]; bpb.FatSize16 = Utilities.ToUInt16LittleEndian(bytes, offset + 0x16); bpb.SectorsPerTrack = Utilities.ToUInt16LittleEndian(bytes, offset + 0x18); bpb.NumHeads = Utilities.ToUInt16LittleEndian(bytes, offset + 0x1A); bpb.HiddenSectors = Utilities.ToUInt32LittleEndian(bytes, offset + 0x1C); bpb.TotalSectors32 = Utilities.ToUInt32LittleEndian(bytes, offset + 0x20); bpb.BiosDriveNumber = bytes[offset + 0x24]; bpb.ChkDskFlags = bytes[offset + 0x25]; bpb.SignatureByte = bytes[offset + 0x26]; bpb.PaddingByte = bytes[offset + 0x27]; bpb.TotalSectors64 = Utilities.ToInt64LittleEndian(bytes, offset + 0x28); bpb.MftCluster = Utilities.ToInt64LittleEndian(bytes, offset + 0x30); bpb.MftMirrorCluster = Utilities.ToInt64LittleEndian(bytes, offset + 0x38); bpb.RawMftRecordSize = bytes[offset + 0x40]; bpb.RawIndexBufferSize = bytes[offset + 0x44]; bpb.VolumeSerialNumber = Utilities.ToUInt64LittleEndian(bytes, offset + 0x48); return(bpb); }
private void CreateBiosParameterBlock(Stream stream, int bootFileSize) { byte[] bootSectors = new byte[bootFileSize]; if (BootCode != null) { Array.Copy(BootCode, 0, bootSectors, 0, BootCode.Length); } BiosParameterBlock bpb = BiosParameterBlock.Initialized(DiskGeometry, _clusterSize, (uint)FirstSector, SectorCount, _mftRecordSize, _indexBufferSize); bpb.MftCluster = _mftCluster; bpb.MftMirrorCluster = _mftMirrorCluster; bpb.ToBytes(bootSectors, 0); // Primary goes at the start of the partition stream.Position = 0; stream.Write(bootSectors, 0, bootSectors.Length); // Backup goes at the end of the data in the partition stream.Position = (SectorCount - 1) * Sizes.Sector; stream.Write(bootSectors, 0, Sizes.Sector); _context.BiosParameterBlock = bpb; }
private File CreateFixedSystemFile(long mftIndex, long firstCluster, ulong numClusters, bool wipe) { BiosParameterBlock bpb = _context.BiosParameterBlock; if (wipe) { byte[] wipeBuffer = new byte[bpb.BytesPerCluster]; _context.RawStream.Position = firstCluster * bpb.BytesPerCluster; for (ulong i = 0; i < numClusters; ++i) { _context.RawStream.Write(wipeBuffer, 0, wipeBuffer.Length); } } FileRecord fileRec = _context.Mft.AllocateRecord((uint)mftIndex, FileRecordFlags.None); fileRec.Flags = FileRecordFlags.InUse; fileRec.SequenceNumber = (ushort)mftIndex; File file = new File(_context, fileRec); StandardInformation.InitializeNewFile(file, FileAttributeFlags.Hidden | FileAttributeFlags.System); file.CreateStream(AttributeType.Data, null, firstCluster, numClusters, (uint)bpb.BytesPerCluster); file.UpdateRecordInMft(); if (_context.ClusterBitmap != null) { _context.ClusterBitmap.MarkAllocated(firstCluster, (long)numClusters); } return(file); }
public MasterFileTable(INtfsContext context) { BiosParameterBlock bpb = context.BiosParameterBlock; _recordCache = new ObjectCache <long, FileRecord>(); _recordLength = bpb.MftRecordSize; _bytesPerSector = bpb.BytesPerSector; // Temporary record stream - until we've bootstrapped the MFT properly _recordStream = new SubStream(context.RawStream, bpb.MftCluster * bpb.SectorsPerCluster * bpb.BytesPerSector, 24 * _recordLength); }
public IndexBlock(Index index, bool isRoot, IndexEntry parentEntry, BiosParameterBlock bpb) : base("INDX", bpb.BytesPerSector) { _index = index; _isRoot = isRoot; Stream stream = index.AllocationStream; _streamPosition = parentEntry.ChildrenVirtualCluster * bpb.BytesPerSector * bpb.SectorsPerCluster; stream.Position = _streamPosition; byte[] buffer = Utilities.ReadFully(stream, (int)index.IndexBufferSize); FromBytes(buffer, 0); }
private IndexBlock(Index index, bool isRoot, long vcn, BiosParameterBlock bpb) : base("INDX", bpb.BytesPerSector, bpb.IndexBufferSize) { _index = index; _isRoot = isRoot; _indexBlockVcn = (ulong)vcn; _streamPosition = vcn * bpb.BytesPerSector * bpb.SectorsPerCluster; _node = new IndexNode(WriteToDisk, UpdateSequenceSize, _index, isRoot, (uint)bpb.IndexBufferSize - FieldSize); WriteToDisk(); }
/// <summary> /// Gets an object that can convert between clusters and files. /// </summary> /// <returns>The cluster map</returns> public ClusterMap BuildClusterMap() { _context = new NtfsContext(); _context.RawStream = _target; _context.Options = new NtfsOptions(); _context.RawStream.Position = 0; byte[] bytes = Utilities.ReadFully(_context.RawStream, 512); _context.BiosParameterBlock = BiosParameterBlock.FromBytes(bytes, 0); _context.Mft = new MasterFileTable(_context); File mftFile = new File(_context, _context.Mft.GetBootstrapRecord()); _context.Mft.Initialize(mftFile); return(_context.Mft.GetClusterMap()); }
public File InitializeNew(INtfsContext context, long firstBitmapCluster, ulong numBitmapClusters, long firstRecordsCluster, ulong numRecordsClusters) { BiosParameterBlock bpb = context.BiosParameterBlock; FileRecord fileRec = new FileRecord(bpb.BytesPerSector, bpb.MftRecordSize, (uint)MftIndex); fileRec.Flags = FileRecordFlags.InUse; fileRec.SequenceNumber = 1; _recordCache[MftIndex] = fileRec; _self = new File(context, fileRec); StandardInformation.InitializeNewFile(_self, FileAttributeFlags.Hidden | FileAttributeFlags.System); NtfsStream recordsStream = _self.CreateStream(AttributeType.Data, null, firstRecordsCluster, numRecordsClusters, (uint)bpb.BytesPerCluster); _recordStream = recordsStream.Open(FileAccess.ReadWrite); Wipe(_recordStream); NtfsStream bitmapStream = _self.CreateStream(AttributeType.Bitmap, null, firstBitmapCluster, numBitmapClusters, (uint)bpb.BytesPerCluster); using (Stream s = bitmapStream.Open(FileAccess.ReadWrite)) { Wipe(s); s.SetLength(8); _bitmap = new Bitmap(s, long.MaxValue); } _recordLength = context.BiosParameterBlock.MftRecordSize; _bytesPerSector = context.BiosParameterBlock.BytesPerSector; _bitmap.MarkPresentRange(0, 1); // Write the MFT's own record to itself byte[] buffer = new byte[_recordLength]; fileRec.ToBytes(buffer, 0); _recordStream.Position = 0; _recordStream.Write(buffer, 0, _recordLength); _recordStream.Flush(); return(_self); }
private Index(AttributeType attrType, AttributeCollationRule collationRule, File file, string name, BiosParameterBlock bpb, UpperCase upCase) { _file = file; _name = name; _bpb = bpb; _isFileIndex = name == "$I30"; _blockCache = new ObjectCache <long, IndexBlock>(); _file.CreateStream(AttributeType.IndexRoot, _name); _root = new IndexRoot() { AttributeType = (uint)attrType, CollationRule = collationRule, IndexAllocationSize = (uint)bpb.IndexBufferSize, RawClustersPerIndexRecord = bpb.RawIndexBufferSize }; _comparer = _root.GetCollator(upCase); _rootNode = new IndexNode(WriteRootNodeToDisk, 0, this, true, 32); }
internal static IndexBlock Initialize(Index index, bool isRoot, IndexEntry parentEntry, BiosParameterBlock bpb) { return(new IndexBlock(index, isRoot, parentEntry.ChildrenVirtualCluster, bpb)); }
private void DoCheck() { _context.RawStream.Position = 0; byte[] bytes = Utilities.ReadFully(_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); } } }