Created
December 10, 2020 03:59
-
-
Save invokethreatguy/c2d81e5c5220977b215afe3562eb404d to your computer and use it in GitHub Desktop.
P/Invoke trick?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static class Program | |
{ | |
[DllImport("kernel32.dll", SetLastError = true)] | |
public static extern IntPtr LoadLibrary(string dllToLoad); | |
[DllImport("kernel32.dll")] | |
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName); | |
static void Main() | |
{ | |
var hModule = LoadLibrary("mimalloc-override.dll"); | |
Patch(typeof(PodHeap.PodHeapNative).GetMethod(nameof(PodHeap.PodHeapNative.AllocateImpl)).MethodHandle, hModule, "mi_malloc"); | |
Patch(typeof(PodHeap.PodHeapNative).GetMethod(nameof(PodHeap.PodHeapNative.FreeImpl)).MethodHandle, hModule, "mi_cfree"); | |
Application.SetHighDpiMode(HighDpiMode.SystemAware); | |
Application.EnableVisualStyles(); | |
Application.SetCompatibleTextRenderingDefault(false); | |
Application.Run(new Form1()); | |
} | |
private static unsafe void Patch(RuntimeMethodHandle methodHandle, IntPtr hModule, string procName) | |
{ | |
RuntimeHelpers.PrepareMethod(methodHandle); | |
var methodPointer = methodHandle.GetFunctionPointer().ToPointer(); | |
var procAddress = GetProcAddress(hModule, methodName); | |
var patchStub = stackalloc byte[] | |
{ | |
0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov rax, procAddress | |
0xff, 0xe0, // jmp rax | |
}; | |
var jitJmpToPreStubOffset = *(int*) ((byte*) methodPointer + 1); | |
var patchAddress = (byte*) methodPointer + 5 /*jmp offset counted starting from next instruction, so skip jmp 5-bytes sequence*/ + jitJmpToPreStubOffset; | |
Unsafe.CopyBlock(patchAddress, patchStub, 12); // copy patch stub bytes to the begining of method's pre-stub (there must be enough space for that in case of using as method body "throw new NotImplementedException()") | |
*(long*) (patchAddress + 2) = procAddress.ToInt64(); // skip 'mov rax' bytecodes (0x48, 0xb8) and write actual procAddress | |
} | |
} | |
public static unsafe class PodHeap | |
{ | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public static T* Allocate<T>(int count) | |
where T : unmanaged | |
{ | |
return (T*) PodHeapNative.AllocateImpl(count * Unsafe.SizeOf<T>()); | |
} | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public static void Free(void* ptr) | |
{ | |
if (ptr == null) return; | |
PodHeapNative.FreeImpl(ptr); | |
} | |
public static class PodHeapNative | |
{ | |
// [DllImport(@"d:\Repos\mimalloc-dev\out\msvc-x64\Release\mimalloc-override.dll")] | |
// [SuppressGCTransition] | |
// [SuppressUnmanagedCodeSecurity] | |
// private static extern void* mi_malloc(long size); | |
// | |
// [DllImport(@"d:\Repos\mimalloc-dev\out\msvc-x64\Release\mimalloc-override.dll")] | |
// [SuppressGCTransition] | |
// [SuppressUnmanagedCodeSecurity] | |
// private static extern void* mi_cfree(void* p); | |
[MethodImpl(MethodImplOptions.NoInlining)] | |
public static void* AllocateImpl(int size) | |
{ | |
throw new NotImplementedException(); | |
// return mi_malloc(size); | |
} | |
[MethodImpl(MethodImplOptions.NoInlining)] | |
public static void FreeImpl(void* ptr) | |
{ | |
throw new NotImplementedException(); | |
// mi_cfree(ptr); | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment