예제 #1
0
        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);
        }
예제 #2
0
        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);
            }
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
            }
        }
예제 #5
0
        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;
        }
예제 #6
0
        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);
        }
예제 #7
0
        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);
        }
예제 #8
0
        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);
        }
예제 #9
0
        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);
        }
예제 #10
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();
        }
예제 #11
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();
        }
예제 #12
0
        /// <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());
        }
예제 #13
0
        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);
        }
예제 #14
0
        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);
        }
예제 #15
0
        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);
        }
예제 #16
0
        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);
                }
            }
        }
예제 #17
0
        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;
        }
예제 #18
0
        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;
        }
예제 #19
0
 internal static IndexBlock Initialize(Index index, bool isRoot, IndexEntry parentEntry, BiosParameterBlock bpb)
 {
     return new IndexBlock(index, isRoot, parentEntry.ChildrenVirtualCluster, bpb);
 }
예제 #20
0
 internal static IndexBlock Initialize(Index index, bool isRoot, IndexEntry parentEntry, BiosParameterBlock bpb)
 {
     return(new IndexBlock(index, isRoot, parentEntry.ChildrenVirtualCluster, bpb));
 }