Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/vmt hook #34

Merged
merged 14 commits into from
Oct 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ set(safetyhook_SOURCES
"src/inline_hook.cpp"
"src/mid_hook.cpp"
"src/thread_freezer.cpp"
"src/utility.cpp"
"src/vmt_hook.cpp"
cmake.toml
)

Expand Down Expand Up @@ -489,6 +491,7 @@ if(SAFETYHOOK_BUILD_TESTS) # build-tests
"unittest/inline_hook.cpp"
"unittest/inline_hook.x86_64.cpp"
"unittest/mid_hook.cpp"
"unittest/vmt_hook.cpp"
cmake.toml
)

Expand Down Expand Up @@ -557,6 +560,7 @@ if(SAFETYHOOK_BUILD_TESTS) # build-tests
"unittest/inline_hook.cpp"
"unittest/inline_hook.x86_64.cpp"
"unittest/mid_hook.cpp"
"unittest/vmt_hook.cpp"
"amalgamated-dist/safetyhook.cpp"
cmake.toml
)
Expand Down
3 changes: 3 additions & 0 deletions include/safetyhook.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
#include <safetyhook/inline_hook.hpp>
#include <safetyhook/mid_hook.hpp>
#include <safetyhook/thread_freezer.hpp>
#include <safetyhook/vmt_hook.hpp>

using SafetyHookContext = safetyhook::Context;
using SafetyHookInline = safetyhook::InlineHook;
using SafetyHookMid = safetyhook::MidHook;
using SafetyInlineHook [[deprecated("Use SafetyHookInline instead.")]] = safetyhook::InlineHook;
using SafetyMidHook [[deprecated("Use SafetyHookMid instead.")]] = safetyhook::MidHook;
using SafetyHookVmt = safetyhook::VmtHook;
using SafetyHookVm = safetyhook::VmHook;
2 changes: 1 addition & 1 deletion include/safetyhook/allocator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,4 +124,4 @@ class Allocator final : public std::enable_shared_from_this<Allocator> {
[[nodiscard]] static bool in_range(
uint8_t* address, const std::vector<uint8_t*>& desired_addresses, size_t max_distance);
};
} // namespace safetyhook
} // namespace safetyhook
31 changes: 23 additions & 8 deletions include/safetyhook/easy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

#include <safetyhook/inline_hook.hpp>
#include <safetyhook/mid_hook.hpp>
#include <safetyhook/utility.hpp>
#include <safetyhook/vmt_hook.hpp>

