diff --git a/example/vmthook.cpp b/example/vmthook.cpp index ee6608d..9168ad1 100644 --- a/example/vmthook.cpp +++ b/example/vmthook.cpp @@ -28,12 +28,7 @@ int main() { std::println("unhooked target->add_42(1) = {}", target->add_42(1)); g_target_hook = safetyhook::create_vmt(target.get()); - -#if SAFETYHOOK_OS_WINDOWS g_add_42_hook = safetyhook::create_vm(g_target_hook, 1, &Hook::hooked_add_42); -#elif SAFETYHOOK_OS_LINUX - g_add_42_hook = safetyhook::create_vm(g_target_hook, 2, &Hook::hooked_add_42); -#endif std::println("hooked target->add_42(2) = {}", target->add_42(2)); diff --git a/test/inline_hook.cpp b/test/inline_hook.cpp index d702a19..5a45af2 100644 --- a/test/inline_hook.cpp +++ b/test/inline_hook.cpp @@ -11,7 +11,7 @@ using namespace Xbyak::util; static suite<"inline hook"> inline_hook_tests = [] { "Function hooked multiple times"_test = [] { struct Target { - __declspec(noinline) static std::string fn(std::string name) { return "hello " + name; } + SAFETYHOOK_NOINLINE static std::string fn(std::string name) { return "hello " + name; } }; expect(eq(Target::fn("world"), "hello world"sv)); @@ -85,7 +85,7 @@ static suite<"inline hook"> inline_hook_tests = [] { "Function with multiple args hooked"_test = [] { struct Target { - __declspec(noinline) static int add(int x, int y) { return x + y; } + SAFETYHOOK_NOINLINE static int add(int x, int y) { return x + y; } }; expect(Target::add(2, 3) == 5_i); @@ -109,12 +109,13 @@ static suite<"inline hook"> inline_hook_tests = [] { expect(Target::add(5, 6) == 11_i); }; +#if SAFETYHOOK_OS_WINDOWS "Active function is hooked and unhooked"_test = [] { static int count = 0; static bool is_running = true; struct Target { - __declspec(noinline) static std::string say_hello(int times) { return "Hello #" + std::to_string(times); } + SAFETYHOOK_NOINLINE static std::string say_hello(int times) { return "Hello #" + std::to_string(times); } static void say_hello_infinitely() { while (is_running) { @@ -150,12 +151,13 @@ static suite<"inline hook"> inline_hook_tests = [] { expect(eq(Target::say_hello(0), "Hello #0"sv)); expect(count > 0_i); }; +#endif "Function with short unconditional branch is hooked"_test = [] { static SafetyHookInline hook; struct Hook { - static int __fastcall fn() { return hook.fastcall() + 42; }; + static int SAFETYHOOK_FASTCALL fn() { return hook.fastcall() + 42; }; }; Xbyak::CodeGenerator cg{}; @@ -169,7 +171,7 @@ static suite<"inline hook"> inline_hook_tests = [] { cg.ret(); cg.nop(10, false); - const auto fn = cg.getCode(); + const auto fn = cg.getCode(); expect(fn() == 1_i); @@ -186,7 +188,7 @@ static suite<"inline hook"> inline_hook_tests = [] { static SafetyHookInline hook; struct Hook { - static int __fastcall fn(int x) { return hook.fastcall(x) + 42; }; + static int SAFETYHOOK_FASTCALL fn(int x) { return hook.fastcall(x) + 42; }; }; Xbyak::CodeGenerator cg{}; @@ -199,11 +201,17 @@ static suite<"inline hook"> inline_hook_tests = [] { cg.mov(eax, 1); cg.ret(); cg.nop(10, false); - return cg.getCode(); + return cg.getCode(); }; +#if SAFETYHOOK_OS_WINDOWS + constexpr auto param = ecx; +#elif SAFETYHOOK_OS_LINUX + constexpr auto param = edi; +#endif + "JB"_test = [&] { - cg.cmp(ecx, 8); + cg.cmp(param, 8); cg.jb(label); const auto fn = finalize(); @@ -227,7 +235,7 @@ static suite<"inline hook"> inline_hook_tests = [] { }; "JBE"_test = [&] { - cg.cmp(ecx, 8); + cg.cmp(param, 8); cg.jbe(label); const auto fn = finalize(); @@ -251,7 +259,7 @@ static suite<"inline hook"> inline_hook_tests = [] { }; "JL"_test = [&] { - cg.cmp(ecx, 8); + cg.cmp(param, 8); cg.jl(label); const auto fn = finalize(); @@ -275,7 +283,7 @@ static suite<"inline hook"> inline_hook_tests = [] { }; "JLE"_test = [&] { - cg.cmp(ecx, 8); + cg.cmp(param, 8); cg.jle(label); const auto fn = finalize(); @@ -299,7 +307,7 @@ static suite<"inline hook"> inline_hook_tests = [] { }; "JNB"_test = [&] { - cg.cmp(ecx, 8); + cg.cmp(param, 8); cg.jnb(label); const auto fn = finalize(); @@ -323,7 +331,7 @@ static suite<"inline hook"> inline_hook_tests = [] { }; "JNBE"_test = [&] { - cg.cmp(ecx, 8); + cg.cmp(param, 8); cg.jnbe(label); const auto fn = finalize(); @@ -347,7 +355,7 @@ static suite<"inline hook"> inline_hook_tests = [] { }; "JNL"_test = [&] { - cg.cmp(ecx, 8); + cg.cmp(param, 8); cg.jnl(label); const auto fn = finalize(); @@ -371,7 +379,7 @@ static suite<"inline hook"> inline_hook_tests = [] { }; "JNLE"_test = [&] { - cg.cmp(ecx, 8); + cg.cmp(param, 8); cg.jnle(label); const auto fn = finalize(); @@ -395,7 +403,7 @@ static suite<"inline hook"> inline_hook_tests = [] { }; "JNO"_test = [&] { - cg.cmp(ecx, 8); + cg.cmp(param, 8); cg.jno(label); const auto fn = finalize(); @@ -419,7 +427,7 @@ static suite<"inline hook"> inline_hook_tests = [] { }; "JNP"_test = [&] { - cg.cmp(ecx, 8); + cg.cmp(param, 8); cg.jnp(label); const auto fn = finalize(); @@ -443,7 +451,7 @@ static suite<"inline hook"> inline_hook_tests = [] { }; "JNS"_test = [&] { - cg.cmp(ecx, 8); + cg.cmp(param, 8); cg.jns(label); const auto fn = finalize(); @@ -467,7 +475,7 @@ static suite<"inline hook"> inline_hook_tests = [] { }; "JNZ"_test = [&] { - cg.cmp(ecx, 8); + cg.cmp(param, 8); cg.jnz(label); const auto fn = finalize(); @@ -491,7 +499,7 @@ static suite<"inline hook"> inline_hook_tests = [] { }; "JO"_test = [&] { - cg.cmp(ecx, 8); + cg.cmp(param, 8); cg.jo(label); const auto fn = finalize(); @@ -515,7 +523,7 @@ static suite<"inline hook"> inline_hook_tests = [] { }; "JP"_test = [&] { - cg.cmp(ecx, 8); + cg.cmp(param, 8); cg.jp(label); const auto fn = finalize(); @@ -539,7 +547,7 @@ static suite<"inline hook"> inline_hook_tests = [] { }; "JS"_test = [&] { - cg.cmp(ecx, 8); + cg.cmp(param, 8); cg.js(label); const auto fn = finalize(); @@ -563,7 +571,7 @@ static suite<"inline hook"> inline_hook_tests = [] { }; "JZ"_test = [&] { - cg.cmp(ecx, 8); + cg.cmp(param, 8); cg.jz(label); const auto fn = finalize(); diff --git a/test/inline_hook.x86_64.cpp b/test/inline_hook.x86_64.cpp index 1ce045e..cf00b5b 100644 --- a/test/inline_hook.x86_64.cpp +++ b/test/inline_hook.x86_64.cpp @@ -58,9 +58,15 @@ static suite<"inline hook (x64)"> inline_hook_x64_tests = [] { Xbyak::CodeGenerator cg{5'000'000'000}; // 5 GB Xbyak::Label start{}; +#if SAFETYHOOK_OS_WINDOWS + constexpr auto param = ecx; +#elif SAFETYHOOK_OS_LINUX + constexpr auto param = edi; +#endif + cg.nop(2'500'000'000, false); // 2.5 GB cg.L(start); - cg.mov(dword[rsp + 8], ecx); + cg.mov(dword[rsp + 8], param); cg.mov(eax, dword[rsp + 8]); cg.imul(eax, dword[rsp + 8]); cg.ret(); diff --git a/test/mid_hook.cpp b/test/mid_hook.cpp index d6920ab..8560f3f 100644 --- a/test/mid_hook.cpp +++ b/test/mid_hook.cpp @@ -6,7 +6,7 @@ using namespace boost::ut; static suite<"mid hook"> mid_hook_tests = [] { "Mid hook to change a register"_test = [] { struct Target { - __declspec(noinline) static int __fastcall add_42(int a) { return a + 42; } + SAFETYHOOK_NOINLINE static int SAFETYHOOK_FASTCALL add_42(int a) { return a + 42; } }; expect(Target::add_42(0) == 42_i); @@ -15,10 +15,18 @@ static suite<"mid hook"> mid_hook_tests = [] { struct Hook { static void add_42(SafetyHookContext& ctx) { +#if SAFETYHOOK_OS_WINDOWS #if SAFETYHOOK_ARCH_X86_64 ctx.rcx = 1337 - 42; #elif SAFETYHOOK_ARCH_X86_32 ctx.ecx = 1337 - 42; +#endif +#elif SAFETYHOOK_OS_LINUX +#if SAFETYHOOK_ARCH_X86_64 + ctx.rdi = 1337 - 42; +#elif SAFETYHOOK_ARCH_X86_32 + ctx.edi = 1337 - 42; +#endif #endif } }; @@ -39,7 +47,7 @@ static suite<"mid hook"> mid_hook_tests = [] { #if SAFETYHOOK_ARCH_X86_64 "Mid hook to change an XMM register"_test = [] { struct Target { - __declspec(noinline) static float __fastcall add_42(float a) { return a + 0.42f; } + SAFETYHOOK_NOINLINE static float SAFETYHOOK_FASTCALL add_42(float a) { return a + 0.42f; } }; expect(Target::add_42(0.0f) == 0.42_f); diff --git a/test/vmt_hook.cpp b/test/vmt_hook.cpp index 8bc7d7b..3872dd9 100644 --- a/test/vmt_hook.cpp +++ b/test/vmt_hook.cpp @@ -11,7 +11,7 @@ static suite<"vmt hook"> vmt_hook_tests = [] { }; struct Target : Interface { - __declspec(noinline) int add_42(int a) override { return a + 42; } + SAFETYHOOK_NOINLINE int add_42(int a) override { return a + 42; } }; std::unique_ptr target = std::make_unique(); @@ -52,8 +52,8 @@ static suite<"vmt hook"> vmt_hook_tests = [] { }; struct Target : Interface { - __declspec(noinline) int add_42(int a) override { return a + 42; } - __declspec(noinline) int add_43(int a) override { return a + 43; } + SAFETYHOOK_NOINLINE int add_42(int a) override { return a + 42; } + SAFETYHOOK_NOINLINE int add_43(int a) override { return a + 43; } }; std::unique_ptr target = std::make_unique(); @@ -105,7 +105,7 @@ static suite<"vmt hook"> vmt_hook_tests = [] { }; struct Target : Interface { - __declspec(noinline) int add_42(int a) override { return a + 42; } + SAFETYHOOK_NOINLINE int add_42(int a) override { return a + 42; } }; std::unique_ptr target = std::make_unique(); @@ -133,7 +133,7 @@ static suite<"vmt hook"> vmt_hook_tests = [] { add_42_hook = std::move(*vm_result); expect(target->add_42(1) == 1380_i); - expect(dynamic_cast(target.get()) != nullptr); + expect(neq(dynamic_cast(target.get()), nullptr)); }; "Can safely destroy VmtHook after object is deleted"_test = [] { @@ -143,7 +143,7 @@ static suite<"vmt hook"> vmt_hook_tests = [] { }; struct Target : Interface { - __declspec(noinline) int add_42(int a) override { return a + 42; } + SAFETYHOOK_NOINLINE int add_42(int a) override { return a + 42; } }; std::unique_ptr target = std::make_unique(); @@ -182,7 +182,7 @@ static suite<"vmt hook"> vmt_hook_tests = [] { }; struct Target : Interface { - __declspec(noinline) int add_42(int a) override { return a + 42; } + SAFETYHOOK_NOINLINE int add_42(int a) override { return a + 42; } }; std::unique_ptr target = std::make_unique(); @@ -235,7 +235,7 @@ static suite<"vmt hook"> vmt_hook_tests = [] { }; struct Target : Interface { - __declspec(noinline) int add_42(int a) override { return a + 42; } + SAFETYHOOK_NOINLINE int add_42(int a) override { return a + 42; } }; std::unique_ptr target = std::make_unique(); @@ -309,7 +309,7 @@ static suite<"vmt hook"> vmt_hook_tests = [] { }; struct Target : Interface { - __declspec(noinline) int add_42(int a) override { return a + 42; } + SAFETYHOOK_NOINLINE int add_42(int a) override { return a + 42; } }; std::unique_ptr target = std::make_unique();