Example #1
0
        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();
                    if (offsetToInfo.TryGetValue(tokenPos, out var exportInfo))
                    {
                        toInfo[token] = new MethodExportInfo(exportInfo.Name, exportInfo.Ordinal, exportOptions);
                    }
                    if (slotSize == 8)
                    {
                        reader.ReadUInt32();
                    }
                }
                reader.Position = pos;
            }
        }
Example #2
0
        public static bool TryGetCpuArch(Machine machine, out CpuArch cpuArch)
        {
            switch (machine)
            {
            case Machine.I386:
            case Machine.I386_Native_Apple:
            case Machine.I386_Native_FreeBSD:
            case Machine.I386_Native_Linux:
            case Machine.I386_Native_NetBSD:
            case Machine.I386_Native_Sun:
                cpuArch = x86CpuArch;
                return(true);

            case Machine.AMD64:
            case Machine.AMD64_Native_Apple:
            case Machine.AMD64_Native_FreeBSD:
            case Machine.AMD64_Native_Linux:
            case Machine.AMD64_Native_NetBSD:
            case Machine.AMD64_Native_Sun:
                cpuArch = x64CpuArch;
                return(true);

            case Machine.IA64:
                cpuArch = itaniumCpuArch;
                return(true);

            case Machine.ARMNT:
            case Machine.ARMNT_Native_Apple:
            case Machine.ARMNT_Native_FreeBSD:
            case Machine.ARMNT_Native_Linux:
            case Machine.ARMNT_Native_NetBSD:
            case Machine.ARMNT_Native_Sun:
                cpuArch = armCpuArch;
                return(true);

            case Machine.ARM64:
            case Machine.ARM64_Native_Apple:
            case Machine.ARM64_Native_FreeBSD:
            case Machine.ARM64_Native_Linux:
            case Machine.ARM64_Native_NetBSD:
            case Machine.ARM64_Native_Sun:
                //TODO: Support ARM64
                goto default;

            default:
                cpuArch = null;
                return(false);
            }
        }
Example #3
0
        static Dictionary <uint, MethodExportInfo> GetOffsetToExportInfoDictionary(ref DataReader reader, IPEImage peImage, ImageDataDirectory exportHdr, CpuArch cpuArch)
        {
            reader.Position = (uint)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();
            uint offsetOfFuncs       = (uint)peImage.ToFileOffset((RVA)reader.ReadUInt32());
            uint offsetOfNames       = (uint)peImage.ToFileOffset((RVA)reader.ReadUInt32());
            uint offsetOfNameIndexes = (uint)peImage.ToFileOffset((RVA)reader.ReadUInt32());

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

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

            for (int i = 0; i < allInfos.Length; i++)
            {
                var  nextOffset = reader.Position + 4;
                uint funcRva    = 0;
                var  rva        = (RVA)reader.ReadUInt32();
                reader.Position = (uint)peImage.ToFileOffset(rva);
                bool rvaValid   = rva != 0 && cpuArch.TryGetExportedRvaFromStub(ref reader, peImage, out funcRva);
                uint funcOffset = rvaValid ? (uint)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);
        }