Пример #1
0
        private void InitiateMFT()
        {
            // Read first FileRecord
            _buffer = new byte[BytesPrFileRecord];
            _diskStream.Seek((long)(_boot.MFTCluster * BytesPrCluster), SeekOrigin.Begin);
            _diskStream.Read(_buffer, 0, _buffer.Length);

            // Parse
            FileRecord record = FileRecord.Parse(_buffer, 0, _boot.BytesPrSector, _sectorsPrRecord);

            // TODO: Parse nonresident $DATA's
            _mftRecord = record;

            // Prep an NTFSDiskStream
            List <AttributeData> dataAttribs = _mftRecord.Attributes.OfType <AttributeData>().Where(s => s.AttributeName == string.Empty && s.NonResidentFlag == ResidentFlag.NonResident).ToList();

            DataFragment[] fragments = dataAttribs.SelectMany(s => s.DataFragments).OrderBy(s => s.StartingVCN).ToArray();

            ushort compressionUnitSize     = dataAttribs[0].NonResidentHeader.CompressionUnitSize;
            ushort compressionClusterCount = (ushort)(compressionUnitSize == 0 ? 0 : Math.Pow(2, compressionUnitSize));

            _mftStream = new NtfsDiskStream(_diskStream, false, fragments, BytesPrCluster, compressionClusterCount, (long)dataAttribs[0].NonResidentHeader.ContentSize);

            CurrentMftRecordNumber = 0;
            FileRecordCount        = (uint)(_mftStream.Length / BytesPrFileRecord);
        }
Пример #2
0
        public FileRecord ParseNextRecord()
        {
            Debug.Assert(_buffer.Length == BytesPrFileRecord);
            Debug.Assert(0 != BytesPrFileRecord);

            uint newPosition = CurrentMftRecordNumber * BytesPrFileRecord;

            if (_mftStream.Position != newPosition)
            {
                _mftStream.Seek(newPosition, SeekOrigin.Begin);
            }

            int read = _mftStream.Read(_buffer, 0, _buffer.Length);

            if (read == 0)
            {
                return(null);
            }

            // Parse
            FileRecord record = FileRecord.Parse(_buffer, 0, _boot.BytesPrSector, _sectorsPrRecord);

            // Increment number
            CurrentMftRecordNumber = record.MFTNumber + 1;

            return(record);
        }
Пример #3
0
        static void Main(string[] args)
        {
            char driveLetter = 'C';

            if (args.Length == 1)
            {
                driveLetter = args[0][0];
            }

            using (RawDisk disk = new RawDisk(driveLetter))
            {
                MftDiskExtents res = new MftDiskExtents();

                byte[]     ntfsBoot = disk.ReadSectors(0, 1);
                BootSector boot     = BootSector.ParseData(ntfsBoot, ntfsBoot.Length, 0);
                Console.WriteLine("MFT is at LCN " + boot.MFTCluster);

                MftDetails mft = GetMftDetails(disk, boot);
                Console.WriteLine("MFT is in " + mft.MftExtents.Length + " extents");

                res.Extents.AddRange(mft.MftExtents);

                using (RawDiskStream diskStream = disk.CreateDiskStream())
                    using (NtfsDiskStream mftStream = new NtfsDiskStream(diskStream, false, mft.MftExtents, (uint)disk.ClusterSize, 0, (long)mft.MftSize))
                    {
                        uint   sectorsPrRecord = (uint)(boot.MFTRecordSizeBytes / disk.SectorSize);
                        ushort bytesPrSector   = (ushort)disk.SectorSize;

                        int records = (int)(mftStream.Length / boot.MFTRecordSizeBytes);

                        byte[] tmp = new byte[boot.MFTRecordSizeBytes];
                        while (true)
                        {
                            int read = mftStream.Read(tmp, 0, tmp.Length);
                            if (read < boot.MFTRecordSizeBytes)
                            {
                                Console.WriteLine("Stopped reading as we got " + read + " bytes instead of " + tmp.Length + " bytes");
                                break;
                            }

                            FileRecord rec = FileRecord.Parse(tmp, 0, bytesPrSector, sectorsPrRecord);

                            // Keep track of all external extents to the MFT
                            RecordExternalDiskExtents(rec, res);

                            //// Special case for LIST attributes, since they can further reference more extents outside the MFT
                            //ProcessNonResidentListAttributes(disk, rec);
                        }
                    }

                long clustersTotal = res.Extents.Sum(x => x.Clusters);

                Console.WriteLine("To copy: {0:N0} extents", res.Extents.Count);
                Console.WriteLine("{0:N0} clusters, {1:N0} bytes", clustersTotal, clustersTotal * disk.ClusterSize);
            }

            Console.ReadLine();
        }
