/// <inheritdoc /> protected override IDebugDataSegment GetContents() { if (_sizeOfData == 0) { return(null); } var reference = _context.File.GetReferenceToRva(_addressOfRawData); if (reference is null || !reference.CanRead) { _context.BadImage("Debug data entry contains an invalid RVA."); return(null); } var reader = reference.CreateReader(); if (_sizeOfData > reader.Length) { _context.BadImage("Debug data entry contains a too large size."); return(null); } reader.ChangeSize(_sizeOfData); return(_context.Parameters.DebugDataReader.ReadDebugData(_context, _type, reader)); }
/// <inheritdoc /> protected override string GetName() { if (!_context.File.TryCreateReaderAtRva(_nameRva, out var reader)) { _context.BadImage("Export directory contains an invalid name RVA."); return(null); } return(reader.ReadAsciiString()); }
/// <inheritdoc /> protected override IList <ImportedSymbol> GetSymbols() { var result = new OwnedCollection <IImportedModule, ImportedSymbol>(this); if (IsEmpty) { return(result); } bool is32Bit = _context.File.OptionalHeader.Magic == OptionalHeaderMagic.Pe32; (ulong ordinalMask, int pointerSize) = is32Bit ? (0x8000_0000ul, sizeof(uint)) : (0x8000_0000_0000_0000ul, sizeof(ulong)); if (!_context.File.TryCreateReaderAtRva(_lookupRva, out var lookupItemReader)) { _context.BadImage($"Imported module \"{Name}\" has an invalid import lookup thunk table RVA."); return(result); } while (true) { ImportedSymbol entry; ulong lookupItem = lookupItemReader.ReadNativeInt(is32Bit); if (lookupItem == 0) { break; } if ((lookupItem & ordinalMask) != 0) { entry = new ImportedSymbol((ushort)(lookupItem & 0xFFFF)); } else { uint hintNameRva = (uint)(lookupItem & 0xFFFFFFFF); if (!_context.File.TryCreateReaderAtRva(hintNameRva, out var reader)) { _context.BadImage($"Invalid Hint-Name RVA for import {Name}!#{result.Count.ToString()}."); entry = new ImportedSymbol(0, "<<<INVALID_NAME_RVA>>>"); } else { entry = new ImportedSymbol(reader.ReadUInt16(), reader.ReadAsciiString()); } } entry.AddressTableEntry = _context.File.GetReferenceToRva((uint)(_addressRva + result.Count * pointerSize)); result.Add(entry); } return(result); }
/// <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 module import entry from an input stream. /// </summary> /// <param name="context">The reader context.</param> /// <param name="reader">The input stream.</param> public SerializedImportedModule(PEReaderContext context, ref BinaryStreamReader reader) { if (!reader.IsValid) { throw new ArgumentNullException(nameof(reader)); } _context = context ?? throw new ArgumentNullException(nameof(context)); _lookupRva = reader.ReadUInt32(); TimeDateStamp = reader.ReadUInt32(); ForwarderChain = reader.ReadUInt32(); uint nameRva = reader.ReadUInt32(); _addressRva = reader.ReadUInt32(); if (nameRva != 0) { if (_context.File.TryCreateReaderAtRva(nameRva, out var nameReader)) { Name = nameReader.ReadAsciiString(); } else { _context.BadImage("Import module contains an invalid name RVA."); } } }
/// <inheritdoc /> protected override IList <IResourceEntry> GetEntries() { var result = new OwnedCollection <IResourceDirectory, IResourceEntry>(this); // Optimisation, check for invalid resource directory offset, and prevention of self loop: if (_namedEntries + _idEntries == 0 || _depth >= MaxDepth) { _context.BadImage($"Reached maximum recursion depth of {_depth} sub resource directories."); return(result); } uint baseRva = _context.File.OptionalHeader .GetDataDirectory(DataDirectoryIndex.ResourceDirectory) .VirtualAddress; // Create entries reader. uint entryListSize = (uint)((_namedEntries + _idEntries) * ResourceDirectoryEntry.EntrySize); if (!_context.File.TryCreateReaderAtRva(_entriesRva, entryListSize, out var entriesReader)) { _context.BadImage("Resource directory contains an invalid entry table RVA and/or entry count."); return(result); } for (int i = 0; i < _namedEntries + _idEntries; i++) { var rawEntry = new ResourceDirectoryEntry(_context, entriesReader); // Note: Even if creating the directory reader fails, we still want to include the directory entry // itself. In such a case, we expose the directory as an empty directory. This is why the // following if statement does not dictate the creation of the data entry or not. if (!_context.File.TryCreateReaderAtRva(baseRva + rawEntry.DataOrSubDirOffset, out var entryReader)) { _context.BadImage($"Resource directory entry {i.ToString()} has an invalid data offset."); } result.Add(rawEntry.IsSubDirectory ? (IResourceEntry) new SerializedResourceDirectory(_context, rawEntry, entryReader, _depth + 1) : new SerializedResourceData(_context, rawEntry, entryReader)); } return(result); }
/// <inheritdoc /> protected override ISegment GetContents() { if (!_context.File.TryCreateReaderAtRva(_contentsRva, _contentsSize, out var reader)) { _context.BadImage("Resource data entry contains an invalid RVA and/or size."); return(null); } return(DataSegment.FromReader(ref reader)); }
/// <inheritdoc /> protected override void Initialize() { if (!_context.File.TryCreateDataDirectoryReader(_relocDirectory, out var reader)) { _context.BadImage("Invalid base relocation data directory RVA and/or size."); return; } while (reader.Offset < reader.StartOffset + reader.Length) { ReadBlock(reader); } }
/// <inheritdoc /> protected override IMetadata GetMetadata() { if (!_metadataDirectory.IsPresentInPE) { return(null); } if (!_context.File.TryCreateDataDirectoryReader(_metadataDirectory, out var directoryReader)) { _context.BadImage(".NET data directory contains an invalid metadata directory RVA and/or size."); return(null); } return(new SerializedMetadata(_context, ref directoryReader)); }
/// <summary> /// Initializes a new instance of <see cref="RsdsDataSegment"/> /// </summary> /// <param name="context">Context for the reader</param> /// <param name="reader">The input stream to read from.</param> /// <returns></returns> public new static RsdsDataSegment FromReader(PEReaderContext context, IBinaryStreamReader reader) { if (reader.Length < RsdsExpectedDataSize) { context.BadImage("RSDS Data was shorter than the minimal expected length"); return(null); } var result = new RsdsDataSegment(); byte[] buffer = new byte[16]; reader.ReadBytes(buffer, 0, 16); result.Guid = new Guid(buffer); result.Age = reader.ReadUInt32(); result.Path = Encoding.UTF8.GetString(reader.ReadBytesUntil(0x00)); return(result); }
/// <inheritdoc /> protected override void Initialize() { if (!_context.File.TryCreateDataDirectoryReader(_dataDirectory, out var reader)) { _context.BadImage("Invalid import data directory RVA and/or size."); return; } while (true) { var entry = ImportedModule.FromReader(_context, reader); if (entry == null) { break; } Items.Add(entry); } }