internal static unsafe DelayImportModuleTable Load(IBinaryAccessor accessor, PEImage image)
        {
            DelayImportTableHeader header;

            fixed(byte *pBuff = accessor.ReadBytes(sizeof(DelayImportTableHeader)))
            {
                header = *(DelayImportTableHeader *)pBuff;
            }

            if (header.Name == 0 || header.DelayImportAddressTable == 0)
            {
                return(null);
            }

            // Save position
            long position = accessor.Position;

            var module = new DelayImportModuleTable();

            module._moduleHandleRVA = header.ModuleHandle;

            // Dll name
            accessor.Position = image.ResolvePositionToSectionData(header.Name);
            module._dllName   = accessor.ReadNullTerminatedString(Encoding.ASCII);

            // DelayImportAddressTable
            accessor.Position = image.ResolvePositionToSectionData(header.DelayImportAddressTable);

            var funcRVAList = new List <uint>();

            while (true)
            {
                uint funcRVA = accessor.ReadUInt32();
                if (funcRVA == 0)
                {
                    break;
                }

                funcRVAList.Add(funcRVA);
            }

            accessor.Position = image.ResolvePositionToSectionData(header.DelayImportNameTable);

            if (image.Is32Bits)
            {
                var entryDataList = new List <uint>();
                for (int i = 0; i < funcRVAList.Count; i++)
                {
                    entryDataList.Add(accessor.ReadUInt32());
                }

                for (int i = 0; i < funcRVAList.Count; i++)
                {
                    uint funcRVA   = funcRVAList[i];
                    uint entryData = entryDataList[i];

                    string name = null;
                    int    ordinal;
                    if ((entryData & 0x80000000) != 0)
                    {
                        // DelayImport by ordinal.
                        ordinal = (int)(entryData & 0x7fffffff);
                    }
                    else
                    {
                        // DelayImport by name.
                        uint hintNameRVA = (entryData & 0x7fffffff);
                        accessor.Position = image.ResolvePositionToSectionData(hintNameRVA);
                        ordinal           = accessor.ReadUInt16();
                        name = accessor.ReadNullTerminatedString(Encoding.ASCII);
                    }

                    var entry = new DelayImportEntry(funcRVA, name, ordinal);
                    entry._parent = module;
                    module._list.Add(entry);
                }
            }
            else
            {
                var entryDataList = new List <ulong>();
                for (int i = 0; i < funcRVAList.Count; i++)
                {
                    entryDataList.Add(accessor.ReadUInt64());
                }

                for (int i = 0; i < funcRVAList.Count; i++)
                {
                    uint  funcRVA   = funcRVAList[i];
                    ulong entryData = entryDataList[i];

                    string name = null;
                    int    ordinal;
                    if ((entryData & 0x8000000000000000) != 0)
                    {
                        // Import by ordinal.
                        ordinal = (int)(entryData & 0x7fffffffffffffff);
                    }
                    else
                    {
                        // Import by name.
                        uint hintNameRVA = (uint)(entryData & 0x7fffffffffffffff);
                        accessor.Position = image.ResolvePositionToSectionData(hintNameRVA);
                        ordinal           = accessor.ReadUInt16();
                        name = accessor.ReadNullTerminatedString(Encoding.ASCII);
                    }

                    var entry = new DelayImportEntry(funcRVA, name, ordinal);
                    entry._parent = module;
                    module._list.Add(entry);
                }
            }

            // Restore position
            accessor.Position = position;

            return(module);
        }
        private static unsafe void Load(IBinaryAccessor accessor, PEImage image, ExportTable table)
        {
            ExportTableHeader header;

            fixed(byte *pBuff = accessor.ReadBytes(sizeof(ExportTableHeader)))
            {
                header = *(ExportTableHeader *)pBuff;
            }

            table._ordinalBase   = (int)header.Base;
            table._timeDateStamp = ConvertUtils.ToDateTime(header.TimeDateStamp);

            // Name
            accessor.Position = image.ResolvePositionToSectionData(header.Name);
            table._dllName    = accessor.ReadNullTerminatedString(Encoding.ASCII);

            if (header.AddressOfFunctions != 0)
            {
                // Export Address Table
                accessor.Position = image.ResolvePositionToSectionData(header.AddressOfFunctions);
                uint[] arrayOfExportRVA = new uint[header.NumberOfFunctions];
                for (int i = 0; i < header.NumberOfFunctions; i++)
                {
                    arrayOfExportRVA[i] = accessor.ReadUInt32();
                }

                // Name pointer table
                accessor.Position = image.ResolvePositionToSectionData(header.AddressOfNames);
                uint[] arrayOfNameRVA = new uint[header.NumberOfNames];
                for (int i = 0; i < header.NumberOfNames; i++)
                {
                    arrayOfNameRVA[i] = accessor.ReadUInt32();
                }

                // Ordinal table
                accessor.Position = image.ResolvePositionToSectionData(header.AddressOfNameOrdinals);
                ushort[] arrayOfOrdinals = new ushort[header.NumberOfNames];
                for (int i = 0; i < header.NumberOfNames; i++)
                {
                    arrayOfOrdinals[i] = accessor.ReadUInt16();
                }

                // Read names and map against export rva
                string[] names = new string[header.NumberOfFunctions];
                for (int i = 0; i < header.NumberOfNames; i++)
                {
                    accessor.Position = image.ResolvePositionToSectionData(arrayOfNameRVA[i]);
                    string name = accessor.ReadNullTerminatedString(Encoding.ASCII);

                    int ordinal = arrayOfOrdinals[i];
                    names[ordinal] = name;
                }

                var exportDirectory = image.Directories[DataDirectories.ExportTable];

                // Build entries
                for (int i = 0; i < header.NumberOfFunctions; i++)
                {
                    uint   exportRVA = arrayOfExportRVA[i];
                    string name      = names[i];

                    ExportEntry entry;

                    // Each entry in the export address table is a field that uses one of two formats in the
                    // following table. If the address specified is not within the export section (as defined
                    // by the address and length that are indicated in the optional header), the field is an
                    // export RVA, which is an actual address in code or data. Otherwise, the field is a
                    // forwarder RVA, which names a symbol in another DLL.
                    if (exportDirectory.Contains(exportRVA))
                    {
                        accessor.Position = image.ResolvePositionToSectionData(exportRVA);
                        string forwarder = accessor.ReadNullTerminatedString(Encoding.ASCII);
                        entry = new ExportForwarderEntry(name, forwarder);
                    }
                    else
                    {
                        entry = new ExportRVAEntry(name, exportRVA);
                    }

                    entry._parent = table;
                    table._list.Add(entry);
                }
            }
        }
        private void ReadStreams(IBinaryAccessor accessor, long metadataOffset)
        {
            int numberOfStream = accessor.ReadUInt16();

            int[]    offsets = new int[numberOfStream];
            int[]    sizes   = new int[numberOfStream];
            string[] names   = new string[numberOfStream];

            for (int i = 0; i < numberOfStream; i++)
            {
                offsets[i] = accessor.ReadInt32();
                sizes[i]   = accessor.ReadInt32();

                // Name of the stream; a zero-terminated ASCII string no longer than 31 characters (plus zero terminator).
                // The name might be shorter, in which case the size of the stream header is correspondingly reduced,
                // padded to the 4-byte boundary.
                long startPos = accessor.Position;
                names[i] = accessor.ReadNullTerminatedString(Encoding.ASCII);
                accessor.Align(startPos, 4);
            }

            int tableIndex = -1;

            for (int i = 0; i < numberOfStream; i++)
            {
                int    offset = offsets[i];
                int    size   = sizes[i];
                string name   = names[i];

                if (name == MetadataConstants.StreamTable)
                {
                    tableIndex          = i;
                    _tables.IsOptimized = true;
                }
                else if (name == MetadataConstants.StreamTableUnoptimized)
                {
                    tableIndex          = i;
                    _tables.IsOptimized = false;
                }
                else if (name == MetadataConstants.StreamStrings)
                {
                    accessor.Position = offset + metadataOffset;
                    _strings.Blob     = new Blob(accessor.ReadBytes(size));
                }
                else if (name == MetadataConstants.StreamUserStrings)
                {
                    accessor.Position = offset + metadataOffset;
                    _userStrings.Blob = new Blob(accessor.ReadBytes(size));
                }
                else if (name == MetadataConstants.StreamGuid)
                {
                    accessor.Position = offset + metadataOffset;
                    _guids.Blob       = new Blob(accessor.ReadBytes(size));
                }
                else if (name == MetadataConstants.StreamBlob)
                {
                    accessor.Position = offset + metadataOffset;
                    _blobs.Blob       = new Blob(accessor.ReadBytes(size));
                }
                else
                {
                    accessor.Position = offset + metadataOffset;
                    var stream = new MetadataExternalStream(name, new Blob(accessor.ReadBytes(size)));
                    ExternalStreams.Add(stream);
                }
            }

            if (tableIndex >= 0)
            {
                // Read table last as it relies on heaps.
                accessor.Position = offsets[tableIndex] + metadataOffset;
                _tables.Read(accessor);
            }
        }
