void Initialize(ModuleDefMD module)
        {
            var vtblHdr = module.Metadata.ImageCor20Header.VTableFixups;

            if (vtblHdr.VirtualAddress == 0 || vtblHdr.Size == 0)
            {
                return;
            }

            var peImage   = module.Metadata.PEImage;
            var exportHdr = peImage.ImageNTHeaders.OptionalHeader.DataDirectories[0];

            if (exportHdr.VirtualAddress == 0 || exportHdr.Size < 0x28)
            {
                return;
            }

            if (!CpuArch.TryGetCpuArch(peImage.ImageNTHeaders.FileHeader.Machine, out var cpuArch))
            {
                Debug.Fail($"Exported methods: Unsupported machine: {peImage.ImageNTHeaders.FileHeader.Machine}");
                return;
            }

            var reader       = peImage.CreateReader();
            var offsetToInfo = GetOffsetToExportInfoDictionary(ref reader, peImage, exportHdr, cpuArch);

            reader.Position = (uint)peImage.ToFileOffset(vtblHdr.VirtualAddress);
            ulong endPos = (ulong)reader.Position + vtblHdr.Size;

            while ((ulong)reader.Position + 8 <= endPos && reader.CanRead(8U))
            {
                var  tableRva      = (RVA)reader.ReadUInt32();
                int  numSlots      = reader.ReadUInt16();
                var  flags         = (VTableFlags)reader.ReadUInt16();
                bool is64bit       = (flags & VTableFlags.Bit64) != 0;
                var  exportOptions = ToMethodExportInfoOptions(flags);

                var pos = reader.Position;
                reader.Position = (uint)peImage.ToFileOffset(tableRva);
                uint slotSize = is64bit ? 8U : 4;
                while (numSlots-- > 0 && reader.CanRead(slotSize))
                {
                    var  tokenPos = reader.Position;
                    uint token    = reader.ReadUInt32();
                    bool b        = offsetToInfo.TryGetValue(tokenPos, out var exportInfo);
                    Debug.Assert(token == 0 || b);
                    if (b)
                    {
                        exportInfo    = new MethodExportInfo(exportInfo.Name, exportInfo.Ordinal, exportOptions);
                        toInfo[token] = exportInfo;
                    }
                    if (slotSize == 8)
                    {
                        reader.ReadUInt32();
                    }
                }
                reader.Position = pos;
            }
        }
Exemple #2
0
        static Dictionary <long, MethodExportInfo> GetOffsetToExportInfoDictionary(IImageStream reader, IPEImage peImage, ImageDataDirectory exportHdr, CpuArch cpuArch)
        {
            reader.Position = (long)peImage.ToFileOffset(exportHdr.VirtualAddress);
            // Skip Characteristics(4), TimeDateStamp(4), MajorVersion(2), MinorVersion(2), Name(4)
            reader.Position += 16;
            uint ordinalBase         = reader.ReadUInt32();
            int  numFuncs            = reader.ReadInt32();
            int  numNames            = reader.ReadInt32();
            long offsetOfFuncs       = (long)peImage.ToFileOffset((RVA)reader.ReadUInt32());
            long offsetOfNames       = (long)peImage.ToFileOffset((RVA)reader.ReadUInt32());
            long offsetOfNameIndexes = (long)peImage.ToFileOffset((RVA)reader.ReadUInt32());

            var names = ReadNames(reader, peImage, numNames, offsetOfNames, offsetOfNameIndexes);

            reader.Position = offsetOfFuncs;
            var allInfos = new MethodExportInfo[numFuncs];
            var dict     = new Dictionary <long, MethodExportInfo>(numFuncs);

            for (int i = 0; i < allInfos.Length; i++)
            {
                var  currOffset = reader.Position;
                var  nextOffset = reader.Position + 4;
                uint funcRva    = 0;
                var  rva        = (RVA)reader.ReadUInt32();
                reader.Position = (long)peImage.ToFileOffset(rva);
                bool rvaValid   = rva != 0 && cpuArch.TryGetExportedRvaFromStub(reader, peImage, out funcRva);
                long funcOffset = rvaValid ? (long)peImage.ToFileOffset((RVA)funcRva) : 0;
                var  exportInfo = new MethodExportInfo((ushort)(ordinalBase + (uint)i));
                if (funcOffset != 0)
                {
                    dict[funcOffset] = exportInfo;
                }
                allInfos[i]     = exportInfo;
                reader.Position = nextOffset;
            }

            foreach (var info in names)
            {
                int index = info.Index;
                if ((uint)index >= (uint)numFuncs)
                {
                    continue;
                }
                allInfos[index].Ordinal = null;
                allInfos[index].Name    = info.Name;
            }

            return(dict);
        }