HoShiMin / HookLib

The functions interception library written on pure C and NativeAPI with UserMode and KernelMode support
MIT License
727 stars 152 forks source link
hook hook-api hooking hooklib hooks hooks-api intercept intercept-calls x86 x86-64

HookLib²

The Win32 lightweight functions interception library

✔ Advantages:

📰 What's new in the 2nd Gen:

🔬 How it works:

TargetFunction():                                 ^ ; return
-> jmp Interceptor ------> Interceptor():         |
   ??? ; Broken bytes        ... Handler code ... |
   ... ; Continuation <--+   CallOriginal() ------|--> OriginalBeginning():
   ...         +---------|-> ...                  |      ... Original beginning ...
   ret --------+         |   ret -----------------+      ... of TargetFunction ...
                         +------------------------------ jmp Continuation

🧵 Trampolines:

Supported trampolines:

Jump to a relative offset:
E9 44 33 22 11  |  jmp rip+0x11223344 ; Relative jump to ±2Gb only

Jump to an absolute address (x32):
FF 25 44 33 22 11  | jmp ds:[0x11223344]
NN NN NN NN        | <- 0x11223344 is points to

Jump to an absolute address (x64):
FF 25 00 00 00 00        | jmp [rip+00h]
88 77 66 55 44 33 22 11  | <- RIP is points to

Trampolines selection logic:

if (relative_jumpable(fn, handler))
{
    set_relative_jump(fn, handler);
}
else
{
    /*
        'Intermediate' is an intermediate buffer that allocates
        in the same block with the function beginning:
    */
    if (relative_jumpable(fn, intermediate))
    {
        set_relative_jump(fn, intermediate);
        set_absolute_jump(intermediate, handler); 
    }
    else
    {
        set_absolute_jump(fn, handler);
    }
}

🪡 Usage:

Add the HookLib.vcxproj to your .sln and add the reference to the HookLib project into your project references list as described here: select project, open the project menu, click Add -> Reference and select the HookLib.
Then add ./HookLib/HookLib/ folder to your header folders list and you're good to go.

#include <HookLib.h>

int func(int a, int b)
{
    return a + b;
}

int handler(int a, int b)
{
    return a * b;
}

template <typename Fn>
Fn hookFunc(Fn fn, Fn handler)
{
    return static_cast<Fn>(hook(fn, handler));
}

void testSimpleHook()
{
    const auto orig = hookFunc(func, handler);

    assert(func(2, 3) == 6); // Hooked, the 'handler' will be called instead
    assert(orig(2, 3) == 5);

    unhook(orig);

    assert(func(2, 3) == 5);
}

void testCppHelpers()
{
    const auto holder = HookFactory::install(func, handler);
    assert(func(2, 3) == 6);
    assert(holder.call(2, 3) == 5);
}

int main()
{
    testSimpleHook();
    testCppHelpers();

    return 0;
}