Пример #4
0
        private static MftDetails GetMftDetails(RawDisk disk, BootSector boot)
        {
            byte[]     mftFirst = disk.ReadClusters((long)boot.MFTCluster, 1);
            FileRecord rec      = FileRecord.Parse(mftFirst, 0, (ushort)disk.SectorSize, (uint)(boot.MFTRecordSizeBytes / disk.SectorSize));

            // Get DATA attrib
            // TODO: Handle multiple DATA attributes
            AttributeGeneric dataAttrib = null;

            foreach (Attribute attribute in rec.Attributes)
            {
                if (attribute.Type == AttributeType.DATA && attribute.AttributeName.Length == 0)
                {
                    // Got it!
                    dataAttrib = attribute as AttributeGeneric;
                    break;
                }
            }

            Debug.Assert(dataAttrib != null);

            MftDetails res = new MftDetails();

            // Get attribute data
            // Parse out extents
            if (dataAttrib.NonResidentFlag == ResidentFlag.Resident)
            {
                byte[] dataAttribData = dataAttrib.Data;

                res.MftSize    = dataAttrib.ResidentHeader.ContentLength;
                res.MftExtents = DataFragment.ParseFragments(dataAttribData, dataAttribData.Length, 0, 0, 0);
            }
            else
            {
                res.MftSize    = dataAttrib.NonResidentHeader.ContentSize;
                res.MftExtents = dataAttrib.NonResidentHeader.Fragments;
            }

            Debug.Assert(res.MftExtents != null);

            return(res);
        }
Пример #5
0
        public FileRecord NextMFTRecord()
        {
            var newPosition = CurrentMftRecordNumber * BytesPerFileRecord;

            if (mftStream.Position != newPosition)
            {
                mftStream.Seek(newPosition, SeekOrigin.Begin);
            }
            var read = mftStream.Read(buffer, 0, buffer.Length);

            if (read == 0)
            {
                return(null);
            }

            var record = FileRecord.Parse(buffer, 0, BootSector.BytesPerSector, SectorsPerRecord);

            CurrentMftRecordNumber = record.MFTNumber + 1;
            return(record);
        }
Пример #6
0
        private void ParseMft()
        {
            buffer = new byte[BytesPerFileRecord];
            DiskStream.Seek((long)(BootSector.MftCluster * BytesPerCluster), SeekOrigin.Begin);
            DiskStream.Read(buffer, 0, buffer.Length);
            mftRecord = FileRecord.Parse(buffer, 0, BootSector.BytesPerSector, SectorsPerRecord);

            var           fragmentList       = new List <DataFragment>();
            AttributeData firstAttributeData = null;

            foreach (var attribute in mftRecord.Attributes)
            {
                if (attribute is AttributeData data && data.AttributeName == string.Empty &&
                    data.NonResidentFlag == ResidentFlag.NonResident)
                {
                    if (firstAttributeData == null)
                    {
                        firstAttributeData = data;
                    }
                    foreach (var frag in data.DataFragments)
                    {
                        fragmentList.Add(frag);
                    }
                }
            }

            fragmentList = Utility.Util.Sort(fragmentList, new DataFragmentComparer());
            ushort compressionUnitSize     = firstAttributeData.NonResidentHeader.CompressionUnitSize;
            ushort compressionClusterCount = (ushort)(compressionUnitSize == 0 ? 0 : Math.Pow(2, compressionUnitSize));

            mftStream = new NtfsDiskStream(DiskStream, false, fragmentList, BytesPerCluster, compressionClusterCount, (long)firstAttributeData.NonResidentHeader.ContentSize);

            CurrentMftRecordNumber = 0;
            FileRecordCount        = (uint)(mftStream.Length / BytesPerFileRecord);
            Console.WriteLine("[NTFS DRIVER] " + FileRecordCount + " file records found");
        }
Пример #7
0
 private FileRecord ParseMFTRecord(byte[] data)
 {
     return(FileRecord.Parse(data, 0, Boot.BytesPrSector, _sectorsPrRecord));
 }
Пример #8
0
 public FileRecord ParseMftRecordData(byte[] data)
 {
     return(FileRecord.Parse(data, 0, BytesPerSector, SectorsPerRecord));
 }