SafetyHook Documentation

repository·main·Indexed 20 days ago

https://github.com/cursey/safetyhook

A C++23 library for safe runtime procedure hooking on Windows x86 and x86_64 systems. It provides a high-level API for inline hooking via safetyhook::create_inline and manages thread states and instruction relocation automatically to minimize risks.

Tokens
746
Snippets
2
Records
3
Agent score
22%

What's inside SafetyHook

  1. Install SafetyHook using Amalgamated builds

    main

    The easiest way to use SafetyHook is via amalgamated builds found on the releases page.

    1. Download the ZIP file (choose the version containing Zydis if you don't already have it in your project).
    2. Copy the files directly into your project.
    3. If you are using the build that includes Zydis, you may need to define the ZYDIS_STATIC_BUILD preprocessor macro.
  2. Install SafetyHook via CMake FetchContent

    main

    You can integrate SafetyHook into your CMake project using FetchContent. If you want SafetyHook to automatically fetch the required Zydis dependency, you must enable the SAFETYHOOK_FETCH_ZYDIS CMake option.

    To enable Zydis fetching, run CMake with: -DSAFETYHOOK_FETCH_ZYDIS=ON

    include(FetchContent)
    
    # Safetyhook
    FetchContent_Declare(
        safetyhook
        GIT_REPOSITORY "https://github.com/cursey/safetyhook.git"
        GIT_TAG "origin/main"
    )
    FetchContent_MakeAvailable(safetyhook)
  3. Use SafetyHook for inline procedure hooking

    main

    SafetyHook provides a high-level API for creating inline hooks. You can use safetyhook::create_inline to redirect a target function to a detour function. To call the original function from within the detour, use the .call<T>(...) method on the returned hook object.

    Note: The target function should ideally be marked with __declspec(noinline) to ensure predictable hooking behavior.

    #include <iostream>
    #include <safetyhook.hpp>
    
    __declspec(noinline) int add(int x, int y) {
        return x + y;
    }
    
    SafetyHookInline g_add_hook{};
    
    int hook_add(int x, int y) {
        // Call the original function using the hook object
        return g_add_hook.call<int>(x * 2, y * 2);
    }
    
    int main() {
        std::cout << "unhooked add(2, 3) = " << add(2, 3) << "\n";
    
        // Create a hook on add
        g_add_hook = safetyhook::create_inline(reinterpret_cast<void*>(add), reinterpret_cast<void*>(hook_add));
    
        std::cout << "hooked add(3, 4) = " << add(3, 4) << "\n";
    
        // Remove the hook by resetting the object
        g_add_hook = {};
    
        std::cout << "unhooked add(5, 6) = " << add(5, 6) << "\n";
    
        return 0;
    }