diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e9c75d..0baacaf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -324,6 +324,32 @@ if(SAFETYHOOK_BUILD_EXAMPLES) # build-examples safetyhook::safetyhook ) +endif() +# Target: example-vmthook +if(SAFETYHOOK_BUILD_EXAMPLES) # 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() # Target: test set(test_SOURCES diff --git a/cmake.toml b/cmake.toml index 91f3ed3..b75b814 100644 --- a/cmake.toml +++ b/cmake.toml @@ -129,6 +129,10 @@ sources = ["example/threadsafe.cpp"] type = "example-dll" sources = ["example/dll.cpp"] +[target.example-vmthook] +type = "example" +sources = ["example/vmthook.cpp"] + [target.test] type = "executable" sources = ["test/*.cpp"] diff --git a/example/midhook.cpp b/example/midhook.cpp index 53eb3cb..0823f9e 100644 --- a/example/midhook.cpp +++ b/example/midhook.cpp @@ -1,4 +1,4 @@ -#include +#include #if __has_include() #include @@ -25,7 +25,7 @@ void hooked_add_42(SafetyHookContext& ctx) { SafetyHookMid g_hook{}; int main() { - std::cout << add_42(2) << "\n"; + std::println("unhooked add_42(2) = {}", add_42(2)); // Let's disassemble add_42 and hook its RET. ZydisDecoder decoder{}; @@ -55,11 +55,11 @@ int main() { g_hook = safetyhook::create_mid(ip, hooked_add_42); - std::cout << add_42(3) << "\n"; + std::println("hooked add_42(3) = {}", add_42(3)); - g_hook.reset(); + g_hook = {}; - std::cout << add_42(4) << "\n"; + std::println("unhooked add_42(4) = {}", add_42(4)); return 0; } diff --git a/example/minimal.cpp b/example/minimal.cpp index e6bffc0..24efe11 100644 --- a/example/minimal.cpp +++ b/example/minimal.cpp @@ -1,4 +1,4 @@ -#include +#include #include @@ -13,16 +13,16 @@ int hook_add(int x, int y) { } int main() { - std::cout << "unhooked add(2, 3) = " << add(2, 3) << "\n"; + std::println("unhooked add(2, 3) = {}", add(2, 3)); // Create a hook on add. g_add_hook = safetyhook::create_inline(reinterpret_cast(add), reinterpret_cast(hook_add)); - std::cout << "hooked add(3, 4) = " << add(3, 4) << "\n"; + std::println("hooked add(3, 4) = {}", add(3, 4)); g_add_hook = {}; - std::cout << "unhooked add(5, 6) = " << add(5, 6) << "\n"; + std::println("unhooked add(5, 6) = {}", add(5, 6)); return 0; } \ No newline at end of file diff --git a/example/multiple.cpp b/example/multiple.cpp index 7d70544..01c2d42 100644 --- a/example/multiple.cpp +++ b/example/multiple.cpp @@ -1,11 +1,11 @@ -#include +#include #include SafetyHookInline hook0, hook1, hook2, hook3; __declspec(noinline) void say_hi(const std::string& name) { - std::cout << "hello " << name << "\n"; + std::println("hello {}", name); } void hook0_fn(const std::string& name) { diff --git a/example/threadsafe.cpp b/example/threadsafe.cpp index 5708f97..78a20ae 100644 --- a/example/threadsafe.cpp +++ b/example/threadsafe.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include @@ -6,7 +6,7 @@ SafetyHookInline g_hook{}; __declspec(noinline) void SayHello(int times) { - std::cout << "Hello #" << times << std::endl; + std::println("Hello #{}", times); } void Hooked_SayHello(int times [[maybe_unused]]) { diff --git a/example/vmthook.cpp b/example/vmthook.cpp new file mode 100644 index 0000000..d81c40e --- /dev/null +++ b/example/vmthook.cpp @@ -0,0 +1,40 @@ +#include +#include + +#include + +class Interface { +public: + virtual ~Interface() = default; + virtual int add_42(int a) = 0; +}; + +class Target : public Interface { +public: + int add_42(int a) override { return a + 42; } +}; + +SafetyHookVmt g_target_hook; +SafetyHookVm g_add_42_hook; + +class Hook : public Target { +public: + int hooked_add_42(int a) { return g_add_42_hook.thiscall(this, a) + 1337; } +}; + +int main() { + auto target = std::make_unique(); + + std::println("unhooked target->add_42(1) = {}", target->add_42(1)); + + g_target_hook = safetyhook::create_vmt(target.get()); + g_add_42_hook = safetyhook::create_vm(g_target_hook, 1, &Hook::hooked_add_42); + + std::println("hooked target->add_42(2) = {}", target->add_42(1)); + + g_target_hook = {}; + + std::println("unhooked target->add_42(3) = {}", target->add_42(1)); + + return 0; +} \ No newline at end of file