namespace safetyhook {
/// @brief Easy to use API for creating an InlineHook.
Expand All @@ -14,13 +16,10 @@ namespace safetyhook {
[[nodiscard]] InlineHook create_inline(void* target, void* destination);

/// @brief Easy to use API for creating an InlineHook.
/// @tparam T The type of the function to hook.
/// @param target The address of the function to hook.
/// @param destination The address of the destination function.
/// @return The InlineHook object.
template <typename T>
requires std::is_function_v<T>
[[nodiscard]] InlineHook create_inline(T* target, T* destination) {
[[nodiscard]] InlineHook create_inline(FnPtr auto target, FnPtr auto destination) {
return create_inline(reinterpret_cast<void*>(target), reinterpret_cast<void*>(destination));
}

Expand All @@ -31,13 +30,29 @@ template <typename T>
[[nodiscard]] MidHook create_mid(void* target, MidHookFn destination);

/// @brief Easy to use API for creating a MidHook.
/// @tparam T The type of the function to hook.
/// @param target the address of the function to hook.
/// @param destination The destination function.
/// @return The MidHook object.
template <typename T>
requires std::is_function_v<T>
[[nodiscard]] MidHook create_mid(T* target, MidHookFn destination) {
[[nodiscard]] MidHook create_mid(FnPtr auto target, MidHookFn destination) {
return create_mid(reinterpret_cast<void*>(target), destination);
}

/// @brief Easy to use API for creating a VmtHook.
/// @param object The object to hook.
/// @return The VmtHook object.
[[nodiscard]] VmtHook create_vmt(void* object);

/// @brief Easy to use API for creating a VmHook.
/// @param vmt The VmtHook to use to create the VmHook.
/// @param index The index of the method to hook.
/// @param destination The destination function.
/// @return The VmHook 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
23 changes: 9 additions & 14 deletions include/safetyhook/inline_hook.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <vector>

#include <safetyhook/allocator.hpp>
#include <safetyhook/utility.hpp>

namespace safetyhook {
/// @brief An inline hook.
Expand Down Expand Up @@ -78,15 +79,12 @@ class InlineHook final {
[[nodiscard]] static std::expected<InlineHook, Error> create(void* target, void* destination);

/// @brief Create an inline hook.
/// @tparam T The type of the function to hook.
/// @param target The address of the function to hook.
/// @param destination The destination address.
/// @return The InlineHook or an InlineHook::Error if an error occurred.
/// @note This will use the default global Allocator.
/// @note If you don't care about error handling, use the easy API (safetyhook::create_inline).
template <typename T>
requires std::is_function_v<T>
[[nodiscard]] static std::expected<InlineHook, Error> create(T* target, T* destination) {
[[nodiscard]] static std::expected<InlineHook, Error> create(FnPtr auto target, FnPtr auto destination) {
return create(reinterpret_cast<void*>(target), reinterpret_cast<void*>(destination));
}

Expand All @@ -100,16 +98,13 @@ class InlineHook final {
const std::shared_ptr<Allocator>& allocator, void* target, void* destination);

/// @brief Create an inline hook with a given Allocator.
/// @tparam T The type of the function to hook.
/// @param allocator The allocator to use.
/// @param target The address of the function to hook.
/// @param destination The destination address.
/// @return The InlineHook or an InlineHook::Error if an error occurred.
/// @note If you don't care about error handling, use the easy API (safetyhook::create_inline).
template <typename T>
requires std::is_function_v<T>
[[nodiscard]] static std::expected<InlineHook, Error> create(
const std::shared_ptr<Allocator>& allocator, T* target, T* destination) {
const std::shared_ptr<Allocator>& allocator, FnPtr auto target, FnPtr auto destination) {
return create(allocator, reinterpret_cast<void*>(target), reinterpret_cast<void*>(destination));
}

Expand Down Expand Up @@ -216,7 +211,7 @@ class InlineHook final {
/// @return The result of calling the original function.
/// @note This function will use the default calling convention set by your compiler.
/// @note This function is unsafe because it doesn't lock the mutex. Only use this if you don't care about unhook
// safety or are worried about the performance cost of locking the mutex.
/// safety or are worried about the performance cost of locking the mutex.
template <typename RetT = void, typename... Args> RetT unsafe_call(Args... args) {
return original<RetT (*)(Args...)>()(args...);
}
Expand All @@ -228,7 +223,7 @@ class InlineHook final {
/// @return The result of calling the original function.
/// @note This function will use the __cdecl calling convention.
/// @note This function is unsafe because it doesn't lock the mutex. Only use this if you don't care about unhook
// safety or are worried about the performance cost of locking the mutex.
/// safety or are worried about the performance cost of locking the mutex.
template <typename RetT = void, typename... Args> RetT unsafe_ccall(Args... args) {
return original<RetT(__cdecl*)(Args...)>()(args...);
}
Expand All @@ -240,7 +235,7 @@ class InlineHook final {
/// @return The result of calling the original function.
/// @note This function will use the __thiscall calling convention.
/// @note This function is unsafe because it doesn't lock the mutex. Only use this if you don't care about unhook
// safety or are worried about the performance cost of locking the mutex.
/// safety or are worried about the performance cost of locking the mutex.
template <typename RetT = void, typename... Args> RetT unsafe_thiscall(Args... args) {
return original<RetT(__thiscall*)(Args...)>()(args...);
}
Expand All @@ -252,7 +247,7 @@ class InlineHook final {
/// @return The result of calling the original function.
/// @note This function will use the __stdcall calling convention.
/// @note This function is unsafe because it doesn't lock the mutex. Only use this if you don't care about unhook
// safety or are worried about the performance cost of locking the mutex.
/// safety or are worried about the performance cost of locking the mutex.
template <typename RetT = void, typename... Args> RetT unsafe_stdcall(Args... args) {
return original<RetT(__stdcall*)(Args...)>()(args...);
}
Expand All @@ -264,7 +259,7 @@ class InlineHook final {
/// @return The result of calling the original function.
/// @note This function will use the __fastcall calling convention.
/// @note This function is unsafe because it doesn't lock the mutex. Only use this if you don't care about unhook
// safety or are worried about the performance cost of locking the mutex.
/// safety or are worried about the performance cost of locking the mutex.
template <typename RetT = void, typename... Args> RetT unsafe_fastcall(Args... args) {
return original<RetT(__fastcall*)(Args...)>()(args...);
}
Expand All @@ -287,4 +282,4 @@ class InlineHook final {

void destroy();
};
} // namespace safetyhook
} // namespace safetyhook
12 changes: 4 additions & 8 deletions include/safetyhook/mid_hook.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <safetyhook/allocator.hpp>
#include <safetyhook/context.hpp>
#include <safetyhook/inline_hook.hpp>
#include <safetyhook/utility.hpp>

namespace safetyhook {

Expand Down Expand Up @@ -56,15 +57,12 @@ class MidHook final {
[[nodiscard]] static std::expected<MidHook, Error> create(void* target, MidHookFn destination);

/// @brief Creates a new MidHook object.
/// @tparam T The type of the function to hook.
/// @param target The address of the function to hook.
/// @param destination The destination function.
/// @return The MidHook object or a MidHook::Error if an error occurred.
/// @note This will use the default global Allocator.
/// @note If you don't care about error handling, use the easy API (safetyhook::create_mid).
template <typename T>
requires std::is_function_v<T>
[[nodiscard]] static std::expected<MidHook, Error> create(T* target, MidHookFn destination) {
[[nodiscard]] static std::expected<MidHook, Error> create(FnPtr auto target, MidHookFn destination) {
return create(reinterpret_cast<void*>(target), destination);
}

Expand All @@ -84,10 +82,8 @@ class MidHook final {
/// @param destination The destination function.
/// @return The MidHook object or a MidHook::Error if an error occurred.
/// @note If you don't care about error handling, use the easy API (safetyhook::create_mid).
template <typename T>
requires std::is_function_v<T>
[[nodiscard]] static std::expected<MidHook, Error> create(
const std::shared_ptr<Allocator>& allocator, T* target, MidHookFn destination) {
const std::shared_ptr<Allocator>& allocator, FnPtr auto target, MidHookFn destination) {
return create(allocator, reinterpret_cast<void*>(target), destination);
}

Expand Down Expand Up @@ -128,4 +124,4 @@ class MidHook final {
std::expected<void, Error> setup(
const std::shared_ptr<Allocator>& allocator, uint8_t* target, MidHookFn destination);
};
} // namespace safetyhook
} // namespace safetyhook
1 change: 0 additions & 1 deletion include/safetyhook/thread_freezer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

#include <cstdint>
#include <functional>
#include <vector>

#include <Windows.h>

Expand Down
8 changes: 7 additions & 1 deletion include/safetyhook/utility.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@

#include <algorithm>
#include <cstdint>
#include <type_traits>

namespace safetyhook {
template <typename T> constexpr void store(uint8_t* address, const T& value) {
std::copy_n(reinterpret_cast<const uint8_t*>(&value), sizeof(T), address);
}
} // namespace safetyhook

template <typename T>
concept FnPtr = requires(T f) { std::is_pointer_v<T>&& std::is_function_v<std::remove_pointer_t<T>>; };

bool is_executable(uint8_t* address);
} // namespace safetyhook
Loading