Esempio n. 1
0
        private void ParseAttributes(byte[] data, uint maxLength, int offset)
        {
            Debug.Assert(Signature == "FILE");

            int attribOffset = offset;

            for (int attribId = 0; ; attribId++)
            {
                AttributeType attributeType = Attribute.GetType(data, attribOffset);
                if (attributeType == AttributeType.EndOfAttributes)
                {
                    break;
                }

                uint length = Attribute.GetTotalLength(data, attribOffset);

                Debug.Assert(attribOffset + length <= offset + maxLength);

                Attribute attrib = Attribute.ParseSingleAttribute(data, (int)length, attribOffset);
                attrib.OwningRecord = FileReference;
                _attributes.Add(attrib);

                attribOffset += attrib.TotalLength;
            }
        }
Esempio n. 2
0
 public void ParseNonResidentAttribute(Attribute attr)
 {
     if (attr.NonResidentFlag == ResidentFlag.NonResident && attr.NonResidentHeader.Fragments.Length > 0)
     {
         // Get data
         attr.ParseAttributeNonResidentBody(this);
     }
 }
Esempio n. 3
0
        public void ParseNonResidentAttribute(Attribute attr)
        {
            if (Provider.MftFileOnly)
            {               // Nothing to do about this
                throw new InvalidOperationException("Provider indicates an MFT file is used. Cannot parse non-resident attributes.");
            }

            if (attr.NonResidentHeader.Fragments.Length > 0)
            {               // Get data
                attr.ParseAttributeNonResidentBody(this);
            }
        }
