/// <summary> /// Reads a metadata directory from an input stream. /// </summary> /// <param name="context">The reader context.</param> /// <param name="directoryReader">The input stream containing the metadata directory.</param> /// <exception cref="ArgumentNullException">Occurs when any of the arguments are <c>null</c>.</exception> /// <exception cref="NotSupportedException">Occurs when an unsupported metadata directory format was encountered.</exception> /// <exception cref="BadImageFormatException">Occurs when the metadata directory header is invalid.</exception> public SerializedMetadata(PEReaderContext context, IBinaryStreamReader directoryReader) { if (directoryReader == null) { throw new ArgumentNullException(nameof(directoryReader)); } _context = context ?? throw new ArgumentNullException(nameof(context)); _streamContentsReader = directoryReader.Fork(); var signature = (MetadataSignature)directoryReader.ReadUInt32(); switch (signature) { case MetadataSignature.Bsjb: // BSJB header is the default header. break; case MetadataSignature.Moc: _context.NotSupported("Old +MOC metadata header format is not supported."); return; default: _context.BadImage($"Invalid metadata header ({(uint) signature:X8})."); return; } MajorVersion = directoryReader.ReadUInt16(); MinorVersion = directoryReader.ReadUInt16(); Reserved = directoryReader.ReadUInt32(); int versionLength = directoryReader.ReadInt32(); if (!directoryReader.CanRead(versionLength)) { _context.BadImage($"Invalid version length in metadata header ({versionLength.ToString()} characters)."); return; } var versionBytes = new byte[versionLength]; directoryReader.ReadBytes(versionBytes, 0, versionBytes.Length); VersionString = Encoding.ASCII.GetString(versionBytes); Flags = directoryReader.ReadUInt16(); _numberOfStreams = directoryReader.ReadInt16(); _streamEntriesReader = directoryReader.Fork(); }
/// <summary> /// Reads a metadata directory from an input stream. /// </summary> /// <param name="reader">The input stream.</param> /// <param name="metadataStreamReader"></param> /// <exception cref="ArgumentNullException">Occurs when any of the arguments are <c>null</c>.</exception> /// <exception cref="NotSupportedException">Occurs when an unsupported metadata directory format was encountered.</exception> /// <exception cref="BadImageFormatException">Occurs when the metadata directory header is invalid.</exception> public SerializedMetadata(IBinaryStreamReader reader, IMetadataStreamReader metadataStreamReader) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } _metadataStreamReader = metadataStreamReader; _streamContentsReader = reader.Fork(); var signature = (MetadataSignature)reader.ReadUInt32(); switch (signature) { case MetadataSignature.Bsjb: // BSJB header is the default header. break; case MetadataSignature.Moc: throw new NotSupportedException("Old +MOC metadata header format is not supported."); default: throw new BadImageFormatException($"Invalid metadata header ({(uint) signature:X8})."); } MajorVersion = reader.ReadUInt16(); MinorVersion = reader.ReadUInt16(); Reserved = reader.ReadUInt32(); int versionLength = reader.ReadInt32(); if (!reader.CanRead(versionLength)) { throw new BadImageFormatException($"Invalid version length in metadata header ({versionLength} characters)."); } var versionBytes = new byte[versionLength]; reader.ReadBytes(versionBytes, 0, versionBytes.Length); VersionString = Encoding.ASCII.GetString(versionBytes); Flags = reader.ReadUInt16(); _numberOfStreams = reader.ReadInt16(); _streamEntriesReader = reader.Fork(); }
/// <inheritdoc /> protected override IList <X64RuntimeFunction> GetEntries() { var reader = _reader.Fork(); var result = new List <X64RuntimeFunction>(); while (reader.CanRead(X64RuntimeFunction.EntrySize)) { result.Add(X64RuntimeFunction.FromReader(_context, reader)); } return(result); }
/// <inheritdoc /> protected override IList <IMetadataStream> GetStreams() { if (_numberOfStreams == 0) { return(base.GetStreams()); } return(new MetadataStreamList( _streamContentsReader.Fork(), _streamEntriesReader.Fork(), _numberOfStreams, _metadataStreamReader)); }
/// <inheritdoc /> protected override IList <TRow> GetRows() { var result = new List <TRow>(); var reader = _reader.Fork(); for (int i = 0; i < _rowCount; i++) { result.Add(_readRow(reader, _originalLayout)); } return(result); }
/// <inheritdoc /> protected override void Initialize() { var headers = new MetadataStreamHeader[_numberOfStreams]; for (int i = 0; i < _numberOfStreams; i++) { headers[i] = MetadataStreamHeader.FromReader(_entriesReader); } for (int i = 0; i < _numberOfStreams; i++) { var header = headers[i]; var streamReader = _metadataReader.Fork(_metadataReader.FileOffset + header.Offset, headers[i].Size); Items.Add(_metadataStreamReader.ReadStream(header, streamReader)); } }
/// <summary> /// Reads a PE file from the provided input stream. /// </summary> /// <param name="reader">The input stream to read from.</param> /// <returns>The PE file that was read.</returns> /// <exception cref="BadImageFormatException">Occurs when the file does not follow the PE file format.</exception> public static PEFile FromReader(IBinaryStreamReader reader) { // DOS header. var dosHeader = DosHeader.FromReader(reader); reader.FileOffset = dosHeader.NextHeaderOffset; uint signature = reader.ReadUInt32(); if (signature != ValidPESignature) { throw new BadImageFormatException(); } // Read NT headers. var peFile = new PEFile( dosHeader, FileHeader.FromReader(reader), OptionalHeader.FromReader(reader)); // Section headers. reader.FileOffset = peFile.OptionalHeader.FileOffset + peFile.FileHeader.SizeOfOptionalHeader; for (int i = 0; i < peFile.FileHeader.NumberOfSections; i++) { var header = SectionHeader.FromReader(reader); var contentsReader = reader.Fork(header.PointerToRawData, header.SizeOfRawData); var contents = DataSegment.FromReader(contentsReader); contents.UpdateOffsets(header.PointerToRawData, header.VirtualAddress); peFile.Sections.Add(new PESection(header, new VirtualSegment(contents, header.VirtualSize))); } // Data between section headers and sections. int extraSectionDataLength = (int)(peFile.OptionalHeader.SizeOfHeaders - reader.FileOffset); if (extraSectionDataLength != 0) { peFile.ExtraSectionData = DataSegment.FromReader(reader, extraSectionDataLength); } return(peFile); }
/// <summary> /// Forks the reader by creating a new instance of a binary stream reader, using the same data source, but a different address. /// </summary> /// <param name="reader">The reader to fork.</param> /// <param name="address">The address of the forked reader to start at.</param> /// <returns>A forked binary stream reader with the same data source, but a different address.</returns> public static IBinaryStreamReader Fork(this IBinaryStreamReader reader, uint address) { return(reader.Fork(address, reader.Length - (address - reader.StartPosition))); }
/// <summary> /// Forks the reader at th current position by creating a new instance of a binary stream reader, using the same data source. /// </summary> /// <param name="reader">The reader to fork.</param> /// <returns>A forked binary stream reader with the same data source.</returns> public static IBinaryStreamReader Fork(this IBinaryStreamReader reader) { uint address = reader.FileOffset; return(reader.Fork(address, reader.Length - (address - reader.StartPosition))); }
/// <summary> /// Forks the reader by creating a new instance of a binary stream reader, using the same data source, but a different address. /// </summary> /// <param name="reader">The reader to fork.</param> /// <param name="address">The address of the forked reader to start at.</param> /// <returns>A forked binary stream reader with the same data source, but a different address.</returns> public static IBinaryStreamReader Fork(this IBinaryStreamReader reader, ulong address) { return(reader.Fork(address, (uint)(reader.Length - (address - reader.StartOffset)))); }
/// <summary> /// Forks the reader at th current position by creating a new instance of a binary stream reader, using the same data source. /// </summary> /// <param name="reader">The reader to fork.</param> /// <returns>A forked binary stream reader with the same data source.</returns> public static IBinaryStreamReader Fork(this IBinaryStreamReader reader) { return(reader.Fork(reader.Offset, (uint)(reader.Length - reader.RelativeOffset))); }