Exemplo n.º 1
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();
        }
Exemplo n.º 2
0
        internal override void ParseAttributeNonResidentBody(RawDisk disk)
        {
            base.ParseAttributeNonResidentBody(disk);

            // Read clusters from disk
            Data = new byte[NonResidentHeader.ContentSize];

            using (RawDiskStream diskStream = disk.CreateDiskStream())
                using (NtfsDiskStream attribStream = new NtfsDiskStream(diskStream, false, NonResidentHeader.Fragments, (uint)disk.ClusterSize, 0, Data.LongLength))
                    attribStream.Read(Data, 0, Data.Length);
        }
        public static byte[] ReadFragments(INTFSInfo ntfsInfo, DataFragment[] fragments)
        {
            int totalLength = (int)(fragments.Sum(s => (decimal)s.Clusters) * ntfsInfo.BytesPrCluster);

            byte[] data = new byte[totalLength];

            Stream diskStream = ntfsInfo.GetDiskStream();

            using (NtfsDiskStream stream = new NtfsDiskStream(diskStream, ntfsInfo.OwnsDiskStream, fragments, ntfsInfo.BytesPrCluster, 0, totalLength))
            {
                stream.Read(data, 0, data.Length);
            }

            // Return the data
            return(data);
        }
        public static byte[] ReadFragments(RawDisk disk, DataFragment[] fragments)
        {
            int totalLength = 0;

            foreach (DataFragment fragment in fragments)
            {
                totalLength += (int)(fragment.Clusters * disk.ClusterSize);
            }

            byte[] data = new byte[totalLength];

            using (Stream diskStream = disk.CreateDiskStream())
                using (NtfsDiskStream stream = new NtfsDiskStream(diskStream, false, fragments, (uint)disk.ClusterSize, 0, totalLength))
                {
                    stream.Read(data, 0, data.Length);
                }

            // Return the data
            return(data);
        }
Exemplo n.º 5
0
        public static byte[] ReadFragments(Ntfs ntfsInfo, List <DataFragment> fragments)
        {
            long totalLength = 0;

            foreach (var frag in fragments)
            {
                totalLength += frag.Clusters * ntfsInfo.BytesPerCluster;
            }

            var data = new byte[totalLength];

            Stream diskStream = ntfsInfo.DiskStream;

            using (NtfsDiskStream stream = new NtfsDiskStream(diskStream, false, fragments, ntfsInfo.BytesPerCluster, 0, totalLength))
            {
                stream.Read(data, 0, data.Length);
            }

            // Return the data
            return(data);
        }
Exemplo n.º 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");
        }
Exemplo n.º 7
0
        private static void PerformCopy(NTFSWrapper wrapper, Options opts, uint mftId)
        {
            // Fetch record
            FileRecord record = wrapper.ReadMFTRecord(mftId);

            // Find attribute(s)
            List <Attribute> attribs = record.Attributes.Concat(record.ExternalAttributes).Where(s => s.Type == opts.SourceAttribute && s.AttributeName == opts.SourceName).ToList();

            if (!attribs.Any())
            {
                PrintError("Unable to find any attribute named \"" + opts.SourceName + "\" of type " + opts.SourceAttribute);
                AwesomeConsole.WriteLine();
                return;
            }

            // Determine resident or non-resident data
            Stream fileStream = null;

            if (attribs.All(x => x.NonResidentFlag == ResidentFlag.NonResident))
            {
                // Fetch fragments
                DataFragment[] fragments = attribs.SelectMany(s => s.NonResidentHeader.Fragments).OrderBy(s => s.StartingVCN).ToArray();

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

                fileStream = new NtfsDiskStream(wrapper.GetDiskStream(), true, fragments, wrapper.BytesPrCluster, compressionClusterCount, (long)attribs.First().NonResidentHeader.ContentSize);
            }
            else
            {
                // Fetch data
                if (attribs.Count != 1)
                {
                    PrintError("There were multiple attributes for this single file that matched, yet they were all Resident. This is an error.");
                    AwesomeConsole.WriteLine();
                    return;
                }

                Attribute attrib = attribs.First();

                if (attrib is AttributeGeneric)
                {
                    AttributeGeneric generic = (AttributeGeneric)attrib;

                    fileStream = new MemoryStream(generic.Data);
                }
                else if (attrib is AttributeData)
                {
                    AttributeData data = (AttributeData)attrib;

                    fileStream = new MemoryStream(data.DataBytes);
                }
                else
                {
                    PrintError("Only certain resident attributes are supported, like $DATA");
                    AwesomeConsole.WriteLine();
                    return;
                }
            }

            // Perform copy
            using (AwesomeConsole.BeginSequentialWrite())
            {
                AwesomeConsole.Write("Found data, copying ");
                AwesomeConsole.Write(fileStream.Length.ToString("N0"), ConsoleColor.Green);
                AwesomeConsole.Write(" bytes to ");
                AwesomeConsole.WriteLine(opts.Destination, ConsoleColor.Green);
            }

            using (FileStream fs = File.OpenWrite(opts.Destination))
            {
                if (fs.CanSeek && fs.CanWrite)
                {
                    // Pre-expand the destination, to help filesystems allocate files
                    fs.SetLength(fileStream.Length);
                }

                byte[] buff           = new byte[65535];
                int    lastProgressed = -1;
                for (long offset = 0; offset < fileStream.Length; offset += buff.Length)
                {
                    int read = fileStream.Read(buff, 0, buff.Length);

                    if (read == 0)
                    {
                        // Finished
                        break;
                    }

                    fs.Write(buff, 0, read);

                    int progressed = (int)((offset * 1f / fileStream.Length) * 20);
                    if (read != buff.Length)
                    {
                        // Finished
                        progressed = 20;
                    }

                    if (lastProgressed != progressed)
                    {
                        AwesomeConsole.Write("[");
                        for (int i = 0; i < 20; i++)
                        {
                            if (i < progressed)
                            {
                                AwesomeConsole.Write("=");
                            }
                            else if (i == progressed)
                            {
                                AwesomeConsole.Write(">");
                            }
                            else
                            {
                                AwesomeConsole.Write(" ");
                            }
                        }
                        AwesomeConsole.Write("]");
                        Console.CursorLeft = 0;

                        lastProgressed = progressed;
                    }
                }
                AwesomeConsole.WriteLine();

                AwesomeConsole.WriteLine("Done.", ConsoleColor.Green);
            }
        }