Небольшой модуль для замены GetModuleHandle/GetProcAddress
Поддерживает x32/x64/AnyCpu
Требует C# 9.0
Компилится под 2.0-4.8.
Поддерживает x32/x64/AnyCpu
Требует C# 9.0
Компилится под 2.0-4.8.
Код:
public unsafe class NativeModules
{
public static readonly delegate*<uint, void*> NativePointer;
static NativeModules()
{
NativePointer = &NativeFunction;
var memory = (byte*)NativePointer;
if (IntPtr.Size == 4)
*memory = 0x64;
else
*(short*)memory++ = 0x4865;
*(int*)++memory = 0x00C3018B;
}
private static void* NativeFunction(uint offset)
{
return new IntPtr(offset).ToPointer();
}
private static IntPtr FindInList(void** list, int index, string module)
{
var entryOffset = index * IntPtr.Size;
var currentList = &list[index];
for (var listEntry = *currentList; listEntry != currentList; listEntry = *(void**) listEntry)
{
var entry = (void**)((byte*) listEntry - entryOffset);
var str = new string((char*)entry[12], 0, *(ushort*)&entry[11] / 2);
if (string.Compare(str, module, StringComparison.InvariantCultureIgnoreCase) == 0)
return new IntPtr(entry[6]);
}
return IntPtr.Zero;
}
public static IntPtr FindModule(string name)
{
var list = IntPtr.Size == 4
? &((void***) NativePointer(0x30))[3][3]
: &((void***) NativePointer(0x60))[3][2];
if (name == null)
return new IntPtr(((void**)((byte*)list[2] - 2 * IntPtr.Size))[6]);
for (var i = 0; i < 6; i+=2)
{
var module = FindInList(list, i, name);
if (module != IntPtr.Zero)
return module;
}
return IntPtr.Zero;
}
public static IntPtr FindProcAddress(IntPtr handle, string procName)
{
if (handle == IntPtr.Zero || procName == null) return IntPtr.Zero;
var image = (byte*) handle.ToPointer();
var exportDir = image + *(int*) (image + *(int*) (image + 60) + (IntPtr.Size == 4 ? 120 : 136));
var names = image + *(int*) (exportDir + 32);
var namesCount = *(int*) (exportDir + 24);
for (int i = 0, offset = 0; i < namesCount; i++, offset += 4)
{
if (string.Compare(new string((sbyte*) (image + *(int*) (names + offset))), procName,
StringComparison.InvariantCultureIgnoreCase) == 0)
return new IntPtr(image + *(int*) (image + *(int*) (exportDir + 28) +
(*(short*) (image + *(int*) (exportDir + 36) + (i << 1)) << 2)));
}
return IntPtr.Zero;
}
}