diff --git a/include/FunctionHook/Hook.h b/include/FunctionHook/Hook.h index 14f11e6..55ccaed 100644 --- a/include/FunctionHook/Hook.h +++ b/include/FunctionHook/Hook.h @@ -40,6 +40,7 @@ public: public: /// @returns True if the function is detour hooked. /// @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); public: /// 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 destination The function that we are redirecting execution to. /// @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. - // TODO ^^ provide a way around this. - + // 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. + // 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(); 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); }; \ No newline at end of file diff --git a/main.cpp b/main.cpp index 60ed86e..2606002 100644 --- a/main.cpp +++ b/main.cpp @@ -23,7 +23,6 @@ int main() { auto* some_class = new Inherited(); virtual_hook = new VTable(some_class, 0, (void*) vtable_hook_function ); some_class->test(); - std::cout << virtual_hook->Valid() << std::endl; delete virtual_hook; delete some_class; diff --git a/src/linux64/Hook.cpp b/src/linux64/Hook.cpp index de63201..3b74e2c 100644 --- a/src/linux64/Hook.cpp +++ b/src/linux64/Hook.cpp @@ -75,3 +75,7 @@ bool VTable::Valid() { intptr_t entry = vtable + sizeof(intptr_t) * vtable_offset; return *((intptr_t*) entry) == (intptr_t) destination; } + +bool VTable::Hooked(void* class_instance_to_check, void* class_instance_to_compare_against) { + return *reinterpret_cast(class_instance_to_check) != *reinterpret_cast(class_instance_to_compare_against); +}