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); }
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); }
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); }
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); }
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); }
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); }
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; } }
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)); }
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; }
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); } }
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); }
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)); }
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); }
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); }
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); }
/// <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)); }
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); }