PE: Add ability to fetch exports with GetExports()

This commit is contained in:
Katy Coe
2020-07-03 19:50:46 +02:00
parent 117a440b58
commit 93fed266ea
4 changed files with 62 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
/*
Copyright 2020 Katy Coe - http://www.djkaty.com - https://github.com/djkaty
All rights reserved.
*/
namespace Il2CppInspector
{
public class Export
{
public int Ordinal;
public string Name;
public ulong VirtualAddress;
}
}

View File

@@ -28,6 +28,7 @@ namespace Il2CppInspector
ulong GlobalOffset { get; }
Dictionary<string, ulong> GetSymbolTable();
uint[] GetFunctionTable();
IEnumerable<Export> GetExports();
U ReadMappedObject<U>(ulong uiAddr) where U : new();
U[] ReadMappedArray<U>(ulong uiAddr, int count) where U : new();
long[] ReadMappedWordArray(ulong uiAddr, int count);
@@ -136,6 +137,9 @@ namespace Il2CppInspector
// Find search locations in the machine code for Il2Cpp data
public virtual uint[] GetFunctionTable() => throw new NotImplementedException();
// Find all symbol exports for the image
public virtual IEnumerable<Export> GetExports() => null;
// Map an RVA to an offset into the file image
// No mapping by default
public virtual uint MapVATR(ulong uiAddr) => (uint) uiAddr;

View File

@@ -144,5 +144,21 @@ namespace Il2CppInspector
public ushort NumberOfLinenumbers;
public uint Characteristics;
}
// _IMAGE_EXPORT_DIRECTORY
internal class PEExportDirectory
{
public uint Characteristics;
public uint TimeDateStamp;
public ushort MajorVersion;
public ushort MinorVersion;
public uint Name;
public uint Base;
public uint NumberOfFunctions;
public uint NumberOfNames;
public uint AddressOfFunctions;
public uint AddressOfNames;
public uint AddressOfNameOrdinals;
}
#pragma warning restore CS0649
}

View File

@@ -4,6 +4,7 @@
All rights reserved.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -113,6 +114,32 @@ namespace Il2CppInspector
return addrs.ToArray();
}
public override IEnumerable<Export> GetExports() {
// Get exports table
var ETStart = pe.DataDirectory[0].VirtualAddress + pe.ImageBase;
// Get export RVAs
var exportDirectoryTable = ReadObject<PEExportDirectory>(MapVATR(ETStart));
var exportCount = (int) exportDirectoryTable.NumberOfFunctions;
var exportAddresses = ReadArray<uint>(MapVATR(exportDirectoryTable.AddressOfFunctions + pe.ImageBase), exportCount);
var exports = exportAddresses.Select((a, i) => new Export {
Ordinal = (int) (exportDirectoryTable.Base + i),
VirtualAddress = pe.ImageBase + a
}).ToDictionary(x => x.Ordinal, x => x);
// Get export names
var nameCount = (int) exportDirectoryTable.NumberOfNames;
var namePointers = ReadArray<uint>(MapVATR(exportDirectoryTable.AddressOfNames + pe.ImageBase), nameCount);
var ordinals = ReadArray<ushort>(MapVATR(exportDirectoryTable.AddressOfNameOrdinals + pe.ImageBase), nameCount);
for (int i = 0; i < nameCount; i++) {
var name = ReadNullTerminatedString(MapVATR(namePointers[i] + pe.ImageBase));
var ordinal = (int) exportDirectoryTable.Base + ordinals[i];
exports[ordinal].Name = name;
}
return exports.Values;
}
public override uint MapVATR(ulong uiAddr) {
if (uiAddr == 0)
return 0;