public unsafe void TestExternalVTableCallAfterVTablePointerIsHooked() { // HookedObjectVirtualFunctionTable only supports hooking objects // where the vtable pointer is at [objectbaseadress] // to test this, we create a pointer to our vtable. // this serves as a fake object, which we can hook nuint vTableOriginal = _nativeCalculator.VTable; IntPtr fakeObject = new IntPtr(&vTableOriginal); // We hook the vtable pointer(fakeObject), this changes the vtable pointer but does not hook any functions yet // Checking if this corrupts anything is done in TestVTableHookExternalCallBeforeHook var vTableHook = HookedObjectVirtualFunctionTable.FromObject(fakeObject.ToUnsigned(), Enum.GetNames(typeof(NativeCalculator.VTableFunctions)).Length);; // We create a VirtualFunctionTable from our fakeObject // Calling the functions should call our hooks var vTable = VirtualFunctionTable.FromObject(fakeObject.ToUnsigned(), Enum.GetNames(typeof(NativeCalculator.VTableFunctions)).Length); var addFunction = vTable.CreateWrapperFunction <NativeCalculator.AddFunction>((int)NativeCalculator.VTableFunctions.Add); var subtractFunction = vTable.CreateWrapperFunction <NativeCalculator.SubtractFunction>((int)NativeCalculator.VTableFunctions.Subtract); var multiplyFunction = vTable.CreateWrapperFunction <NativeCalculator.MultiplyFunction>((int)NativeCalculator.VTableFunctions.Multiply); var divideFunction = vTable.CreateWrapperFunction <NativeCalculator.DivideFunction>((int)NativeCalculator.VTableFunctions.Divide); // Test Calling after we hook the vtable pointer using an 'external' class (VirtualFunctionTable) // This should not modify any results for (int x = 1; x < 100; x++) { for (int y = 100; y > 0; y--) { int add = x + y; int subtract = x - y; int multiply = x * y; int divide = x / y; Assert.Equal(add, addFunction(x, y)); Assert.Equal(subtract, subtractFunction(x, y)); Assert.Equal(multiply, multiplyFunction(x, y)); Assert.Equal(divide, divideFunction(x, y)); } } }
public IVirtualFunctionTable VirtualFunctionTableFromObject(IntPtr objectAddress, int numberOfMethods) => VirtualFunctionTable.FromObject(objectAddress, numberOfMethods);
public unsafe void TestExternalVTableCallAfterFunctionHook() { int addHook(int a, int b) { return(_addHook.OriginalFunction(a, b) + 1); } int subHook(int a, int b) { return(_subHook.OriginalFunction(a, b) - 1); } int mulHook(int a, int b) { return(_multiplyHook.OriginalFunction(a, b) * 2); } int divHook(int a, int b) { return(_divideHook.OriginalFunction(a, b) * 2); } // HookedObjectVirtualFunctionTable only supports hooking objects // where the vtable pointer is at [objectbaseadress] // to test this, we create a pointer to our vtable. // this serves as a fake object, which we can hook IntPtr vTableOriginal = _nativeCalculator.VTable; IntPtr fakeObject = new IntPtr(&vTableOriginal); // We hook the vtable pointer(fakeObject), this changes the vtable pointer but does not hook any functions yet // Checking if this corrupts anything is done in TestVTableCallsAfterHookingVTablePointer var vTableHook = HookedObjectVirtualFunctionTable.FromObject(fakeObject, Enum.GetNames(typeof(NativeCalculator.VTableFunctions)).Length);; _addHook = vTableHook.CreateFunctionHook <NativeCalculator.AddFunction>((int)NativeCalculator.VTableFunctions.Add, addHook).Activate(); _subHook = vTableHook.CreateFunctionHook <NativeCalculator.SubtractFunction>((int)NativeCalculator.VTableFunctions.Subtract, subHook).Activate(); _multiplyHook = vTableHook.CreateFunctionHook <NativeCalculator.MultiplyFunction>((int)NativeCalculator.VTableFunctions.Multiply, mulHook).Activate(); _divideHook = vTableHook.CreateFunctionHook <NativeCalculator.DivideFunction>((int)NativeCalculator.VTableFunctions.Divide, divHook).Activate(); // We create a VirtualFunctionTable from our fakeObject // Calling the functions should call our hooks var vTable = VirtualFunctionTable.FromObject(fakeObject, Enum.GetNames(typeof(NativeCalculator.VTableFunctions)).Length); var addFunction = vTable.CreateWrapperFunction <NativeCalculator.AddFunction>((int)NativeCalculator.VTableFunctions.Add); var subtractFunction = vTable.CreateWrapperFunction <NativeCalculator.SubtractFunction>((int)NativeCalculator.VTableFunctions.Subtract); var multiplyFunction = vTable.CreateWrapperFunction <NativeCalculator.MultiplyFunction>((int)NativeCalculator.VTableFunctions.Multiply); var divideFunction = vTable.CreateWrapperFunction <NativeCalculator.DivideFunction>((int)NativeCalculator.VTableFunctions.Divide); // Test Calling after we hook the vtable function pointers using an 'external' class (VirtualFunctionTable) // This should not modify any results for (int x = 1; x < 100; x++) { for (int y = 100; y > 0; y--) { int add = (x + y) + 1; int subtract = (x - y) - 1; int multiply = (x * y) * 2; int divide = (x / y) * 2; Assert.Equal(add, addFunction(x, y)); Assert.Equal(subtract, subtractFunction(x, y)); Assert.Equal(multiply, multiplyFunction(x, y)); Assert.Equal(divide, divideFunction(x, y)); } } }