Esempio n. 1
0
        /// <summary>
        /// Used to check/adjust data before we begin to interpret it
        /// </summary>
        private unsafe void FixupRawMftdata(byte *buffer, UInt64 len)
        {
            FileRecordHeader *ntfsFileRecordHeader = (FileRecordHeader *)buffer;

            if (ntfsFileRecordHeader->RecordHeader.Type != RecordType.File)
            {
                return;
            }

            UInt16 *wordBuffer = (UInt16 *)buffer;

            UInt16 *UpdateSequenceArray = (UInt16 *)(buffer + ntfsFileRecordHeader->RecordHeader.UsaOffset);
            UInt32  increment           = (UInt32)_diskInfo.BytesPerSector / sizeof(UInt16);

            UInt32 Index = increment - 1;

            for (int i = 1; i < ntfsFileRecordHeader->RecordHeader.UsaCount; i++)
            {
                /* Check if we are inside the buffer. */
                if (Index * sizeof(UInt16) >= len)
                {
                    throw new Exception("USA data indicates that data is missing, the MFT may be corrupt.");
                }

                // Check if the last 2 bytes of the sector contain the Update Sequence Number.
                if (wordBuffer[Index] != UpdateSequenceArray[0])
                {
                    throw new Exception("USA fixup word is not equal to the Update Sequence Number, the MFT may be corrupt.");
                }

                /* Replace the last 2 bytes in the sector with the value from the Usa array. */
                wordBuffer[Index] = UpdateSequenceArray[i];
                Index             = Index + increment;
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Process an actual MFT record from the buffer
        /// </summary>
        private unsafe bool ProcessMftRecord(byte *buffer, UInt64 length, UInt32 nodeIndex, out Node node, List <Stream> streams, bool isMftNode)
        {
            node = new Node();

            FileRecordHeader *ntfsFileRecordHeader = (FileRecordHeader *)buffer;

            node.MFTRecordNumber = ntfsFileRecordHeader->MFTRecordNumber;

            node.SequenceNumber = ntfsFileRecordHeader->BaseFileRecord.SequenceNumber;

            if (ntfsFileRecordHeader->RecordHeader.Type != RecordType.File)
            {
                return(false);
            }

            //the inode is not in use
            if ((ntfsFileRecordHeader->Flags & 1) != 1)
            {
                return(false);
            }

            UInt64 baseInode = ((UInt64)ntfsFileRecordHeader->BaseFileRecord.InodeNumberHighPart << 32) + ntfsFileRecordHeader->BaseFileRecord.InodeNumberLowPart;

            //This is an inode extension used in an AttributeAttributeList of another inode, don't parse it
            if (baseInode != 0)
            {
                return(false);
            }

            if (ntfsFileRecordHeader->AttributeOffset >= length)
            {
                throw new Exception("Error: attributes in Inode %I64u are outside the FILE record, the MFT may be corrupt.");
            }

            if (ntfsFileRecordHeader->BytesInUse > length)
            {
                throw new Exception("Error: in Inode %I64u the record is bigger than the size of the buffer, the MFT may be corrupt.");
            }

            //make the file appear in the rootdirectory by default
            node.ParentNodeIndex = ROOTDIRECTORY;

            if ((ntfsFileRecordHeader->Flags & 2) == 2)
            {
                node.Attributes |= Attributes.Directory;
            }

            ProcessAttributes(ref node, nodeIndex, buffer + ntfsFileRecordHeader->AttributeOffset, length - ntfsFileRecordHeader->AttributeOffset, 65535, 0, streams, isMftNode);

            return(true);
        }