Example #1
0
        public byte[] GetBytes(int bytesPerIndexRecord)
        {
            int               strideCount             = bytesPerIndexRecord / MultiSectorHelper.BytesPerStride;
            ushort            updateSequenceArraySize = (ushort)(1 + strideCount);
            MultiSectorHeader multiSectorHeader       = new MultiSectorHeader(ValidSignature, UpdateSequenceArrayOffset, updateSequenceArraySize);

            int updateSequenceArrayPaddedLength = (int)Math.Ceiling((double)(updateSequenceArraySize * 2) / 8) * 8;

            m_indexHeader.EntriesOffset   = (uint)(IndexHeader.Length + updateSequenceArrayPaddedLength);
            m_indexHeader.TotalLength     = (uint)(IndexHeader.Length + updateSequenceArrayPaddedLength + IndexEntry.GetLength(IndexEntries));
            m_indexHeader.AllocatedLength = (uint)(bytesPerIndexRecord - IndexHeaderOffset);

            byte[] buffer = new byte[bytesPerIndexRecord];
            multiSectorHeader.WriteBytes(buffer, 0x00);
            LittleEndianWriter.WriteUInt64(buffer, 0x08, LogFileSequenceNumber);
            LittleEndianWriter.WriteUInt64(buffer, 0x10, (ulong)RecordVBN);
            m_indexHeader.WriteBytes(buffer, 0x18);

            IndexEntry.WriteIndexEntries(buffer, UpdateSequenceArrayOffset + updateSequenceArrayPaddedLength, IndexEntries);

            // Write UpdateSequenceNumber and UpdateSequenceReplacementData
            List <byte[]> updateSequenceReplacementData = MultiSectorHelper.EncodeSegmentBuffer(buffer, 0, bytesPerIndexRecord, UpdateSequenceNumber);

            MultiSectorHelper.WriteUpdateSequenceArray(buffer, UpdateSequenceArrayOffset, updateSequenceArraySize, UpdateSequenceNumber, updateSequenceReplacementData);
            return(buffer);
        }
Example #2
0
        public byte[] GetBytes(int bytesPerIndexRecord, bool applyUsaProtection)
        {
            int               strideCount             = bytesPerIndexRecord / MultiSectorHelper.BytesPerStride;
            ushort            updateSequenceArraySize = (ushort)(1 + strideCount);
            MultiSectorHeader multiSectorHeader       = new MultiSectorHeader(ValidSignature, UpdateSequenceArrayOffset, updateSequenceArraySize);

            int updateSequenceArrayPaddedLength = (int)Math.Ceiling((double)(updateSequenceArraySize * 2) / 8) * 8;

            m_indexHeader.EntriesOffset   = (uint)(IndexHeader.Length + updateSequenceArrayPaddedLength);
            m_indexHeader.TotalLength     = (uint)(IndexHeader.Length + updateSequenceArrayPaddedLength + IndexEntry.GetLength(IndexEntries));
            m_indexHeader.AllocatedLength = (uint)(bytesPerIndexRecord - IndexHeaderOffset);

            int length = applyUsaProtection ? bytesPerIndexRecord : GetNumberOfBytesInUse(bytesPerIndexRecord);

            byte[] buffer = new byte[length];
            multiSectorHeader.WriteBytes(buffer, 0x00);
            LittleEndianWriter.WriteUInt64(buffer, 0x08, LogFileSequenceNumber);
            LittleEndianWriter.WriteUInt64(buffer, 0x10, (ulong)RecordVBN);
            m_indexHeader.WriteBytes(buffer, 0x18);
            LittleEndianWriter.WriteUInt16(buffer, UpdateSequenceArrayOffset, UpdateSequenceNumber);

            IndexEntry.WriteIndexEntries(buffer, UpdateSequenceArrayOffset + updateSequenceArrayPaddedLength, IndexEntries);

            if (applyUsaProtection)
            {
                MultiSectorHelper.ApplyUsaProtection(buffer, 0);
            }
            return(buffer);
        }
        private LfsRestartPage ReadRestartPage()
        {
            byte[] firstPageBytes = ReadData(0, Volume.BytesPerSector);
            uint   systemPageSize = LfsRestartPage.GetSystemPageSize(firstPageBytes, 0);
            int    bytesToRead    = (int)systemPageSize - firstPageBytes.Length;

            if (bytesToRead > 0)
            {
                byte[] temp = ReadData((ulong)firstPageBytes.Length, bytesToRead);
                firstPageBytes = ByteUtils.Concatenate(firstPageBytes, temp);
            }
            MultiSectorHelper.RevertUsaProtection(firstPageBytes, 0);
            LfsRestartPage firstRestartPage = new LfsRestartPage(firstPageBytes, 0);

            byte[] secondPageBytes = ReadData(systemPageSize, (int)systemPageSize);
            MultiSectorHelper.RevertUsaProtection(secondPageBytes, 0);
            LfsRestartPage secondRestartPage = new LfsRestartPage(secondPageBytes, 0);

            if (secondRestartPage.RestartArea.CurrentLsn > firstRestartPage.RestartArea.CurrentLsn)
            {
                m_restartPage            = secondRestartPage;
                m_isFirstRestartPageTurn = true;
            }
            else
            {
                m_restartPage = firstRestartPage;
            }
            return(m_restartPage);
        }
