I thought I’d show you something fun to do in C#; changing method bodies at runtime, AFTER they’ve been JIT’d. This is a fairly simple process actually. The first thing we have to do is load our assembly using reflection:
Assembly asm = Assembly.LoadFile(Path.GetFullPath("test.exe"));
Type mainType = asm.EntryPoint.DeclaringType;
MethodInfo method = mainType.GetMethod("Foo",
BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Static);
The method we’re gonna use looks like this:
Let’s invoke it with 1000 as parameter. Expected output would be 1000*1000:
Console.WriteLine("Original value: " + method.Invoke(null, new object[] { 1000 }));
And indeed it shows 1000*1000:
Now let’s change this method to show something else! First of all we would need to force the method to be JIT’d in order for the assembly code to even be present in memory. But since we already invoked the method, it has already been JIT’d, but if we didn’t we could use:
RuntimeHelpers.PrepareMethod(method.MethodHandle);
Okay now to the interesting part. Before I start with this you should read .NET Framework Internals: MethodDesc to understand why this works. First thing we need to do is retrieve a pointer to the native method:
IntPtr pBody = method.MethodHandle.GetFunctionPointer();
Since we know our target int is 0x3e8 (1000), we iterate the body until we find it, we then write our new 0x539 (1337) in place of it:
unsafe
{
var ptr = (byte*) pBody.ToPointer();
for (var i = 0; i < 100; i++)
{
// Assuming our 0xE8 byte is the first one
if ((*(ptr+i)) == 0xe8)
(*(int*)(ptr+i)) = 0x539;
}
}
That’s it! Let’s call the method the same way we did in the beginning:
Console.WriteLine("New value: " + method.Invoke(null, new object[] { 1000 }));
It should just return 1000*1000 as before, right? Of course not, silly. We replaced the 1000 with 1337:
I’m not sure what this could be used for in practice. Perhaps some sort of obfuscation? But then you’d probably be better off using MethodRental.SwapMethodBody to work with the IL code rather than assembly. Hope you found this little example interesting. 🙂
Download files used: http://www.multiupload.nl/UR4EBGQ3BT