Exemplo n.º 4
0
        internal static unsafe ImportModuleTable Load(IBinaryAccessor accessor, PEImage image)
        {
            ImportTableHeader header;

            fixed(byte *pBuff = accessor.ReadBytes(sizeof(ImportTableHeader)))
            {
                header = *(ImportTableHeader *)pBuff;
            }

            if (header.Name == 0 || (header.ImportLookupTableRVA == 0 && header.ImportAddressTableRVA == 0))
            {
                return(null);
            }

            // Save position
            long position = accessor.Position;

            var module = new ImportModuleTable();

            module._forwarderChain = header.ForwarderChain;

            // Dll name
            accessor.Position = image.ResolvePositionToSectionData(header.Name);
            module._dllName   = accessor.ReadNullTerminatedString(Encoding.ASCII);

            // Set RVA to ImportLookupTable or ImportAddressTable. Both tables are equivalent.
            if (header.ImportLookupTableRVA != 0)
            {
                accessor.Position = image.ResolvePositionToSectionData(header.ImportLookupTableRVA);
            }
            else
            {
                accessor.Position = image.ResolvePositionToSectionData(header.ImportAddressTableRVA);
            }

            if (image.Is32Bits)
            {
                // Read IMAGE_THUNK_DATA32 structures
                var thunkDataList = new List <uint>();
                while (true)
                {
                    uint entryData = accessor.ReadUInt32();
                    if (entryData == 0)
                    {
                        break;
                    }

                    thunkDataList.Add(entryData);
                }

                foreach (uint thunkData in thunkDataList)
                {
                    string name = null;
                    int    ordinal;
                    if ((thunkData & 0x80000000) != 0)
                    {
                        // Import by ordinal.
                        ordinal = (int)(thunkData & 0x7fffffff);
                    }
                    else
                    {
                        // Import by name.
                        uint hintNameRVA = (thunkData & 0x7fffffff);
                        accessor.Position = image.ResolvePositionToSectionData(hintNameRVA);
                        ordinal           = accessor.ReadUInt16();
                        name = accessor.ReadNullTerminatedString(Encoding.ASCII);
                    }

                    var entry = new ImportEntry(name, ordinal);
                    entry._parent = module;
                    module._list.Add(entry);
                }
            }
            else
            {
                // Read IMAGE_THUNK_DATA64 structures
                var thunkDataList = new List <ulong>();
                while (true)
                {
                    ulong entryData = accessor.ReadUInt64();
                    if (entryData == 0)
                    {
                        break;
                    }

                    thunkDataList.Add(entryData);
                }

                foreach (ulong thunkData in thunkDataList)
                {
                    string name = null;
                    int    ordinal;
                    if ((thunkData & 0x8000000000000000) != 0)
                    {
                        // Import by ordinal.
                        ordinal = (int)(thunkData & 0x7fffffffffffffff);
                    }
                    else
                    {
                        // Import by name.
                        uint hintNameRVA = (uint)(thunkData & 0x7fffffffffffffff);
                        accessor.Position = image.ResolvePositionToSectionData(hintNameRVA);
                        ordinal           = accessor.ReadUInt16();
                        name = accessor.ReadNullTerminatedString(Encoding.ASCII);
                    }

                    var entry = new ImportEntry(name, ordinal);
                    entry._parent = module;
                    module._list.Add(entry);
                }
            }

            // Restore position
            accessor.Position = position;

            return(module);
        }