Example #4
0
        public byte[] GetBytes(int bytesPerSystemPage, bool applyUsaProtection)
        {
            m_systemPageSize = (uint)bytesPerSystemPage;
            int               strideCount             = bytesPerSystemPage / MultiSectorHelper.BytesPerStride;
            ushort            updateSequenceArraySize = (ushort)(1 + strideCount);
            MultiSectorHeader multiSectorHeader       = new MultiSectorHeader(ValidSignature, UpdateSequenceArrayOffset, updateSequenceArraySize);
            int               restartOffset           = (int)Math.Ceiling((double)(UpdateSequenceArrayOffset + updateSequenceArraySize * 2) / 8) * 8;

            byte[] buffer = new byte[bytesPerSystemPage];
            multiSectorHeader.WriteBytes(buffer, 0);
            LittleEndianWriter.WriteUInt64(buffer, 0x08, ChkDskLsn);
            LittleEndianWriter.WriteUInt32(buffer, 0x10, m_systemPageSize);
            LittleEndianWriter.WriteUInt32(buffer, 0x14, LogPageSize);
            LittleEndianWriter.WriteUInt16(buffer, 0x18, (ushort)restartOffset);
            LittleEndianWriter.WriteInt16(buffer, 0x1A, MinorVersion);
            LittleEndianWriter.WriteInt16(buffer, 0x1C, MajorVersion);
            LittleEndianWriter.WriteUInt16(buffer, UpdateSequenceArrayOffset, UpdateSequenceNumber);
            RestartArea.WriteBytes(buffer, restartOffset);

            if (applyUsaProtection)
            {
                MultiSectorHelper.ApplyUsaProtection(buffer, 0);
            }
            return(buffer);
        }
        /// <param name="segmentLength">This refers to the maximum length of FileRecord as defined in the Volume's BootRecord</param>
        public byte[] GetBytes(int bytesPerFileRecordSegment, ushort minorNTFSVersion)
        {
            int    strideCount             = bytesPerFileRecordSegment / MultiSectorHelper.BytesPerStride;
            ushort updateSequenceArraySize = (ushort)(1 + strideCount);

            ushort updateSequenceArrayOffset;

            if (minorNTFSVersion == 0)
            {
                updateSequenceArrayOffset = NTFS30UpdateSequenceArrayOffset;
            }
            else
            {
                updateSequenceArrayOffset = NTFS31UpdateSequenceArrayOffset;
            }

            MultiSectorHeader multiSectorHeader    = new MultiSectorHeader(ValidSignature, updateSequenceArrayOffset, updateSequenceArraySize);
            ushort            firstAttributeOffset = GetFirstAttributeOffset(bytesPerFileRecordSegment, minorNTFSVersion);

            byte[] buffer = new byte[bytesPerFileRecordSegment];
            multiSectorHeader.WriteBytes(buffer, 0x00);
            LittleEndianWriter.WriteUInt64(buffer, 0x08, LogFileSequenceNumber);
            LittleEndianWriter.WriteUInt16(buffer, 0x10, m_sequenceNumber);
            LittleEndianWriter.WriteUInt16(buffer, 0x12, ReferenceCount);
            LittleEndianWriter.WriteUInt16(buffer, 0x14, firstAttributeOffset);
            LittleEndianWriter.WriteUInt16(buffer, 0x16, (ushort)m_flags);

            LittleEndianWriter.WriteInt32(buffer, 0x1C, bytesPerFileRecordSegment);
            m_baseFileRecordSegment.WriteBytes(buffer, 0x20);
            LittleEndianWriter.WriteUInt16(buffer, 0x28, NextAttributeInstance);
            if (minorNTFSVersion == 1)
            {
                LittleEndianWriter.WriteUInt32(buffer, 0x2C, (uint)m_segmentNumber);
            }

            // write attributes
            int position = firstAttributeOffset;

            foreach (AttributeRecord attribute in m_immediateAttributes)
            {
                byte[] attributeBytes = attribute.GetBytes();
                ByteWriter.WriteBytes(buffer, position, attributeBytes);
                position += attributeBytes.Length;
            }

            byte[] marker = GetEndMarker();
            ByteWriter.WriteBytes(buffer, position, marker);
            position += marker.Length;
            position += 4; // record (length) is aligned to 8-byte boundary

            uint segmentLength = (uint)position;

            LittleEndianWriter.WriteUInt32(buffer, 0x18, segmentLength);

            // Write UpdateSequenceNumber and UpdateSequenceReplacementData
            List <byte[]> updateSequenceReplacementData = MultiSectorHelper.EncodeSegmentBuffer(buffer, 0, bytesPerFileRecordSegment, UpdateSequenceNumber);

            MultiSectorHelper.WriteUpdateSequenceArray(buffer, updateSequenceArrayOffset, updateSequenceArraySize, UpdateSequenceNumber, updateSequenceReplacementData);
            return(buffer);
        }
