/// <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());
        }
Ejemplo n.º 3
0
        /// <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);
        }
Ejemplo n.º 4
0
        /// <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();
        }
Ejemplo n.º 5
0
        /// <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.");
                }
            }
        }
Ejemplo n.º 6
0
        /// <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));
        }
Ejemplo n.º 8
0
        /// <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));
        }
Ejemplo n.º 10
0
        /// <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);
        }
Ejemplo n.º 11
0
        /// <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);
            }
        }