### Build Multiple Example Target Source: https://github.com/cursey/safetyhook/blob/main/CMakeLists.txt Configures and builds the multiple example executable. This target requires C++23 support and links against the safetyhook library. ```cmake if(SAFETYHOOK_BUILD_EXAMPLES) set(example-multiple_SOURCES "example/multiple.cpp" cmake.toml ) add_executable(example-multiple) target_sources(example-multiple PRIVATE ${example-multiple_SOURCES}) source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${example-multiple_SOURCES}) target_compile_features(example-multiple PRIVATE cxx_std_23 ) target_link_libraries(example-multiple PRIVATE safetyhook::safetyhook ) get_directory_property(CMKR_VS_STARTUP_PROJECT DIRECTORY ${PROJECT_SOURCE_DIR} DEFINITION VS_STARTUP_PROJECT) if(NOT CMKR_VS_STARTUP_PROJECT) set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT example-multiple) endif() endif() ``` -------------------------------- ### Build Minimal Example Target Source: https://github.com/cursey/safetyhook/blob/main/CMakeLists.txt Configures and builds the minimal example executable. This target requires C++23 support and links against the safetyhook library. ```cmake if(SAFETYHOOK_BUILD_EXAMPLES) set(example-minimal_SOURCES "example/minimal.cpp" cmake.toml ) add_executable(example-minimal) target_sources(example-minimal PRIVATE ${example-minimal_SOURCES}) source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${example-minimal_SOURCES}) target_compile_features(example-minimal PRIVATE cxx_std_23 ) target_link_libraries(example-minimal PRIVATE safetyhook::safetyhook ) get_directory_property(CMKR_VS_STARTUP_PROJECT DIRECTORY ${PROJECT_SOURCE_DIR} DEFINITION VS_STARTUP_PROJECT) if(NOT CMKR_VS_STARTUP_PROJECT) set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT example-minimal) endif() endif() ``` -------------------------------- ### Build VMTHook Example Target Source: https://github.com/cursey/safetyhook/blob/main/CMakeLists.txt Configures and builds the VMTHook example executable. This target requires C++23 support and links against the safetyhook library. ```cmake if(SAFETYHOOK_BUILD_EXAMPLES) set(example-vmthook_SOURCES "example/vmthook.cpp" cmake.toml ) add_executable(example-vmthook) target_sources(example-vmthook PRIVATE ${example-vmthook_SOURCES}) source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${example-vmthook_SOURCES}) target_compile_features(example-vmthook PRIVATE cxx_std_23 ) target_link_libraries(example-vmthook PRIVATE safetyhook::safetyhook ) get_directory_property(CMKR_VS_STARTUP_PROJECT DIRECTORY ${PROJECT_SOURCE_DIR} DEFINITION VS_STARTUP_PROJECT) if(NOT CMKR_VS_STARTUP_PROJECT) set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT example-vmthook) endif() endif() ``` -------------------------------- ### Build DLL Example Target (Windows Only) Source: https://github.com/cursey/safetyhook/blob/main/CMakeLists.txt Configures and builds the DLL example library for Windows. This target requires C++23 support and links against the safetyhook library. ```cmake if(SAFETYHOOK_BUILD_EXAMPLES AND WIN32) set(example-dll_SOURCES "example/dll.cpp" cmake.toml ) add_library(example-dll SHARED) target_sources(example-dll PRIVATE ${example-dll_SOURCES}) source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${example-dll_SOURCES}) target_compile_features(example-dll PUBLIC cxx_std_23 ) target_link_libraries(example-dll PUBLIC safetyhook::safetyhook ) endif() ``` -------------------------------- ### Build Threadsafe Example Target Source: https://github.com/cursey/safetyhook/blob/main/CMakeLists.txt Configures and builds the threadsafe example executable. This target requires C++23 support and links against the safetyhook library. ```cmake if(SAFETYHOOK_BUILD_EXAMPLES) set(example-threadsafe_SOURCES "example/threadsafe.cpp" cmake.toml ) add_executable(example-threadsafe) target_sources(example-threadsafe PRIVATE ${example-threadsafe_SOURCES}) source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${example-threadsafe_SOURCES}) target_compile_features(example-threadsafe PRIVATE cxx_std_23 ) target_link_libraries(example-threadsafe PRIVATE safetyhook::safetyhook ) get_directory_property(CMKR_VS_STARTUP_PROJECT DIRECTORY ${PROJECT_SOURCE_DIR} DEFINITION VS_STARTUP_PROJECT) if(NOT CMKR_VS_STARTUP_PROJECT) set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT example-threadsafe) endif() endif() ``` -------------------------------- ### Build Midhook Example Target Source: https://github.com/cursey/safetyhook/blob/main/CMakeLists.txt Configures and builds the midhook example executable. This target requires C++23 support and links against the safetyhook library. ```cmake if(SAFETYHOOK_BUILD_EXAMPLES) set(example-midhook_SOURCES "example/midhook.cpp" cmake.toml ) add_executable(example-midhook) target_sources(example-midhook PRIVATE ${example-midhook_SOURCES}) source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${example-midhook_SOURCES}) target_compile_features(example-midhook PRIVATE cxx_std_23 ) target_link_libraries(example-midhook PRIVATE safetyhook::safetyhook ) get_directory_property(CMKR_VS_STARTUP_PROJECT DIRECTORY ${PROJECT_SOURCE_DIR} DEFINITION VS_STARTUP_PROJECT) if(NOT CMKR_VS_STARTUP_PROJECT) set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT example-midhook) endif() endif() ``` -------------------------------- ### FetchContent for SafetyHook Installation Source: https://github.com/cursey/safetyhook/blob/main/README.md Use this CMake code to include SafetyHook in your project via FetchContent. Ensure Zydis is fetched by setting the appropriate CMake option if needed. ```CMake include(FetchContent) # Safetyhook FetchContent_Declare( safetyhook GIT_REPOSITORY "https://github.com/cursey/safetyhook.git" GIT_TAG "origin/main" ) FetchContent_MakeAvailable(safetyhook) ``` -------------------------------- ### Install SafetyHook with CMake FetchContent Source: https://context7.com/cursey/safetyhook/llms.txt Integrate SafetyHook into your CMake project using FetchContent. Ensure Zydis is available as it's a required dependency for instruction decoding. ```cmake include(FetchContent) FetchContent_Declare( safetyhook GIT_REPOSITORY "https://github.com/cursey/safetyhook.git" GIT_TAG "origin/main" ) FetchContent_MakeAvailable(safetyhook) # Link against safetyhook in your target target_link_libraries(your_target PRIVATE safetyhook::safetyhook) ``` -------------------------------- ### Inline Hooking Example with SafetyHook Source: https://github.com/cursey/safetyhook/blob/main/README.md Demonstrates how to create and manage an inline hook for a function using SafetyHook. The hook modifies the function's behavior by calling the original function with modified arguments. ```C++ #include #include __declspec(noinline) int add(int x, int y) { return x + y; } SafetyHookInline g_add_hook{}; int hook_add(int x, int y) { return g_add_hook.call(x * 2, y * 2); } int main() { std::cout << "unhooked add(2, 3) = " << add(2, 3) << "\n"; // Create a hook on add (This uses SafetyHook's easy API). g_add_hook = safetyhook::create_inline(reinterpret_cast(add), reinterpret_cast(hook_add)); std::cout << "hooked add(3, 4) = " << add(3, 4) << "\n"; g_add_hook = {}; std::cout << "unhooked add(5, 6) = " << add(5, 6) << "\n"; return 0; } ``` -------------------------------- ### Chaining Multiple Inline Hooks Source: https://context7.com/cursey/safetyhook/llms.txt Multiple hooks can be installed on the same function. Each hook chains to the previous one, allowing modular interception of function calls. Hooks should be removed in the reverse order of their installation. ```cpp #include #include #include SafetyHookInline hook0, hook1, hook2, hook3; __declspec(noinline) void say_hi(const std::string& name) { std::cout << "hello " << name << "\n"; } void hook0_fn(const std::string& name) { hook0.call(name + " and bob"); } void hook1_fn(const std::string& name) { hook1.call(name + " and alice"); } void hook2_fn(const std::string& name) { hook2.call(name + " and eve"); } void hook3_fn(const std::string& name) { hook3.call(name + " and carol"); } int main() { // Install hooks in sequence - they chain together hook0 = safetyhook::create_inline(reinterpret_cast(say_hi), reinterpret_cast(hook0_fn)); hook1 = safetyhook::create_inline(reinterpret_cast(say_hi), reinterpret_cast(hook1_fn)); hook2 = safetyhook::create_inline(reinterpret_cast(say_hi), reinterpret_cast(hook2_fn)); hook3 = safetyhook::create_inline(reinterpret_cast(say_hi), reinterpret_cast(hook3_fn)); say_hi("world"); // Output: hello world and carol and eve and alice and bob // Hooks should be removed in reverse order hook3.reset(); hook2.reset(); hook1.reset(); hook0.reset(); return 0; } ``` -------------------------------- ### Hooking a running function with SafetyHook Source: https://context7.com/cursey/safetyhook/llms.txt Demonstrates installing an inline hook on a function while it is being called by a worker thread. SafetyHook automatically manages thread suspension and instruction pointer adjustment. ```cpp #include #include #include #include SafetyHookInline g_hook{}; std::atomic running{true}; __declspec(noinline) void process_data(int id) { std::cout << "Processing #" << id << "\n"; } void hooked_process_data(int id) { g_hook.call(id + 1000); // Modify the ID } void worker_thread() { int counter = 0; while (running) { process_data(counter++); std::this_thread::sleep_for(std::chrono::milliseconds(100)); } } int main() { // Start worker thread that calls process_data continuously std::thread worker(worker_thread); // Let it run for a bit std::this_thread::sleep_for(std::chrono::milliseconds(500)); // Install hook while function is being called // SafetyHook stops all threads and fixes IPs automatically std::cout << "Installing hook...\n"; g_hook = safetyhook::create_inline( reinterpret_cast(process_data), reinterpret_cast(hooked_process_data) ); // Let hooked version run std::this_thread::sleep_for(std::chrono::milliseconds(500)); // Remove hook safely std::cout << "Removing hook...\n"; g_hook.reset(); // Let original run again std::this_thread::sleep_for(std::chrono::milliseconds(500)); running = false; worker.join(); return 0; } ``` -------------------------------- ### Create VMT Hook with Error Handling Source: https://context7.com/cursey/safetyhook/llms.txt Shows how to use SafetyHookVmt::create for robust error checking and how to apply a single hook instance to multiple objects. ```cpp #include #include #include #include class Entity { public: virtual ~Entity() = default; virtual void update() { std::cout << "Entity::update()\n"; } }; class Player : public Entity { public: void update() override { std::cout << "Player::update()\n"; } }; static SafetyHookVmt g_vmt; static SafetyHookVm g_update_hook; class HookedEntity : public Entity { public: void hooked_update() { std::cout << "[HOOKED] "; g_update_hook.thiscall(this); } }; int main() { auto player1 = std::make_unique(); auto player2 = std::make_unique(); // Create VMT hook with error handling auto vmt_result = SafetyHookVmt::create(player1.get()); if (!vmt_result.has_value()) { if (vmt_result.error().type == SafetyHookVmt::Error::BAD_ALLOCATION) { std::cerr << "Failed to allocate VMT copy\n"; } return 1; } g_vmt = std::move(*vmt_result); // Hook the update method #if SAFETYHOOK_OS_WINDOWS auto hook_result = g_vmt.hook_method(1, &HookedEntity::hooked_update); #else auto hook_result = g_vmt.hook_method(2, &HookedEntity::hooked_update); #endif if (hook_result.has_value()) { g_update_hook = std::move(*hook_result); } // Apply hook to additional objects g_vmt.apply(player2.get()); player1->update(); // Output: [HOOKED] Player::update() player2->update(); // Output: [HOOKED] Player::update() // Remove hook from specific object g_vmt.remove(player2.get()); player2->update(); // Output: Player::update() // Reset removes from all objects g_vmt.reset(); return 0; } ``` -------------------------------- ### Create VMT Hook with safetyhook::create_vmt Source: https://context7.com/cursey/safetyhook/llms.txt Demonstrates hooking virtual methods by cloning a VMT and using VmHook to intercept calls. Note that VMT indices differ between Windows and Linux platforms. ```cpp #include #include #include // Interface with virtual methods class Interface { public: virtual ~Interface() = default; virtual int add_42(int a) = 0; virtual int multiply(int a, int b) = 0; }; // Target class to hook class Target : public Interface { public: int add_42(int a) override { return a + 42; } int multiply(int a, int b) override { return a * b; } }; SafetyHookVmt g_vmt_hook; SafetyHookVm g_add_42_hook; SafetyHookVm g_multiply_hook; // Hook class that provides replacement methods class Hook : public Target { public: int hooked_add_42(int a) { std::cout << "add_42 intercepted with: " << a << "\n"; // Call original using thiscall convention return g_add_42_hook.thiscall(this, a) + 1000; } int hooked_multiply(int a, int b) { std::cout << "multiply intercepted: " << a << " * " << b << "\n"; return g_multiply_hook.thiscall(this, a, b) * 2; } }; int main() { auto target = std::make_unique(); std::cout << "Before hook:\n"; std::cout << " add_42(1) = " << target->add_42(1) << "\n"; // 43 std::cout << " multiply(3, 4) = " << target->multiply(3, 4) << "\n"; // 12 // Create VMT hook for the object g_vmt_hook = safetyhook::create_vmt(target.get()); // Hook individual methods by VMT index // Note: Index 0 is destructor, actual methods start at index 1+ #if SAFETYHOOK_OS_WINDOWS g_add_42_hook = safetyhook::create_vm(g_vmt_hook, 1, &Hook::hooked_add_42); g_multiply_hook = safetyhook::create_vm(g_vmt_hook, 2, &Hook::hooked_multiply); #elif SAFETYHOOK_OS_LINUX // Linux may have different VMT layout g_add_42_hook = safetyhook::create_vm(g_vmt_hook, 2, &Hook::hooked_add_42); g_multiply_hook = safetyhook::create_vm(g_vmt_hook, 3, &Hook::hooked_multiply); #endif std::cout << "\nAfter hook:\n"; std::cout << " add_42(1) = " << target->add_42(1) << "\n"; // 1043 std::cout << " multiply(3, 4) = " << target->multiply(3, 4) << "\n"; // 24 // Reset unhooks all methods and restores original VMT g_vmt_hook = {}; std::cout << "\nAfter unhook:\n"; std::cout << " add_42(1) = " << target->add_42(1) << "\n"; // 43 std::cout << " multiply(3, 4) = " << target->multiply(3, 4) << "\n"; // 12 return 0; } ``` -------------------------------- ### Creating a hook with a custom allocator Source: https://context7.com/cursey/safetyhook/llms.txt Shows how to control memory allocation for hook trampolines by providing a custom allocator instance. ```cpp #include #include __declspec(noinline) int target_func(int x) { return x + 1; } static SafetyHookInline g_hook; int hooked_func(int x) { return g_hook.call(x * 2); } int main() { // Create a custom allocator auto allocator = safetyhook::Allocator::create(); // Or use the global allocator // auto allocator = safetyhook::Allocator::global(); // Create hook with custom allocator auto result = SafetyHookInline::create( allocator, target_func, hooked_func ); if (result.has_value()) { g_hook = std::move(*result); std::cout << "target_func(5) = " << target_func(5) << "\n"; // Output: target_func(5) = 11 (5*2 + 1) // Access hook metadata std::cout << "Target address: 0x" << std::hex << g_hook.target_address() << "\n"; std::cout << "Destination address: 0x" << g_hook.destination_address() << "\n"; std::cout << "Trampoline address: 0x" << g_hook.trampoline().address() << "\n"; g_hook.reset(); } return 0; } ``` -------------------------------- ### Build Test Target Source: https://github.com/cursey/safetyhook/blob/main/CMakeLists.txt Configures and builds the test executable. This target requires C++23 support and links against Boost.UT, safetyhook, and xbyak libraries. It also disables Boost.UT modules. ```cmake if(SAFETYHOOK_BUILD_TEST) set(test_SOURCES "test/allocator.cpp" "test/inline_hook.cpp" "test/inline_hook.x86_64.cpp" "test/main.cpp" "test/mid_hook.cpp" "test/vmt_hook.cpp" cmake.toml ) add_executable(test) target_sources(test PRIVATE ${test_SOURCES}) source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${test_SOURCES}) target_compile_definitions(test PRIVATE BOOST_UT_DISABLE_MODULE ) target_compile_features(test PRIVATE cxx_std_23 ) target_link_libraries(test PRIVATE Boost::ut safetyhook::safetyhook xbyak::xbyak ) get_directory_property(CMKR_VS_STARTUP_PROJECT DIRECTORY ${PROJECT_SOURCE_DIR} DEFINITION VS_STARTUP_PROJECT) if(NOT CMKR_VS_STARTUP_PROJECT) set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT test) endif() endif() ``` -------------------------------- ### Create Inline Hook with StartDisabled Flag Source: https://context7.com/cursey/safetyhook/llms.txt Creates a hook in a disabled state that can be enabled and disabled on demand. Useful for toggling hooks at runtime without destroying and recreating them. Ensure the hook is properly reset when no longer needed. ```cpp #include #include __declspec(noinline) int multiply(int a, int b) { return a * b; } static SafetyHookInline g_hook; int hooked_multiply(int a, int b) { return g_hook.call(a, b) + 100; // Add 100 to result } int main() { // Create hook but start disabled auto result = SafetyHookInline::create( multiply, hooked_multiply, SafetyHookInline::StartDisabled ); if (!result.has_value()) { return 1; } g_hook = std::move(*result); std::cout << "Disabled: " << multiply(5, 3) << "\n"; // Output: 15 // Enable the hook if (g_hook.enable().has_value()) { std::cout << "Enabled: " << multiply(5, 3) << "\n"; // Output: 115 } // Disable the hook if (g_hook.disable().has_value()) { std::cout << "Disabled again: " << multiply(5, 3) << "\n"; // Output: 15 } // Check if hook is currently enabled std::cout << "Hook enabled: " << std::boolalpha << g_hook.enabled() << "\n"; g_hook.reset(); return 0; } ``` -------------------------------- ### Create a mid-hook with explicit error handling Source: https://context7.com/cursey/safetyhook/llms.txt Uses SafetyHookMid::create to return a std::expected object, allowing for robust error checking during hook initialization. ```cpp #include #include __declspec(noinline) int compute(int x) { return x * x; } static SafetyHookMid g_hook; void intercept(SafetyHookContext& ctx) { #if SAFETYHOOK_ARCH_X86_64 // Log the input argument (first param in rcx on Windows x64) std::cout << "compute() called with: " << ctx.rcx << "\n"; #elif SAFETYHOOK_ARCH_X86_32 // On x86, check the stack for arguments std::cout << "compute() intercepted\n"; #endif } int main() { auto result = SafetyHookMid::create(compute, intercept); if (!result.has_value()) { auto& error = result.error(); if (error.type == SafetyHookMid::Error::BAD_ALLOCATION) { std::cerr << "Memory allocation failed\n"; } else if (error.type == SafetyHookMid::Error::BAD_INLINE_HOOK) { std::cerr << "Internal inline hook failed\n"; } return 1; } g_hook = std::move(*result); compute(5); // Output: compute() called with: 5 g_hook.reset(); return 0; } ``` -------------------------------- ### InlineHook Calling Conventions Source: https://context7.com/cursey/safetyhook/llms.txt The library supports multiple calling conventions when calling the original function. Use the appropriate method based on the target function's calling convention. Unsafe variants offer better performance by skipping mutex locks. ```cpp #include #include SafetyHookInline g_MessageBoxA_hook{}; SafetyHookInline g_PeekMessageW_hook{}; // MessageBoxA uses WINAPI (__stdcall on x86) int WINAPI hooked_MessageBoxA(HWND hwnd, LPCSTR text, LPCSTR caption, UINT type) { OutputDebugStringA("MessageBoxA intercepted!\n"); // Use stdcall() for __stdcall functions return g_MessageBoxA_hook.stdcall(hwnd, "Hooked!", caption, type); } // PeekMessageW uses WINAPI (__stdcall on x86) BOOL WINAPI hooked_PeekMessageW(LPMSG msg, HWND wnd, UINT min, UINT max, UINT remove) { // Use stdcall() for Windows API functions return g_PeekMessageW_hook.stdcall(msg, wnd, min, max, remove); } // Available calling convention methods: // g_hook.call(args...) - Default calling convention // g_hook.ccall(args...) - __cdecl // g_hook.stdcall(args...) - __stdcall // g_hook.thiscall(args...) - __thiscall // g_hook.fastcall(args...) - __fastcall // Unsafe variants (no mutex lock, better performance): // g_hook.unsafe_call(args...) // g_hook.unsafe_ccall(args...) // g_hook.unsafe_stdcall(args...) // g_hook.unsafe_thiscall(args...) // g_hook.unsafe_fastcall(args...) BOOL WINAPI DllMain(HINSTANCE, DWORD reason, LPVOID) { if (reason == DLL_PROCESS_ATTACH) { g_MessageBoxA_hook = safetyhook::create_inline( reinterpret_cast(&MessageBoxA), reinterpret_cast(&hooked_MessageBoxA) ); g_PeekMessageW_hook = safetyhook::create_inline( reinterpret_cast(&PeekMessageW), reinterpret_cast(&hooked_PeekMessageW) ); } else if (reason == DLL_PROCESS_DETACH) { g_PeekMessageW_hook.reset(); g_MessageBoxA_hook.reset(); } return TRUE; } ``` -------------------------------- ### Create Inline Hook with explicit error handling Source: https://context7.com/cursey/safetyhook/llms.txt Use `SafetyHookInline::create` for explicit error handling via `std::expected`. This is preferred when you need to manage hook creation failures gracefully. Ensure the hook object is moved or copied correctly. ```cpp #include #include __declspec(noinline) std::string greet(std::string name) { return "hello " + name; } static SafetyHookInline g_hook; std::string hooked_greet(std::string name) { return g_hook.call(name + " (hooked)"); } int main() { // Create hook with error handling auto hook_result = SafetyHookInline::create(greet, hooked_greet); if (!hook_result.has_value()) { auto& error = hook_result.error(); switch (error.type) { case SafetyHookInline::Error::BAD_ALLOCATION: std::cerr << "Failed to allocate memory for hook\n"; break; case SafetyHookInline::Error::FAILED_TO_DECODE_INSTRUCTION: std::cerr << "Failed to decode instruction at target\n"; break; case SafetyHookInline::Error::NOT_ENOUGH_SPACE: std::cerr << "Not enough space at target for hook\n"; break; default: std::cerr << "Hook creation failed\n"; } return 1; } g_hook = std::move(*hook_result); std::cout << greet("world") << "\n"; // Output: hello world (hooked) g_hook.reset(); return 0; } ``` -------------------------------- ### Create a mid-hook with safetyhook::create_mid Source: https://context7.com/cursey/safetyhook/llms.txt Uses a callback to inspect and modify CPU registers during function execution. Requires a valid target address, often determined via disassembly. ```cpp #include #include __declspec(noinline) int add_42(int a) { return a + 42; } SafetyHookMid g_mid_hook{}; // Mid hook callback receives CPU context void hooked_add_42(SafetyHookContext& ctx) { // On x64: registers are rax, rbx, rcx, rdx, rsi, rdi, r8-r15, rip, rsp, rflags // On x86: registers are eax, ebx, ecx, edx, esi, edi, eip, esp, eflags // XMM registers xmm0-xmm15 (x64) or xmm0-xmm7 (x86) are also available #if SAFETYHOOK_ARCH_X86_64 std::cout << "Original return value would be: " << ctx.rax << "\n"; ctx.rax = 1337; // Override return value #elif SAFETYHOOK_ARCH_X86_32 std::cout << "Original return value would be: " << ctx.eax << "\n"; ctx.eax = 1337; // Override return value #endif } int main() { std::cout << "Before hook: add_42(2) = " << add_42(2) << "\n"; // Output: Before hook: add_42(2) = 44 // Hook at a specific address (e.g., before the RET instruction) // In practice, you'd calculate this address using a disassembler auto target_addr = reinterpret_cast(add_42); // Find RET instruction (0xC3) - simplified example while (*target_addr != 0xC3) { target_addr++; } g_mid_hook = safetyhook::create_mid(target_addr, hooked_add_42); std::cout << "After hook: add_42(3) = " << add_42(3) << "\n"; // Output: After hook: add_42(3) = 1337 g_mid_hook = {}; std::cout << "After unhook: add_42(4) = " << add_42(4) << "\n"; // Output: After unhook: add_42(4) = 46 return 0; } ``` -------------------------------- ### Create Inline Hook with safetyhook::create_inline Source: https://context7.com/cursey/safetyhook/llms.txt Use `safetyhook::create_inline` for a straightforward way to redirect function calls. This method handles errors internally. The hook object must outlive the hook's usage. ```cpp #include #include // Original function to hook __declspec(noinline) int add(int x, int y) { return x + y; } // Global hook object (must outlive the hook) SafetyHookInline g_add_hook{}; // Hook function that intercepts calls to add() int hook_add(int x, int y) { std::cout << "Intercepted add(" << x << ", " << y << ")\n"; // Call original function with modified arguments return g_add_hook.call(x * 2, y * 2); } int main() { std::cout << "Before hook: add(2, 3) = " << add(2, 3) << "\n"; // Output: Before hook: add(2, 3) = 5 // Create the inline hook g_add_hook = safetyhook::create_inline( reinterpret_cast(add), reinterpret_cast(hook_add) ); std::cout << "After hook: add(3, 4) = " << add(3, 4) << "\n"; // Output: Intercepted add(3, 4) // Output: After hook: add(3, 4) = 14 // Remove hook by resetting (RAII - also happens on destruction) g_add_hook = {}; std::cout << "After unhook: add(5, 6) = " << add(5, 6) << "\n"; // Output: After unhook: add(5, 6) = 11 return 0; } ``` -------------------------------- ### safetyhook::create_mid Source: https://context7.com/cursey/safetyhook/llms.txt Creates a mid hook that allows inspection and modification of CPU registers at an arbitrary code location. ```APIDOC ## safetyhook::create_mid ### Description Creates a mid hook that allows inspection and modification of CPU registers at an arbitrary code location. The destination function receives a Context reference containing all register values which can be read or modified. ### Parameters - **target_addr** (uint8_t*) - Required - The memory address where the hook should be placed. - **callback** (function) - Required - The callback function that receives the SafetyHookContext. ### Response - **SafetyHookMid** (object) - Returns a hook object that manages the lifetime of the mid-hook. ``` -------------------------------- ### InlineHook::create Source: https://context7.com/cursey/safetyhook/llms.txt Creates an inline hook with explicit error handling using std::expected. This method is preferred when you need to handle potential hook creation failures gracefully. ```APIDOC ## InlineHook::create ### Description Creates an inline hook and returns a std::expected object containing either the hook or an error type. ### Parameters - **target** (void*) - Required - The address of the function to hook. - **destination** (void*) - Required - The address of the custom hook function. ### Response #### Success Response - **SafetyHookInline** (object) - The initialized hook object. #### Error Handling - **BAD_ALLOCATION** - Failed to allocate memory for the hook. - **FAILED_TO_DECODE_INSTRUCTION** - Failed to decode instruction at target. - **NOT_ENOUGH_SPACE** - Not enough space at target for hook. ### Request Example ```cpp auto hook_result = SafetyHookInline::create(greet, hooked_greet); ``` ``` -------------------------------- ### SafetyHookMid::create Source: https://context7.com/cursey/safetyhook/llms.txt Creates a mid hook with explicit error handling, returning a result object containing the hook or error details. ```APIDOC ## SafetyHookMid::create ### Description Creates a mid hook with explicit error handling. Returns std::expected with either the hook or detailed error information. ### Parameters - **target** (function) - Required - The target function to hook. - **callback** (function) - Required - The callback function to execute when the hook is triggered. ### Response - **std::expected** (object) - Returns the hook object on success, or an error object containing the error type (e.g., BAD_ALLOCATION, BAD_INLINE_HOOK) on failure. ``` -------------------------------- ### safetyhook::create_inline Source: https://context7.com/cursey/safetyhook/llms.txt Creates an inline hook that redirects execution from a target function to a custom destination function. This API handles errors internally and is designed for ease of use. ```APIDOC ## safetyhook::create_inline ### Description Creates an inline hook that redirects execution from a target function to a custom destination function. The hook object provides methods to call the original function from within the hook. ### Parameters - **target** (void*) - Required - The address of the function to hook. - **destination** (void*) - Required - The address of the custom hook function. ### Request Example ```cpp SafetyHookInline g_add_hook = safetyhook::create_inline(reinterpret_cast(add), reinterpret_cast(hook_add)); ``` ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.