Example #6
0
        public FileRecordSegment(byte[] buffer, int offset, int bytesPerSector, long segmentNumber)
        {
            Signature = ByteReader.ReadAnsiString(buffer, offset + 0x00, 4);

            ushort updateSequenceArrayOffset = LittleEndianConverter.ToUInt16(buffer, offset + 0x04);
            ushort updateSequenceArraySize   = LittleEndianConverter.ToUInt16(buffer, offset + 0x06);

            LogFileSequenceNumber = LittleEndianConverter.ToUInt64(buffer, offset + 0x08);
            SequenceNumber        = LittleEndianConverter.ToUInt16(buffer, offset + 0x10);
            HardLinkCount         = LittleEndianConverter.ToUInt16(buffer, offset + 0x12);
            ushort firstAttributeOffset = LittleEndianConverter.ToUInt16(buffer, offset + 0x14);

            m_flags = (FileRecordFlags)LittleEndianConverter.ToUInt16(buffer, offset + 0x16);
            uint segmentRealSize      = LittleEndianConverter.ToUInt32(buffer, offset + 0x18);
            uint segmentAllocatedSize = LittleEndianConverter.ToUInt32(buffer, offset + 0x1C);

            BaseFileRecordSegmentNumber = LittleEndianConverter.ToUInt64(buffer, offset + 0x20);
            NextAttributeId             = LittleEndianConverter.ToUInt16(buffer, offset + 0x28);
            // 2 zeros - padding
            MftSegmentNumberXP = LittleEndianConverter.ToUInt32(buffer, offset + 0x2C);

            // There is an UpdateSequenceNumber for the FileRecordSegment,
            // and an entry in the UpdateSequenceArray for each sector of the record
            // The last two bytes of each sector contains this entry for integrity-check purposes
            int position = offset + updateSequenceArrayOffset;

            UpdateSequenceNumber = LittleEndianConverter.ToUInt16(buffer, position);
            position            += 2;
            // This stores the data that was supposed to be placed at the end of each sector, and was replaced with an UpdateSequenceNumber
            List <byte[]> updateSequenceReplacementData = new List <byte[]>();

            for (int index = 0; index < updateSequenceArraySize - 1; index++)
            {
                byte[] endOfSectorBytes = new byte[2];
                endOfSectorBytes[0] = buffer[position + 0];
                endOfSectorBytes[1] = buffer[position + 1];
                updateSequenceReplacementData.Add(endOfSectorBytes);
                position += 2;
            }

            MultiSectorHelper.DecodeSegmentBuffer(buffer, offset, UpdateSequenceNumber, updateSequenceReplacementData);

            // read attributes
            position = offset + firstAttributeOffset;
            while (!IsEndMarker(buffer, position))
            {
                AttributeRecord attribute = AttributeRecord.FromBytes(buffer, position);

                m_immediateAttributes.Add(attribute);
                position += (int)attribute.StoredRecordLength;
                if (position > buffer.Length)
                {
                    throw new InvalidDataException("Improper attribute length");
                }
            }

            m_mftSegmentNumber = segmentNumber;
        }
        /// <summary>
        /// This method is used to read the record segment(s) of the MFT itself.
        /// Only after strapping the MFT we can use GetFileRecordSegment which relies on the MFT file record.
        /// </summary>
        private FileRecordSegment ReadMftRecordSegment(long mftStartLCN, long segmentNumber)
        {
            long sectorIndex = mftStartLCN * m_volume.SectorsPerCluster + segmentNumber * m_volume.SectorsPerFileRecordSegment;

            byte[] segmentBytes = m_volume.ReadSectors(sectorIndex, m_volume.SectorsPerFileRecordSegment, ContentType.MftData);
            MultiSectorHelper.RevertUsaProtection(segmentBytes, 0);
            FileRecordSegment result = new FileRecordSegment(segmentBytes, 0, segmentNumber);

            return(result);
        }
