Search code examples
c#assemblydelegateshookfunction-pointers

How to get a function memory address from a Delegate


I'd like to hook a function from a DLL loaded in the same process, so each time that function is called my custom function is executed instead.

In order to do that, I have declared a dummy function that will be the one executed in replace of the original function from the DLL:

 public static bool hookFunc(string a, ulong b, string c, IntPtr d)
{
     Console.WriteLine("hi");
     return true;
}

After that, I declare a Delegate and I generate a new instance of it pointing to my hookFunc function and then I get a pointer from the delegate using GetFunctionPointerForDelegate(). I also generate the bytes sequence that I will use to patch the original function's memory and I complete this sequence using the memory address of my function hookFunc (obtained from the new pointer):

public delegate bool hookDel(string a, ulong b, string c, IntPtr d);

public void hookManager()
        {

            var a = new hookDel(hookFunc);
            var hookPtr = Marshal.GetFunctionPointerForDelegate(a);
            var hookPointerBytes = BitConverter.GetBytes(hookPtr.ToInt64());
            newBytes = new byte[] { 0x49, 0xbb, hookPointerBytes[0], hookPointerBytes[1], hookPointerBytes[2], hookPointerBytes[3], hookPointerBytes[4], hookPointerBytes[5],
                                    hookPointerBytes[6], hookPointerBytes[7], 0x41, 0xff, 0xe3 };
        }

At this point, the content of the variable newBytes translated to assembly should be the following instructions:

mov r11, [memory address of my hookFunc function]
jmp r11

Finally, I get the original DLL's function memory address with GetProcAddress and I patch the first bytes with WriteProcessMemory, using for that replacement the content of the variable newBytes. After getting several StackOverflow errors, I have debugged the code with WinDbg and I discovered that the variable hookPointerBytes does not contain the address of hookFunc, therefore when the hook is triggered the jmp instruction is driving the code execution flow to a memory address where there is not executable code, and this is probably the reason why my program crashes.

I've verified that the DLL's function hooking is successfully completed and the jmp instruction is being executed. My question is, why am I not getting the real memory address of hookFunc by using the pointer obtained from the Delegate? Is there any other way in C# to get the memory address of my hookFunc function?


Solution

  • I'm not sure if you are going to get this to work without unsafe code. I think that you are going to require an unmanaged pointer which you can obtain via ToPointer on your IntPtr.

    byte* pointer = (byte*) hookPtr.ToPointer();
    
    for (int k = 0; k < 7; k++) {
        newBytes[k+2] = *(pointer + k);
    }
    

    Ive not tried this myself but you can find an example of it done here: https://github.com/wledfor2/PlayHooky

    Specific class: https://github.com/wledfor2/PlayHooky/blob/master/HookManager.cs