stevemk14ebr / PolyHook

x86/x64 C++ Hooking Library
MIT License
886 stars 172 forks source link

Relocation of conditional jumps: x64 MessageBox #3

Closed darkr4y closed 8 years ago

darkr4y commented 8 years ago

How can use this lib to hook windows api , can you give a example plz?~

darkr4y commented 8 years ago

Its my test code

// PolyHook.cpp : Defines the entry point for the console application.
//
#include <tchar.h>
#include "PolyHook.h"
typedef int(__stdcall *fnMessageBox)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
fnMessageBox msgbox;
// Hook function must have same prototype as target function.
int __stdcall MessageBoxAHook(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
    printf("Hooked");
    return msgbox(0, "Hooked Msgbox", "Warning", MB_OK);
}
int _tmain(int argc, _TCHAR* argv[])
{

    MessageBoxA(0, "Not hooked yet", "Warning", MB_OK);
    //HMODULE user32 = GetModuleHandleA("User32.dll");
    //uint32_t original = (uint32_t)GetProcAddress(user32, "MessageBoxA");
    //msgbox = (fnMessageBox)GetProcAddress(user32, "MessageBoxA");
    //msgbox(0, "Get Msgbox", "Warning", MB_OK);
    PLH::Detour* Hook = new PLH::Detour();

    Hook->SetupHook(&MessageBoxA, &MessageBoxAHook); //can cast to byte* to
    Hook->Hook();

    msgbox = Hook->GetOriginal<fnMessageBox>();
    MessageBoxA(0, "Not hooked yet", "Warning", MB_OK);// hook here
    Hook->UnHook();
    MessageBoxA(0, "Not hooked yet", "Warning", MB_OK);// unhook

    Sleep(10000);
    return 0;
}

It can jump into hooked func,but when return to original func,it crashed I used dbg to trace

image

darkr4y commented 8 years ago

use the same code , run the x86 bin , it goes well. so , is it a bug ?

stevemk14ebr commented 8 years ago

it's failing to relocate the je opcode, you can see that just before the push rax line. This is an error specific to x64. The reason this happens is because the address space x64 is much larger than the +-2GB of x86 so opcodes that have small offsets (31 bytes in this JE case) cannot be properly moved as the trampoline copies them significanly farther than their opcode supports a jump to. The only possible way to fix this would be to re-encode the instruction itself into one that supports a farther jump but that is significantly more work and i am willing to do at this moment. You can notice that i have already documented this bug under https://github.com/stevemk14ebr/PolyHook/issues/1. You will be hard pressed to find any x64 hooking library that properly supports this case, i may decide to fix it waaaaay down the road but like i said it's alot of work so it will be a long time if i ever do. On the bright side this is also a not very common case so if you hook another function chances are it would work properly

stevemk14ebr commented 8 years ago

I decided to spend the day and fix this, the working code can now be found under my "development" branch, please check this out and get back to me if this fixes your issue. It's been fixed by building up a jump table at the end of the trampoline, the conditional jumps are re-encoded to point to an absolute jump that then points to the final destination, so je->jmp->destination

darkr4y commented 8 years ago

wait a moment , I'll check it , thx

darkr4y commented 8 years ago

the testing is ok. and I'll try some more in-depth test. thx again :)

stevemk14ebr commented 8 years ago

if you could get back to me on how your additional tests went that would be great, i would like to close this issue if it's been properly fixed