Example #8
0
        private IndexRecord ReadIndexRecord(long subnodeVBN)
        {
            long sectorIndex = ConvertToSectorIndex(subnodeVBN);

            byte[] recordBytes = m_indexAllocationData.ReadSectors(sectorIndex, this.SectorsPerIndexRecord);
            MultiSectorHelper.RevertUsaProtection(recordBytes, 0);
            IndexRecord record = new IndexRecord(recordBytes, 0);

            return(record);
        }
Example #9
0
        private LfsRestartPage ReadRestartPage()
        {
            byte[] pageBytes      = ReadData(0, Volume.BytesPerSector);
            uint   systemPageSize = LfsRestartPage.GetSystemPageSize(pageBytes, 0);
            int    bytesToRead    = (int)systemPageSize - pageBytes.Length;

            if (bytesToRead > 0)
            {
                byte[] temp = ReadData((ulong)pageBytes.Length, bytesToRead);
                pageBytes = ByteUtils.Concatenate(pageBytes, temp);
            }
            MultiSectorHelper.RevertUsaProtection(pageBytes, 0);
            m_restartPage = new LfsRestartPage(pageBytes, 0);
            return(m_restartPage);
        }
Example #10
0
        public IndexRecord(byte[] buffer, int offset)
        {
            Signature = ByteReader.ReadAnsiString(buffer, offset + 0x00, 4);
            if (Signature != ValidSignature)
            {
                throw new InvalidDataException("Invalid INDX record signature");
            }
            ushort updateSequenceArrayOffset = LittleEndianConverter.ToUInt16(buffer, offset + 0x04);
            ushort updateSequenceArraySize   = LittleEndianConverter.ToUInt16(buffer, offset + 0x06);

            LogFileSequenceNumber = LittleEndianConverter.ToUInt64(buffer, offset + 0x08);
            RecordVCN             = LittleEndianConverter.ToUInt64(buffer, offset + 0x10);
            EntriesOffset         = LittleEndianConverter.ToUInt32(buffer, offset + 0x18);
            IndexLength           = LittleEndianConverter.ToUInt32(buffer, offset + 0x1C);
            AllocatedLength       = LittleEndianConverter.ToUInt32(buffer, offset + 0x20);
            HasChildren           = ByteReader.ReadByte(buffer, offset + 0x24) > 0;

            int position = offset + updateSequenceArrayOffset;

            UpdateSequenceNumber = LittleEndianConverter.ToUInt16(buffer, position);
            position            += 2;
            List <byte[]> updateSequenceReplacementData = new List <byte[]>();

            for (int index = 0; index < updateSequenceArraySize - 1; index++)
            {
                byte[] endOfSectorBytes = new byte[2];
                endOfSectorBytes[0] = buffer[position + 0];
                endOfSectorBytes[1] = buffer[position + 1];
                updateSequenceReplacementData.Add(endOfSectorBytes);
                position += 2;
            }

            MultiSectorHelper.DecodeSegmentBuffer(buffer, offset, UpdateSequenceNumber, updateSequenceReplacementData);

            position = 0x18 + (int)EntriesOffset;
            if (HasChildren)
            {
                IndexNode node = new IndexNode(buffer, position);
                IndexEntries = node.Entries;
            }
            else
            {
                FileNameIndexLeafNode leaf = new FileNameIndexLeafNode(buffer, position);
                FileNameEntries = leaf.Entries;
            }
        }
Example #11
0
        private LfsRecordPage ReadPageFromFile(ulong pageOffset)
        {
            if (m_restartPage == null)
            {
                m_restartPage = ReadRestartPage();
            }

            byte[] pageBytes     = ReadData(pageOffset, (int)m_restartPage.LogPageSize);
            uint   pageSignature = LittleEndianConverter.ToUInt32(pageBytes, 0);

            if (pageSignature == LfsRecordPage.UninitializedPageSignature)
            {
                return(null);
            }
            MultiSectorHelper.RevertUsaProtection(pageBytes, 0);
            return(new LfsRecordPage(pageBytes, m_restartPage.LogRestartArea.LogPageDataOffset));
        }
