Search code examples
c#c++.netassemblyreverse-engineering

How(and where) does the native code get loaded after JIT compilation?


I have an app, written in .net(C#, 64-bit), I also have a DLL(written in C++) which I want to load at runtime and call specific functions from the main application(from within the DLL). To do that, I'd have to find the native code of this .net app and declare a function pointer to the function.

Now, I've already walked through the PE header and the metadata, found the RVA of the wanted function, however it gets me to the IL(bytecode) implementation instead of the native one(which is called at runtime). After some debugging I've managed to find the function's native(ASM) code, mapped in 64-bit address space, which I'm able to call from the DLL but I can't figure out how I could find this function dynamically(after every time the IL code runs through the JITC).

Is there any way to get information about how/where in memory the JITC loaded the native code? I couldn't really find anything relevant in the PE header regarding this.


Solution

  • After a bit of research I've found ICorDebugFunction::GetNativeCode which will return the JIT'ed function's address(given it's been compiled). Managed to get it working through a pipe server.

    For anyone who's trying to accomplish something similar as me, you might want to look into how objects are handled in the memory(I imagine it might be different depending on the compiler/.net framework), they all seem to have pointers to tables that contain JIT'ed (member) function addresses with their RID(which can be found in the PE header as well).