Skip to content

Commit

Permalink
Test: Linux support
Browse files Browse the repository at this point in the history
  • Loading branch information
cursey committed Feb 5, 2024
1 parent 0531d16 commit 952f88c
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 40 deletions.
5 changes: 0 additions & 5 deletions example/vmthook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand Down
54 changes: 31 additions & 23 deletions test/inline_hook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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);
Expand All @@ -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) {
Expand Down Expand Up @@ -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<int>() + 42; };
static int SAFETYHOOK_FASTCALL fn() { return hook.fastcall<int>() + 42; };
};

Xbyak::CodeGenerator cg{};
Expand All @@ -169,7 +171,7 @@ static suite<"inline hook"> inline_hook_tests = [] {
cg.ret();
cg.nop(10, false);

const auto fn = cg.getCode<int(__fastcall*)()>();
const auto fn = cg.getCode<int(SAFETYHOOK_FASTCALL*)()>();

expect(fn() == 1_i);

Expand All @@ -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<int>(x) + 42; };
static int SAFETYHOOK_FASTCALL fn(int x) { return hook.fastcall<int>(x) + 42; };
};

Xbyak::CodeGenerator cg{};
Expand All @@ -199,11 +201,17 @@ static suite<"inline hook"> inline_hook_tests = [] {
cg.mov(eax, 1);
cg.ret();
cg.nop(10, false);
return cg.getCode<int(__fastcall*)(int)>();
return cg.getCode<int(SAFETYHOOK_FASTCALL*)(int)>();
};

#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();

Expand All @@ -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();

Expand All @@ -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();

Expand All @@ -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();

Expand All @@ -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();

Expand All @@ -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();

Expand All @@ -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();

Expand All @@ -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();

Expand All @@ -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();

Expand All @@ -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();

Expand All @@ -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();

Expand All @@ -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();

Expand All @@ -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();

Expand All @@ -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();

Expand All @@ -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();

Expand All @@ -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();

Expand Down
8 changes: 7 additions & 1 deletion test/inline_hook.x86_64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
12 changes: 10 additions & 2 deletions test/mid_hook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
}
};
Expand All @@ -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);
Expand Down
18 changes: 9 additions & 9 deletions test/vmt_hook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<Interface> target = std::make_unique<Target>();
Expand Down Expand Up @@ -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<Interface> target = std::make_unique<Target>();
Expand Down Expand Up @@ -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<Interface> target = std::make_unique<Target>();
Expand Down Expand Up @@ -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*>(target.get()) != nullptr);
expect(neq(dynamic_cast<Target*>(target.get()), nullptr));
};

"Can safely destroy VmtHook after object is deleted"_test = [] {
Expand All @@ -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<Interface> target = std::make_unique<Target>();
Expand Down Expand Up @@ -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<Interface> target = std::make_unique<Target>();
Expand Down Expand Up @@ -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<Interface> target = std::make_unique<Target>();
Expand Down Expand Up @@ -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<Interface> target = std::make_unique<Target>();
Expand Down

0 comments on commit 952f88c

Please sign in to comment.