Example #12
0
        public FileRecordSegment(byte[] buffer, int offset, long segmentNumber)
        {
            MultiSectorHeader multiSectorHeader = new MultiSectorHeader(buffer, offset + 0x00);

            if (multiSectorHeader.Signature != ValidSignature)
            {
                throw new InvalidDataException("Invalid FILE record signature");
            }
            LogFileSequenceNumber = LittleEndianConverter.ToUInt64(buffer, offset + 0x08);
            m_sequenceNumber      = LittleEndianConverter.ToUInt16(buffer, offset + 0x10);
            ReferenceCount        = LittleEndianConverter.ToUInt16(buffer, offset + 0x12);
            ushort firstAttributeOffset = LittleEndianConverter.ToUInt16(buffer, offset + 0x14);

            m_flags = (FileRecordFlags)LittleEndianConverter.ToUInt16(buffer, offset + 0x16);
            uint segmentLength          = LittleEndianConverter.ToUInt32(buffer, offset + 0x18);
            uint segmentAllocatedLength = LittleEndianConverter.ToUInt32(buffer, offset + 0x1C);

            m_baseFileRecordSegment = new MftSegmentReference(buffer, offset + 0x20);
            NextAttributeInstance   = LittleEndianConverter.ToUInt16(buffer, offset + 0x28);
            // 2 bytes padding
            m_segmentNumberOnDisk = LittleEndianConverter.ToUInt32(buffer, offset + 0x2C);

            int           position = offset + multiSectorHeader.UpdateSequenceArrayOffset;
            List <byte[]> updateSequenceReplacementData = MultiSectorHelper.ReadUpdateSequenceArray(buffer, position, multiSectorHeader.UpdateSequenceArraySize, out UpdateSequenceNumber);

            MultiSectorHelper.DecodeSegmentBuffer(buffer, offset, UpdateSequenceNumber, updateSequenceReplacementData);

            // Read attributes
            position = offset + firstAttributeOffset;
            while (!IsEndMarker(buffer, position))
            {
                AttributeRecord attribute = AttributeRecord.FromBytes(buffer, position);

                m_immediateAttributes.Add(attribute);
                position += (int)attribute.RecordLengthOnDisk;
                if (position > buffer.Length)
                {
                    throw new InvalidDataException("Invalid attribute length");
                }
            }

            m_segmentNumber = segmentNumber;
        }
Example #13
0
        private FileRecordSegment GetFileRecordSegment(long segmentNumber)
        {
            NTFSBootRecord bootRecord = m_volume.BootRecord;

            // Note: File record always start at the beginning of a sector
            // Note: Record can span multiple clusters, or alternatively, several records can be stored in the same cluster
            long firstSectorIndex = segmentNumber * m_volume.SectorsPerFileRecordSegment;

            byte[] segmentBytes = m_mftFile.Data.ReadSectors(firstSectorIndex, m_volume.SectorsPerFileRecordSegment);

            if (FileRecordSegment.ContainsFileRecordSegment(segmentBytes))
            {
                MultiSectorHelper.RevertUsaProtection(segmentBytes, 0);
                FileRecordSegment recordSegment = new FileRecordSegment(segmentBytes, 0, segmentNumber);
                return(recordSegment);
            }
            else
            {
                return(null);
            }
        }
Example #14
0
        public IndexRecord(byte[] buffer, int offset)
        {
            MultiSectorHeader multiSectorHeader = new MultiSectorHeader(buffer, offset + 0x00);

            if (multiSectorHeader.Signature != ValidSignature)
            {
                throw new InvalidDataException("Invalid INDX record signature");
            }
            LogFileSequenceNumber = LittleEndianConverter.ToUInt64(buffer, offset + 0x08);
            RecordVBN             = (long)LittleEndianConverter.ToUInt64(buffer, offset + 0x10);
            m_indexHeader         = new IndexHeader(buffer, offset + 0x18);

            int           position = offset + multiSectorHeader.UpdateSequenceArrayOffset;
            List <byte[]> updateSequenceReplacementData = MultiSectorHelper.ReadUpdateSequenceArray(buffer, position, multiSectorHeader.UpdateSequenceArraySize, out UpdateSequenceNumber);

            MultiSectorHelper.DecodeSegmentBuffer(buffer, offset, UpdateSequenceNumber, updateSequenceReplacementData);

            int entriesOffset = 0x18 + (int)m_indexHeader.EntriesOffset;

            IndexEntries = IndexEntry.ReadIndexEntries(buffer, entriesOffset);
        }
Example #15
0
        public LogRecordPage(byte[] buffer, int offset, int dataOffset)
        {
            MultiSectorHeader multiSectorHeader = new MultiSectorHeader(buffer, offset + 0x00);

            if (multiSectorHeader.Signature != ValidSignature)
            {
                throw new InvalidDataException("Invalid RCRD record signature");
            }
            LastLsnOrFileOffset = LittleEndianConverter.ToUInt64(buffer, offset + 0x08);
            Flags        = (LogRecordPageFlags)LittleEndianConverter.ToUInt32(buffer, offset + 0x10);
            PageCount    = LittleEndianConverter.ToUInt16(buffer, offset + 0x14);
            PagePosition = LittleEndianConverter.ToUInt16(buffer, offset + 0x16);
            ushort nextRecordOffset = LittleEndianConverter.ToUInt16(buffer, offset + 0x18);

            LastEndLsn = LittleEndianConverter.ToUInt64(buffer, offset + 0x20);
            int           position = offset + multiSectorHeader.UpdateSequenceArrayOffset;
            List <byte[]> updateSequenceReplacementData = MultiSectorHelper.ReadUpdateSequenceArray(buffer, position, multiSectorHeader.UpdateSequenceArraySize, out UpdateSequenceNumber);

            MultiSectorHelper.DecodeSegmentBuffer(buffer, offset, UpdateSequenceNumber, updateSequenceReplacementData);
            Data = ByteReader.ReadBytes(buffer, offset + dataOffset, (int)(nextRecordOffset - dataOffset));
        }
