6#ifndef SAFETYHOOK_USE_CXXMODULES
18#include "safetyhook/common.hpp"
19#include "safetyhook/utility.hpp"
23class SAFETYHOOK_API InlineHook final {
128 [[nodiscard]]
static std::expected<InlineHook, Error>
create(
138 template <
typename T,
typename U>
150 [[nodiscard]]
static std::expected<InlineHook, Error>
create(
160 template <
typename T,
typename U>
161 [[nodiscard]]
static std::expected<InlineHook, Error>
create(
180 [[nodiscard]] uint8_t*
target()
const {
return m_target; }
184 [[nodiscard]] uintptr_t
target_address()
const {
return reinterpret_cast<uintptr_t
>(m_target); }
188 [[nodiscard]] uint8_t*
destination()
const {
return m_destination; }
192 [[nodiscard]] uintptr_t
destination_address()
const {
return reinterpret_cast<uintptr_t
>(m_destination); }
200 explicit operator bool()
const {
return static_cast<bool>(m_trampoline); }
205 template <
typename T> [[nodiscard]] T
original()
const {
return reinterpret_cast<T
>(m_trampoline.address()); }
217 template <
typename RetT = void,
typename... Args> RetT
call(Args... args) {
218 std::scoped_lock lock{m_mutex};
219 return m_trampoline ?
original<RetT (*)(Args...)>()(args...) : RetT();
228 template <
typename RetT = void,
typename... Args> RetT
ccall(Args... args) {
229 std::scoped_lock lock{m_mutex};
230 return m_trampoline ?
original<RetT(SAFETYHOOK_CCALL*)(Args...)>()(args...) : RetT();
239 template <
typename RetT = void,
typename... Args> RetT
thiscall(Args... args) {
240 std::scoped_lock lock{m_mutex};
241 return m_trampoline ?
original<RetT(SAFETYHOOK_THISCALL*)(Args...)>()(args...) : RetT();
250 template <
typename RetT = void,
typename... Args> RetT
stdcall(Args... args) {
251 std::scoped_lock lock{m_mutex};
252 return m_trampoline ?
original<RetT(SAFETYHOOK_STDCALL*)(Args...)>()(args...) : RetT();
261 template <
typename RetT = void,
typename... Args> RetT
fastcall(Args... args) {
262 std::scoped_lock lock{m_mutex};
263 return m_trampoline ?
original<RetT(SAFETYHOOK_FASTCALL*)(Args...)>()(args...) : RetT();
274 template <
typename RetT = void,
typename... Args> RetT
unsafe_call(Args... args) {
275 return original<RetT (*)(Args...)>()(args...);
286 template <
typename RetT = void,
typename... Args> RetT
unsafe_ccall(Args... args) {
287 return original<RetT(SAFETYHOOK_CCALL*)(Args...)>()(args...);
298 template <
typename RetT = void,
typename... Args> RetT
unsafe_thiscall(Args... args) {
299 return original<RetT(SAFETYHOOK_THISCALL*)(Args...)>()(args...);
310 template <
typename RetT = void,
typename... Args> RetT
unsafe_stdcall(Args... args) {
311 return original<RetT(SAFETYHOOK_STDCALL*)(Args...)>()(args...);
322 template <
typename RetT = void,
typename... Args> RetT
unsafe_fastcall(Args... args) {
323 return original<RetT(SAFETYHOOK_FASTCALL*)(Args...)>()(args...);
327 [[nodiscard]] std::expected<void, Error>
enable();
330 [[nodiscard]] std::expected<void, Error>
disable();
333 [[nodiscard]]
bool enabled()
const {
return m_enabled; }
345 uint8_t* m_destination{};
346 Allocation m_trampoline{};
347 std::vector<uint8_t> m_original_bytes{};
348 uintptr_t m_trampoline_size{};
349 std::recursive_mutex m_mutex{};
351 Type m_type{Type::Unset};
353 std::expected<void, Error> setup(
354 const std::shared_ptr<Allocator>& allocator, uint8_t* target, uint8_t* destination);
355 std::expected<void, Error> e9_hook(
const std::shared_ptr<Allocator>& allocator);
357#if SAFETYHOOK_ARCH_X86_64
358 std::expected<void, Error> ff_hook(
const std::shared_ptr<Allocator>& allocator);
Allocator for allocating memory near target addresses.
A memory allocation.
Definition allocator.hpp:22
Error
The error type returned by the allocate functions.
Definition allocator.hpp:80
An inline hook.
Definition inline_hook.hpp:23
RetT stdcall(Args... args)
Calls the original function.
Definition inline_hook.hpp:250
RetT unsafe_fastcall(Args... args)
Calls the original function.
Definition inline_hook.hpp:322
std::expected< void, Error > enable()
Enable the hook.
uint8_t * target() const
Get a pointer to the target.
Definition inline_hook.hpp:180
RetT unsafe_thiscall(Args... args)
Calls the original function.
Definition inline_hook.hpp:298
RetT thiscall(Args... args)
Calls the original function.
Definition inline_hook.hpp:239
static std::expected< InlineHook, Error > create(T target, U destination, Flags flags=Default)
Create an inline hook.
Definition inline_hook.hpp:139
void reset()
Reset the hook.
uintptr_t target_address() const
Get the target address.
Definition inline_hook.hpp:184
static std::expected< InlineHook, Error > create(void *target, void *destination, Flags flags=Default)
Create an inline hook.
RetT unsafe_stdcall(Args... args)
Calls the original function.
Definition inline_hook.hpp:310
RetT fastcall(Args... args)
Calls the original function.
Definition inline_hook.hpp:261
static std::expected< InlineHook, Error > create(const std::shared_ptr< Allocator > &allocator, T target, U destination, Flags flags=Default)
Create an inline hook with a given Allocator.
Definition inline_hook.hpp:161
RetT call(Args... args)
Calls the original function.
Definition inline_hook.hpp:217
RetT unsafe_call(Args... args)
Calls the original function.
Definition inline_hook.hpp:274
Flags
Flags for InlineHook.
Definition inline_hook.hpp:116
@ StartDisabled
Start the hook disabled.
Definition inline_hook.hpp:118
@ Default
Default flags.
Definition inline_hook.hpp:117
uint8_t * destination() const
Get a pointer ot the destination.
Definition inline_hook.hpp:188
bool enabled() const
Check if the hook is enabled.
Definition inline_hook.hpp:333
RetT ccall(Args... args)
Calls the original function.
Definition inline_hook.hpp:228
std::expected< void, Error > disable()
Disable the hook.
const Allocation & trampoline() const
Get the trampoline Allocation.
Definition inline_hook.hpp:196
T original() const
Returns the address of the trampoline to call the original function.
Definition inline_hook.hpp:205
RetT unsafe_ccall(Args... args)
Calls the original function.
Definition inline_hook.hpp:286
uintptr_t destination_address() const
Get the destination address.
Definition inline_hook.hpp:192
const auto & original_bytes() const
Returns a vector containing the original bytes of the target function.
Definition inline_hook.hpp:209
static std::expected< InlineHook, Error > create(const std::shared_ptr< Allocator > &allocator, void *target, void *destination, Flags flags=Default)
Create an inline hook with a given Allocator.
A mid function hook.
Definition mid_hook.hpp:25
Error type for InlineHook.
Definition inline_hook.hpp:26
Error type for InlineHook.
Definition inline_hook.hpp:26
enum safetyhook::InlineHook::Error::@135365244370362274101266221067006252356170164043 type
The type of error.
uint8_t * ip
IP of the problematic instruction.
Definition inline_hook.hpp:41
static Error unsupported_instruction_in_trampoline(uint8_t *ip)
Create a UNSUPPORTED_INSTRUCTION_IN_TRAMPOLINE error.
Definition inline_hook.hpp:87
static Error short_jump_in_trampoline(uint8_t *ip)
Create a SHORT_JUMP_IN_TRAMPOLINE error.
Definition inline_hook.hpp:67
static Error not_enough_space(uint8_t *ip)
Create a NOT_ENOUGH_SPACE error.
Definition inline_hook.hpp:107
static Error failed_to_decode_instruction(uint8_t *ip)
Create a FAILED_TO_DECODE_INSTRUCTION error.
Definition inline_hook.hpp:57
static Error ip_relative_instruction_out_of_range(uint8_t *ip)
Create a IP_RELATIVE_INSTRUCTION_OUT_OF_RANGE error.
Definition inline_hook.hpp:77
static Error bad_allocation(Allocator::Error err)
Create a BAD_ALLOCATION error.
Definition inline_hook.hpp:47
Allocator::Error allocator_error
Allocator error information.
Definition inline_hook.hpp:40
static Error failed_to_unprotect(uint8_t *ip)
Create a FAILED_TO_UNPROTECT error.
Definition inline_hook.hpp:97
@ UNSUPPORTED_INSTRUCTION_IN_TRAMPOLINE
An unsupported instruction was found in the trampoline.
Definition inline_hook.hpp:33
@ NOT_ENOUGH_SPACE
Not enough space to create the hook.
Definition inline_hook.hpp:35
@ IP_RELATIVE_INSTRUCTION_OUT_OF_RANGE
An IP-relative instruction is out of range.
Definition inline_hook.hpp:32
@ FAILED_TO_UNPROTECT
Failed to unprotect memory.
Definition inline_hook.hpp:34
@ FAILED_TO_DECODE_INSTRUCTION
Failed to decode an instruction.
Definition inline_hook.hpp:30
@ SHORT_JUMP_IN_TRAMPOLINE
The trampoline contains a short jump.
Definition inline_hook.hpp:31
@ BAD_ALLOCATION
An error occurred when allocating memory.
Definition inline_hook.hpp:29