Esempio n. 4
0
        private void InitializeNTFS()
        {
            // Read $BOOT
            if (Provider.MftFileOnly)
            {
                Boot                  = new BootSector();
                Boot.OEMCode          = "NTFS";
                Boot.SectorsPrCluster = 2;                      // Small cluster
                Boot.BytesPrSector    = 512;                    // Smallest possible sector

                // Get FileRecord size (read first record's size)
                byte[] mft_data = new byte[512];
                Provider.ReadBytes(mft_data, 0, 0, mft_data.Length);

                Boot.MFTRecordSizeBytes = FileRecord.ParseAllocatedSize(mft_data, 0);

                mft_data = null;
            }
            else
            {
                byte[] drive_data = new byte[512];
                Provider.ReadBytes(drive_data, 0, 0, 512);
                Boot = BootSector.ParseData(drive_data, 512, 0);

                drive_data = null;

                Debug.Assert(Boot.OEMCode == "NTFS");
            }

            // Get FileRecord size
            BytesPrFileRecord = Boot.MFTRecordSizeBytes;
            _sectorsPrRecord  = BytesPrFileRecord / BytesPrSector;
            Debug.WriteLine($"Updated BytesPrFileRecord, now set to {BytesPrFileRecord}");

            // Prep cache
            MftRawCache = new RawDiskCache(0);

            // Read $MFT file record

            byte[] record_data = ReadMFTRecordData((uint)SpecialMFTFiles.MFT);
            FileMFT     = ParseMFTRecord(record_data);
            record_data = null;


            Debug.Assert(FileMFT != null);

            Debug.Assert(FileMFT.Attributes.Count(s => s.Type == AttributeType.DATA) == 1);
            AttributeData fileMftData = FileMFT.Attributes.OfType <AttributeData>().Single();

            Debug.Assert(fileMftData.NonResidentFlag == ResidentFlag.NonResident);
            Debug.Assert(fileMftData.DataFragments.Length >= 1);

            MftStream = OpenFileRecord(FileMFT);

            // Prep cache
            long maxLength          = MftStream.Length;
            long toAllocateForCache = Math.Min(maxLength, _rawDiskCacheSizeRecords * BytesPrFileRecord);

            MftRawCache = new RawDiskCache((int)toAllocateForCache);

            // Get number of FileRecords
            FileRecordCount = (uint)((fileMftData.DataFragments.Sum(s => (float)s.Clusters)) * (BytesPrCluster * 1f / BytesPrFileRecord));
            FileRecords     = new WeakReference[FileRecordCount];

            FileRecords[0] = new WeakReference(FileMFT);

            // Read $VOLUME file record
            FileRecord fileVolume = ReadMFTRecord(SpecialMFTFiles.Volume);

            // Get version
            Attribute versionAttrib = fileVolume.Attributes.SingleOrDefault(s => s.Type == AttributeType.VOLUME_INFORMATION);

            if (versionAttrib != null)
            {
                AttributeVolumeInformation attrib = (AttributeVolumeInformation)versionAttrib;
                NTFSVersion = new Version(attrib.MajorVersion, attrib.MinorVersion);
            }
        }
        private static void PrettyPrintAttribute(NTFSParser parser, Options options, FileRecord record, Attribute attrib, int indentCount)
        {
            string indent = "";

            for (int i = 0; i < indentCount; i++)
            {
                indent += SingleIndent;
            }

            AwesomeConsole.Write(indent + attrib.Id + ": ");
            PrintType(attrib.Type);

            AwesomeConsole.Write(" ");
            PrintName(attrib.AttributeName, true, true);

            if (attrib.NonResidentFlag == ResidentFlag.NonResident)
            {
                AwesomeConsole.Write(" (NonResident)", ConsoleColor.Red);
            }

            AwesomeConsole.WriteLine();

            indent += SingleIndent;

            switch (attrib.Type)
            {
            case AttributeType.STANDARD_INFORMATION:
                AttributeStandardInformation standardInformation = (AttributeStandardInformation)attrib;

                AwesomeConsole.WriteLine(indent + "Creation Time: " + standardInformation.TimeCreated + " " + standardInformation.TimeCreated.Kind);
                AwesomeConsole.WriteLine(indent + "Modified Time: " + standardInformation.TimeModified + " " + standardInformation.TimeModified.Kind);
                AwesomeConsole.WriteLine(indent + "Accessed Time: " + standardInformation.TimeAccessed + " " + standardInformation.TimeAccessed.Kind);
                AwesomeConsole.WriteLine(indent + "Mft Modified : " + standardInformation.TimeMftModified + " " + standardInformation.TimeMftModified.Kind);

                break;

            case AttributeType.ATTRIBUTE_LIST:
                AttributeList list = (AttributeList)attrib;

                foreach (AttributeListItem listItem in list.Items)
                {
                    AwesomeConsole.Write(indent + listItem.AttributeId + ": ");
                    PrintType(listItem.Type);
                    AwesomeConsole.Write(" ");

                    PrintName(listItem.Name, true, true);
                    AwesomeConsole.Write(" ");

                    if (record.FileReference == listItem.BaseFile)
                    {
                        AwesomeConsole.Write("(this record)", ConsoleColor.DarkGray);
                    }
                    else
                    {
                        PrintReference(listItem.BaseFile);
                    }

                    AwesomeConsole.WriteLine();
                }

                break;

            case AttributeType.FILE_NAME:
                AttributeFileName fileName = (AttributeFileName)attrib;

                using (AwesomeConsole.BeginSequentialWrite())
                {
                    AwesomeConsole.Write(indent + "Parent dir: ");
                    AwesomeConsole.WriteLine(fileName.ParentDirectory, ConsoleColor.Cyan);
                }

                AwesomeConsole.WriteLine(indent + "Namespace: " + fileName.FilenameNamespace);

                AwesomeConsole.Write(indent + "Flags: ");
                PrintEnums(fileName.FileFlags);
                AwesomeConsole.WriteLine();

                AwesomeConsole.Write(indent + "Name: ");
                PrintName(fileName.FileName, false, true);
                AwesomeConsole.WriteLine();

                AwesomeConsole.WriteLine(indent + "C Time: " + fileName.CTime + " " + fileName.CTime.Kind);
                AwesomeConsole.WriteLine(indent + "M Time: " + fileName.MTime + " " + fileName.MTime.Kind);
                AwesomeConsole.WriteLine(indent + "A Time: " + fileName.ATime + " " + fileName.ATime.Kind);
                AwesomeConsole.WriteLine(indent + "R Time: " + fileName.RTime + " " + fileName.RTime.Kind);

                break;

            case AttributeType.DATA:
                AttributeData data = (AttributeData)attrib;

                if (data.NonResidentFlag == ResidentFlag.Resident)
                {
                    AwesomeConsole.WriteLine(indent + "Data length: {0:N0} Bytes", data.ResidentHeader.ContentLength);
                }
                else
                {
                    AwesomeConsole.WriteLine(indent + "Data length: {0:N0} Bytes", data.NonResidentHeader.ContentSize);

                    AwesomeConsole.Write(indent + "VCN: ");
                    PrintRange(parser, options, data.NonResidentHeader.StartingVCN, data.NonResidentHeader.EndingVCN - data.NonResidentHeader.StartingVCN);
                    AwesomeConsole.WriteLine();

                    AwesomeConsole.WriteLine(indent + "Fragments: {0:N0}", data.NonResidentHeader.Fragments.Length);

                    AwesomeConsole.WriteLine(indent + SingleIndent + "LCN-range, cluster count, VCN-range", ConsoleColor.DarkGray);

                    foreach (DataFragment fragment in data.NonResidentHeader.Fragments)
                    {
                        AwesomeConsole.Write(indent + SingleIndent);
                        PrintRange(parser, options, fragment.LCN, fragment.Clusters);
                        AwesomeConsole.Write(SingleIndent);
                        PrintSize(parser, options, fragment.Clusters);
                        AwesomeConsole.Write(SingleIndent);
                        PrintRange(parser, options, fragment.StartingVCN, fragment.Clusters);

                        if (fragment.IsCompressed)
                        {
                            AwesomeConsole.Write(" (Compressed)");
                        }
                        if (fragment.IsSparseFragment)
                        {
                            AwesomeConsole.Write(" (Sparse)");
                        }

                        AwesomeConsole.WriteLine();
                    }
                }

                break;

            case AttributeType.OBJECT_ID:
                AttributeObjectId objectId = (AttributeObjectId)attrib;

                AwesomeConsole.Write(indent + "ObjectId    : ");
                PrintGUID(objectId.ObjectId);
                AwesomeConsole.WriteLine();

                AwesomeConsole.Write(indent + "BithVolumeId: ");
                PrintGUID(objectId.BithVolumeId);
                AwesomeConsole.WriteLine();

                AwesomeConsole.Write(indent + "BithObjectId: ");
                PrintGUID(objectId.BithObjectId);
                AwesomeConsole.WriteLine();

                AwesomeConsole.Write(indent + "DomainId    : ");
                PrintGUID(objectId.DomainId);
                AwesomeConsole.WriteLine();

                break;

            case AttributeType.SECURITY_DESCRIPTOR:
                AttributeSecurityDescriptor securityDescriptor = (AttributeSecurityDescriptor)attrib;

                AwesomeConsole.Write(indent + "SID: ");
                PrintSID(securityDescriptor.UserSID);
                AwesomeConsole.WriteLine();

                AwesomeConsole.Write(indent + "GID: ");
                PrintSID(securityDescriptor.GroupSID);
                AwesomeConsole.WriteLine();

                AwesomeConsole.Write(indent + "Flags: ");
                PrintEnums(securityDescriptor.ControlFlags);
                AwesomeConsole.WriteLine();

                AwesomeConsole.WriteLine();

                AwesomeConsole.WriteLine(indent + "SACL: " + (securityDescriptor.SACL == null ? 0 : securityDescriptor.SACL.ACECount));
                if (securityDescriptor.SACL == null)
                {
                    AwesomeConsole.WriteLine(indent + SingleIndent + "Not present", ConsoleColor.Red);
                }
                else
                {
                    foreach (ACE ace in securityDescriptor.SACL.ACEs)
                    {
                        PrintACE(indent, ace);
                    }
                }

                AwesomeConsole.WriteLine(indent + "DACL: " + (securityDescriptor.DACL == null ? 0 : securityDescriptor.DACL.ACECount));
                if (securityDescriptor.DACL == null)
                {
                    AwesomeConsole.WriteLine(indent + SingleIndent + "Not present", ConsoleColor.Red);
                }
                else
                {
                    foreach (ACE ace in securityDescriptor.DACL.ACEs)
                    {
                        PrintACE(indent, ace);
                    }
                }

                break;

            case AttributeType.VOLUME_NAME:
                AttributeVolumeName volumeName = (AttributeVolumeName)attrib;

                AwesomeConsole.Write(indent + "Name: ");
                PrintName(volumeName.VolumeName);
                AwesomeConsole.WriteLine();

                break;

            case AttributeType.VOLUME_INFORMATION:
                AttributeVolumeInformation volumeInformation = (AttributeVolumeInformation)attrib;

                AwesomeConsole.WriteLine(indent + "Reserved: " + volumeInformation.Reserved);
                AwesomeConsole.WriteLine(indent + "MajorVersion: " + volumeInformation.MajorVersion + "." + volumeInformation.MinorVersion);

                AwesomeConsole.Write(indent + "VolumeInformationFlag: ");
                PrintEnums(volumeInformation.VolumeInformationFlag);
                AwesomeConsole.WriteLine();

                break;

            case AttributeType.INDEX_ROOT:
                AttributeIndexRoot indexRoot = (AttributeIndexRoot)attrib;

                AwesomeConsole.WriteLine(indent + "IndexType: " + indexRoot.IndexType);
                AwesomeConsole.WriteLine(indent + "CollationRule: " + indexRoot.CollationRule);
                AwesomeConsole.WriteLine(indent + "IndexAllocationSize: " + indexRoot.IndexAllocationSize);
                AwesomeConsole.WriteLine(indent + "ClustersPrIndexRecord: " + indexRoot.ClustersPrIndexRecord);
                AwesomeConsole.WriteLine();

                AwesomeConsole.WriteLine(indent + "SizeOfIndexTotal: " + indexRoot.SizeOfIndexTotal);
                AwesomeConsole.WriteLine(indent + "IndexFlags: " + indexRoot.IndexFlags);
                AwesomeConsole.WriteLine(indent + "Entries: " + indexRoot.Entries.Length);

                foreach (IndexEntry entry in indexRoot.Entries)
                {
                    AwesomeConsole.Write(indent + SingleIndent);
                    PrintReference(entry.FileRefence);

                    if (entry.ChildFileName != null)
                    {
                        AwesomeConsole.Write(" ");
                        PrintName(entry.ChildFileName.FileName, true);
                        AwesomeConsole.Write(" ");
                        PrintEnums(entry.ChildFileName.FileFlags);
                    }

                    AwesomeConsole.WriteLine();
                }

                break;

            case AttributeType.INDEX_ALLOCATION:
                AttributeIndexAllocation indexAllocation = (AttributeIndexAllocation)attrib;

                AwesomeConsole.WriteLine(indent + "Chunks: " + indexAllocation.Indexes.Length);

                for (int i = 0; i < indexAllocation.Indexes.Length; i++)
                {
                    IndexAllocationChunk chunk = indexAllocation.Indexes[i];
                    AwesomeConsole.WriteLine(indent + SingleIndent + string.Format("{0:N0}: {1:N0} of {2:N0} Bytes used", i, chunk.SizeOfIndexTotal, chunk.SizeOfIndexAllocated));
                }

                AwesomeConsole.WriteLine(indent + "Entries: " + indexAllocation.Entries.Length);

                foreach (IndexEntry entry in indexAllocation.Entries)
                {
                    AwesomeConsole.Write(indent + SingleIndent);
                    PrintReference(entry.FileRefence);

                    if (entry.ChildFileName != null)
                    {
                        AwesomeConsole.Write(" ");
                        PrintName(entry.ChildFileName.FileName, true);
                        AwesomeConsole.Write(" ");
                        PrintEnums(entry.ChildFileName.FileFlags);
                    }

                    AwesomeConsole.WriteLine();
                }

                break;

            case AttributeType.BITMAP:
                AttributeBitmap bitmap = (AttributeBitmap)attrib;

                AwesomeConsole.WriteLine(indent + "Bitfield Size: {0:N0} ({1:N0} bytes)", bitmap.Bitfield.Length, bitmap.Bitfield.Length / 8);

                // Print out 4 lines of 64 bits
                const int bitsPrLine = 64;

                for (int line = 0; line < 4; line++)
                {
                    if (bitmap.Bitfield.Length <= line * bitsPrLine)
                    {
                        break;
                    }

                    AwesomeConsole.Write(indent + "{0,-6}", (line * bitsPrLine) + ":");

                    for (int offset = line * bitsPrLine; offset < line * bitsPrLine + bitsPrLine; offset += 8)
                    {
                        if (bitmap.Bitfield.Length <= offset)
                        {
                            break;
                        }

                        for (int j = offset; j < offset + 8; j++)
                        {
                            if (bitmap.Bitfield.Length <= j)
                            {
                                break;
                            }

                            AwesomeConsole.Write(bitmap.Bitfield[j] ? "1" : "0");
                        }

                        AwesomeConsole.Write(" ");
                    }

                    AwesomeConsole.WriteLine();
                }

                if (bitmap.Bitfield.Length > 256)
                {
                    PrintError(indent + "Bitfield was longer than 256 bits, so the rest wasn't printed.");
                    AwesomeConsole.WriteLine();
                }

                break;

            case AttributeType.LOGGED_UTILITY_STREAM:
                AttributeLoggedUtilityStream loggedUtilityStream = (AttributeLoggedUtilityStream)attrib;

                AwesomeConsole.WriteLine(indent + "Data: {0:N0} Bytes", loggedUtilityStream.Data.Length);

                break;

            default:
                if (Debugger.IsAttached)
                {
                    Debugger.Break();
                }
                PrintError(attrib.Type + " not supported");
                break;
            }
        }
Esempio n. 6
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);
            }
        }