Example #16
0
        public LogRestartPage(byte[] buffer, int offset)
        {
            MultiSectorHeader multiSectorHeader = new MultiSectorHeader(buffer, offset + 0x00);

            if (multiSectorHeader.Signature != ValidSignature)
            {
                throw new InvalidDataException("Invalid RSTR record signature");
            }
            ChkDskLsn        = LittleEndianConverter.ToUInt64(buffer, offset + 0x08);
            m_systemPageSize = LittleEndianConverter.ToUInt32(buffer, offset + 0x10);
            LogPageSize      = LittleEndianConverter.ToUInt32(buffer, offset + 0x14);
            ushort restartOffset = LittleEndianConverter.ToUInt16(buffer, offset + 0x18);

            MinorVersion = LittleEndianConverter.ToInt16(buffer, offset + 0x1A);
            MajorVersion = LittleEndianConverter.ToInt16(buffer, offset + 0x1C);
            int           position = offset + multiSectorHeader.UpdateSequenceArrayOffset;
            List <byte[]> updateSequenceReplacementData = MultiSectorHelper.ReadUpdateSequenceArray(buffer, position, multiSectorHeader.UpdateSequenceArraySize, out UpdateSequenceNumber);

            MultiSectorHelper.DecodeSegmentBuffer(buffer, offset, UpdateSequenceNumber, updateSequenceReplacementData);
            LogRestartArea = new LogRestartArea(buffer, offset + restartOffset);
        }
Example #17
0
        public byte[] GetBytes(int bytesPerLogPage, int dataOffset)
        {
            int               strideCount             = bytesPerLogPage / MultiSectorHelper.BytesPerStride;
            ushort            updateSequenceArraySize = (ushort)(1 + strideCount);
            MultiSectorHeader multiSectorHeader       = new MultiSectorHeader(ValidSignature, UpdateSequenceArrayOffset, updateSequenceArraySize);
            ushort            nextRecordOffset        = (ushort)(dataOffset + Data.Length);

            byte[] buffer = new byte[bytesPerLogPage];
            multiSectorHeader.WriteBytes(buffer, 0);
            LittleEndianWriter.WriteUInt64(buffer, 0x08, LastLsnOrFileOffset);
            LittleEndianWriter.WriteUInt32(buffer, 0x10, (uint)Flags);
            LittleEndianWriter.WriteUInt16(buffer, 0x14, PageCount);
            LittleEndianWriter.WriteUInt16(buffer, 0x16, PagePosition);
            LittleEndianWriter.WriteUInt16(buffer, 0x18, nextRecordOffset);
            LittleEndianWriter.WriteUInt64(buffer, 0x20, LastEndLsn);
            ByteWriter.WriteBytes(buffer, dataOffset, Data);

            // Write UpdateSequenceNumber and UpdateSequenceReplacementData
            List <byte[]> updateSequenceReplacementData = MultiSectorHelper.EncodeSegmentBuffer(buffer, 0, bytesPerLogPage, UpdateSequenceNumber);

            MultiSectorHelper.WriteUpdateSequenceArray(buffer, UpdateSequenceArrayOffset, updateSequenceArraySize, UpdateSequenceNumber, updateSequenceReplacementData);
            return(buffer);
        }
        public byte[] GetBytes(int bytesPerLogPage, bool applyUsaProtection)
        {
            int               strideCount             = bytesPerLogPage / MultiSectorHelper.BytesPerStride;
            ushort            updateSequenceArraySize = (ushort)(1 + strideCount);
            MultiSectorHeader multiSectorHeader       = new MultiSectorHeader(ValidSignature, UpdateSequenceArrayOffset, updateSequenceArraySize);

            byte[] buffer = new byte[bytesPerLogPage];
            multiSectorHeader.WriteBytes(buffer, 0);
            LittleEndianWriter.WriteUInt64(buffer, 0x08, LastLsnOrFileOffset);
            LittleEndianWriter.WriteUInt32(buffer, 0x10, (uint)Flags);
            LittleEndianWriter.WriteUInt16(buffer, 0x14, PageCount);
            LittleEndianWriter.WriteUInt16(buffer, 0x16, PagePosition);
            LittleEndianWriter.WriteUInt16(buffer, 0x18, NextRecordOffset);
            LittleEndianWriter.WriteUInt64(buffer, 0x20, LastEndLsn);
            LittleEndianWriter.WriteUInt16(buffer, UpdateSequenceArrayOffset, UpdateSequenceNumber);
            ByteWriter.WriteBytes(buffer, m_dataOffset, Data);

            if (applyUsaProtection)
            {
                MultiSectorHelper.ApplyUsaProtection(buffer, 0);
            }
            return(buffer);
        }
