Skip to content

Commit

Permalink
VmtHook: Add easy API for hooking methods
Browse files Browse the repository at this point in the history
  • Loading branch information
cursey committed Oct 6, 2023
1 parent ffff4c8 commit 5e67184
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 1 deletion.
8 changes: 8 additions & 0 deletions include/safetyhook/easy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,12 @@ namespace safetyhook {
}

[[nodiscard]] VmtHook create_vmt(void* object);
[[nodiscard]] VmHook create_vm(VmtHook& vmt, size_t index, FnPtr auto destination) {
if (auto hook = vmt.hook_method(index, destination)) {
return std::move(*hook);
} else {
return {};
}
}

} // namespace safetyhook
33 changes: 32 additions & 1 deletion unittest/vmt_hook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,4 +297,35 @@ TEST_CASE("Can remove an object that was previously VMT hooked", "[vmt_hook]") {
REQUIRE(target0->add_42(2) == 44);
REQUIRE(target1->add_42(2) == 44);
REQUIRE(target2->add_42(2) == 44);
}
}

TEST_CASE("VMT hook an object instance with easy API", "[vmt_hook]") {
struct Interface {
virtual ~Interface() = default;
virtual int add_42(int a) = 0;
};

struct Target : Interface {
__declspec(noinline) int add_42(int a) override { return a + 42; }
};

std::unique_ptr<Interface> target = std::make_unique<Target>();

REQUIRE(target->add_42(0) == 42);

static SafetyHookVmt target_hook{};
static SafetyHookVm add_42_hook{};

struct Hook : Target {
int hooked_add_42(int a) { return add_42_hook.thiscall<int>(this, a) + 1337; }
};

target_hook = safetyhook::create_vmt(target.get());
add_42_hook = safetyhook::create_vm(target_hook, 1, &Hook::hooked_add_42);

REQUIRE(target->add_42(1) == 1380);

add_42_hook.reset();

REQUIRE(target->add_42(2) == 44);
}

0 comments on commit 5e67184

Please sign in to comment.