Search code examples
c++hookcalldetours

Microsoft Detour - Hook Function with an assembler "call" instruction


The first question on this board and already a pretty long one - i'm sorry for that (and hereby thank you all for the great tips i got from this platform).

I'm trying to hook several functions (it's more or less plugin code, so the function I want to hook is not written/can not be changed by me, but can be directly accessed in the same process/thread) with Microsoft Detours.

Every function which shall be hooked is generated by a c-style compiler and always has the following assembler "startup" code:

045A1A85  push        ebp  
045A1A86  push        ebx  
045A1A87  push        esi  
045A1A88  push        edi  
045A1A89  call        045A1A8E  
045A1A8E  pop         eax  
045A1A8F  mov         ebx,eax  
//go on with a little bit more assembler code

As you can see some registers are pushed to the stack, and then the call instruction is invoked to the next line (please do not ask to change this, as already said i do not have access to this generated code). The call instruction changes the stack - this stack change is saved in the eax register and used for further processing(!!!)

This method will be hooked to:

045A1A85  jmp         hooking_function (528040h)  
045A1A8A  int         3  
045A1A8B  int         3  
045A1A8C  int         3  
045A1A8D  int         3  
045A1A8E  pop         eax  

The hooking function is defined as a naked function which just jumps to the trampoline function.

__inline __declspec(naked) void hooking_function()
{
    //more code in future
    __asm {
        jmp org_func_trampoline
    }
}

With the following trampoline function:

031F0060  push        ebp  
031F0061  push        ebx  
031F0062  push        esi  
031F0063  push        edi  
031F0064  call        045A1A8E  
031F0069  jmp         045A1A8E  

The main problem is, that the call instruction in the trampoline assembler code 1) adds a wrong value to the stack (in this case to 031f0064 instead of 045A1A89) --> further processing with eax will receive wrong results 2) destroys more or less the stack frame, as the next "ret" will jump back to "031F0069" ==> same processing will be done twice; ret will be called AGAIN, leads to wrong function..

Please understand, that it is NOT guaranteed that every function i want to hook begins with the above stated preamble.. therefore i can not rewrite the hooking function, and ignore the trampoline method...

So the basic question after all this text: Is it possible to hook a function with Microsoft Detour, where in the first 5 Byte of the function a call instruction is invoked? (if not, are there any alternatives?)

Thank you very much for reading (and hopefully for your help)


Solution

  • The original code performs

    045A1A89  call        045A1A8E  
    045A1A8E  pop         eax  
    

    which is just an easy way to get the content of the eip register. The pop eax immediately removes the return address (045A1A8E) from the stack and sets eax to eip's value at the point of its execution.

    Detours obviously has no way of knowing this and treats it like any subroutine, so it performs call 045A1A8E from the trampoline which will result in a different value of eax (different eip).

    I'm not entirely sure why it would return to 031F0069, from reading the code you posted it shouldn't be doing that.

    So, yes, this is a very special case. Detours usually is perfectly capable of hooking functions that have calls among the first few instructions. This one just managed to perfectly place these 2 instructions for Detours to split them in a disadvantageous way.