Example #19
0
        public byte[] GetBytes(int bytesPerSystemPage)
        {
            m_systemPageSize = (uint)bytesPerSystemPage;
            int               strideCount             = bytesPerSystemPage / MultiSectorHelper.BytesPerStride;
            ushort            updateSequenceArraySize = (ushort)(1 + strideCount);
            MultiSectorHeader multiSectorHeader       = new MultiSectorHeader(ValidSignature, UpdateSequenceArrayOffset, updateSequenceArraySize);
            int               restartOffset           = (int)Math.Ceiling((double)(UpdateSequenceArrayOffset + updateSequenceArraySize * 2) / 8) * 8;

            byte[] buffer = new byte[bytesPerSystemPage];
            multiSectorHeader.WriteBytes(buffer, 0);
            LittleEndianWriter.WriteUInt64(buffer, 0x08, ChkDskLsn);
            LittleEndianWriter.WriteUInt32(buffer, 0x10, m_systemPageSize);
            LittleEndianWriter.WriteUInt32(buffer, 0x14, LogPageSize);
            LittleEndianWriter.WriteUInt16(buffer, 0x18, (ushort)restartOffset);
            LittleEndianWriter.WriteInt16(buffer, 0x1A, MinorVersion);
            LittleEndianWriter.WriteInt16(buffer, 0x1C, MajorVersion);
            LogRestartArea.WriteBytes(buffer, restartOffset);

            // Write UpdateSequenceNumber and UpdateSequenceReplacementData
            List <byte[]> updateSequenceReplacementData = MultiSectorHelper.EncodeSegmentBuffer(buffer, 0, bytesPerSystemPage, UpdateSequenceNumber);

            MultiSectorHelper.WriteUpdateSequenceArray(buffer, UpdateSequenceArrayOffset, updateSequenceArraySize, UpdateSequenceNumber, updateSequenceReplacementData);
            return(buffer);
        }
Example #20
0
        /// <param name="segmentLength">This refers to the maximum length of FileRecord as defined in the Volume's BootRecord</param>
        public byte[] GetBytes(int segmentLength, int bytesPerCluster, ushort minorNTFSVersion)
        {
            int    strideCount             = segmentLength / MultiSectorHelper.BytesPerStride;
            ushort updateSequenceArraySize = (ushort)(1 + strideCount);

            ushort updateSequenceArrayOffset;

            if (minorNTFSVersion == 0)
            {
                updateSequenceArrayOffset = NTFS30UpdateSequenceArrayOffset;
            }
            else
            {
                updateSequenceArrayOffset = NTFS31UpdateSequenceArrayOffset;
            }

            ushort firstAttributeOffset = GetFirstAttributeOffset(segmentLength, minorNTFSVersion);

            byte[] buffer = new byte[segmentLength];
            ByteWriter.WriteAnsiString(buffer, 0, Signature, 4);
            LittleEndianWriter.WriteUInt16(buffer, 0x04, updateSequenceArrayOffset);
            LittleEndianWriter.WriteUInt16(buffer, 0x06, updateSequenceArraySize);
            LittleEndianWriter.WriteUInt64(buffer, 0x08, LogFileSequenceNumber);
            LittleEndianWriter.WriteUInt16(buffer, 0x10, SequenceNumber);
            LittleEndianWriter.WriteUInt16(buffer, 0x12, HardLinkCount);
            LittleEndianWriter.WriteUInt16(buffer, 0x14, firstAttributeOffset);
            LittleEndianWriter.WriteUInt16(buffer, 0x16, (ushort)m_flags);

            LittleEndianWriter.WriteInt32(buffer, 0x1C, segmentLength);
            LittleEndianWriter.WriteUInt64(buffer, 0x20, BaseFileRecordSegmentNumber);
            LittleEndianWriter.WriteUInt16(buffer, 0x28, NextAttributeId);
            if (minorNTFSVersion == 1)
            {
                LittleEndianWriter.WriteUInt32(buffer, 0x2C, MftSegmentNumberXP);
            }

            // write attributes
            int position = firstAttributeOffset;

            foreach (AttributeRecord attribute in m_immediateAttributes)
            {
                byte[] attributeBytes = attribute.GetBytes(bytesPerCluster);
                ByteWriter.WriteBytes(buffer, position, attributeBytes);
                position += attributeBytes.Length;
            }

            byte[] marker = GetEndMarker();
            ByteWriter.WriteBytes(buffer, position, marker);
            position += marker.Length;
            position += 4; // record (length) is aligned to 8-byte boundary

            uint segmentRealSize = (uint)position;

            LittleEndianWriter.WriteUInt32(buffer, 0x18, segmentRealSize);

            // write UpdateSequenceNumber and UpdateSequenceReplacementData
            List <byte[]> updateSequenceReplacementData = MultiSectorHelper.EncodeSegmentBuffer(buffer, 0, segmentLength, UpdateSequenceNumber);

            position = updateSequenceArrayOffset;
            LittleEndianWriter.WriteUInt16(buffer, position, UpdateSequenceNumber);
            position += 2;
            foreach (byte[] endOfSectorBytes in updateSequenceReplacementData)
            {
                ByteWriter.WriteBytes(buffer, position, endOfSectorBytes);
                position += 2;
            }

            return(buffer);
        }
 private FileRecordSegment GetFileRecordSegment(long segmentNumber)
 {
     byte[] segmentBytes = GetFileRecordSegmentBytes(segmentNumber);
     MultiSectorHelper.RevertUsaProtection(segmentBytes, 0);
     return(new FileRecordSegment(segmentBytes, 0, segmentNumber));
 }
