Add a way to know if a class has a unique vtable.
This commit is contained in:
@@ -40,6 +40,7 @@ public:
|
|||||||
public:
|
public:
|
||||||
/// @returns True if the function is detour hooked.
|
/// @returns True if the function is detour hooked.
|
||||||
/// @param function_address The function to check.
|
/// @param function_address The function to check.
|
||||||
|
// TODO check for other instructions. There's a handful that are common.
|
||||||
static bool Hooked(void* function_address);
|
static bool Hooked(void* function_address);
|
||||||
public:
|
public:
|
||||||
/// Create a new detour hook.
|
/// Create a new detour hook.
|
||||||
@@ -73,13 +74,22 @@ public:
|
|||||||
/// @param vtable_offset The position of the virtual function in the vtable for the *base class* of our target class instance.
|
/// @param vtable_offset The position of the virtual function in the vtable for the *base class* of our target class instance.
|
||||||
/// @param destination The function that we are redirecting execution to.
|
/// @param destination The function that we are redirecting execution to.
|
||||||
/// @note vtable offsets are in the same order they appear in the class definition.
|
/// @note vtable offsets are in the same order they appear in the class definition.
|
||||||
/// @note *every* instance of the class will be hooked. not just the class instance.
|
/// @note *every* instance of the class will be hooked. not just the instance you pass in.
|
||||||
/// @note if the class instance provided is destroyed before we remove our hook, We can't remove our hook anymore.
|
/// @note if the class instance provided is destroyed before we remove our hook, We can't remove our hook anymore.
|
||||||
// TODO ^^ provide a way around this.
|
|
||||||
|
|
||||||
// TODO a constructor where we can pass in the function to be hooked and
|
// TODO a constructor where we can pass in the function to be hooked and
|
||||||
// find it in the vtable so you don't have to provide the offset.
|
// find it in the vtable so you don't have to provide the offset.
|
||||||
|
// This would only work if we know exactly what the class layout is, Like if we're running directly inside the process.
|
||||||
|
// But it's still a nice feature.
|
||||||
VTable(void* class_instance, int vtable_offset, void* destination);
|
VTable(void* class_instance, int vtable_offset, void* destination);
|
||||||
~VTable();
|
~VTable();
|
||||||
public:
|
public:
|
||||||
|
/// Checks for "Shadow VTable Hook" which is, some cheats will copy the entire vtable to a new
|
||||||
|
/// memory region and replace the pointer to the vtable on the target instance to that one.
|
||||||
|
/// The downfall of this is that it makes that instance of the class unique when it would be impossible otherwise.
|
||||||
|
/// @param class_instance_to_check The instance of our class we suspect to have been modified.
|
||||||
|
/// @param class_instance_to_compare_against A class instance of the exact same type created directly before this check.
|
||||||
|
/// @note Shoutouts to AimTux Fuzion for demonstrating how cheats do this.
|
||||||
|
// TODO provide some mechanism to detect the traditional VMT hook as-well *more tricky*
|
||||||
|
static bool Hooked(void* class_instance_to_check, void* class_instance_to_compare_against);
|
||||||
};
|
};
|
1
main.cpp
1
main.cpp
@@ -23,7 +23,6 @@ int main() {
|
|||||||
auto* some_class = new Inherited();
|
auto* some_class = new Inherited();
|
||||||
virtual_hook = new VTable(some_class, 0, (void*) vtable_hook_function );
|
virtual_hook = new VTable(some_class, 0, (void*) vtable_hook_function );
|
||||||
some_class->test();
|
some_class->test();
|
||||||
|
|
||||||
std::cout << virtual_hook->Valid() << std::endl;
|
std::cout << virtual_hook->Valid() << std::endl;
|
||||||
delete virtual_hook;
|
delete virtual_hook;
|
||||||
delete some_class;
|
delete some_class;
|
||||||
|
@@ -75,3 +75,7 @@ bool VTable::Valid() {
|
|||||||
intptr_t entry = vtable + sizeof(intptr_t) * vtable_offset;
|
intptr_t entry = vtable + sizeof(intptr_t) * vtable_offset;
|
||||||
return *((intptr_t*) entry) == (intptr_t) destination;
|
return *((intptr_t*) entry) == (intptr_t) destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VTable::Hooked(void* class_instance_to_check, void* class_instance_to_compare_against) {
|
||||||
|
return *reinterpret_cast<void**>(class_instance_to_check) != *reinterpret_cast<void**>(class_instance_to_compare_against);
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user