Example #22
0
        public byte[] GetBytes(int bytesPerFileRecordSegment, ushort minorNTFSVersion, bool applyUsaProtection)
        {
            int    strideCount             = bytesPerFileRecordSegment / MultiSectorHelper.BytesPerStride;
            ushort updateSequenceArraySize = (ushort)(1 + strideCount);

            ushort updateSequenceArrayOffset;

            if (minorNTFSVersion == 0)
            {
                updateSequenceArrayOffset = NTFS30UpdateSequenceArrayOffset;
            }
            else
            {
                updateSequenceArrayOffset = NTFS31UpdateSequenceArrayOffset;
            }

            MultiSectorHeader multiSectorHeader    = new MultiSectorHeader(ValidSignature, updateSequenceArrayOffset, updateSequenceArraySize);
            ushort            firstAttributeOffset = GetFirstAttributeOffset(bytesPerFileRecordSegment, minorNTFSVersion);

            int length = applyUsaProtection ? bytesPerFileRecordSegment : GetNumberOfBytesInUse(bytesPerFileRecordSegment, minorNTFSVersion);

            byte[] buffer = new byte[length];
            multiSectorHeader.WriteBytes(buffer, 0x00);
            LittleEndianWriter.WriteUInt64(buffer, 0x08, LogFileSequenceNumber);
            LittleEndianWriter.WriteUInt16(buffer, 0x10, m_sequenceNumber);
            LittleEndianWriter.WriteUInt16(buffer, 0x12, ReferenceCount);
            LittleEndianWriter.WriteUInt16(buffer, 0x14, firstAttributeOffset);
            LittleEndianWriter.WriteUInt16(buffer, 0x16, (ushort)m_flags);

            LittleEndianWriter.WriteInt32(buffer, 0x1C, bytesPerFileRecordSegment);
            m_baseFileRecordSegment.WriteBytes(buffer, 0x20);
            LittleEndianWriter.WriteUInt16(buffer, 0x28, NextAttributeInstance);
            if (minorNTFSVersion == 1)
            {
                LittleEndianWriter.WriteUInt32(buffer, 0x2C, (uint)m_segmentNumber);
            }
            LittleEndianWriter.WriteUInt32(buffer, updateSequenceArrayOffset, UpdateSequenceNumber);

            // write attributes
            int position = firstAttributeOffset;

            foreach (AttributeRecord attribute in m_immediateAttributes)
            {
                byte[] attributeBytes = attribute.GetBytes();
                ByteWriter.WriteBytes(buffer, position, attributeBytes);
                position += attributeBytes.Length;
            }

            LittleEndianWriter.WriteUInt32(buffer, position, AttributesEndMarker);
            position += AttributesEndMarkerLength; // End marker + alignment to 8-byte boundary

            uint segmentLength = (uint)position;

            LittleEndianWriter.WriteUInt32(buffer, 0x18, segmentLength);

            if (applyUsaProtection)
            {
                MultiSectorHelper.ApplyUsaProtection(buffer, 0);
            }
            return(buffer);
        }