public void TestVTableCall() { var vTable = VirtualFunctionTable.FromAddress(_nativeCalculator.VTable, Enum.GetNames(typeof(NativeCalculator.VTableFunctions)).Length); // Setup calling functions. 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 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)); } } }
/// <summary> /// Copies Crosire's D3D8To9 and hooks the DX9 device creation. /// </summary> /// <param name="dllDirectory">Directory containing Crosire's d3d8to9.</param> public void HookDevice(string dllDirectory) { // Copy crosire's d3d8to9 to game directory and then load it. (Game should use D3D9 now). if (!File.Exists("d3d8.dll")) { File.Copy(dllDirectory + $"\\d3d8.dll", "d3d8.dll", true); } // Load Crosire's D3D8To9 (which in turn loads D3D9 internally) LoadLibraryW("d3d8.dll"); // Get our D3D Interface VTable using (Direct3D direct3D = new Direct3D()) using (Form renderForm = new Form()) using (SharpDX.Direct3D9.Device device = new SharpDX.Direct3D9.Device(direct3D, 0, DeviceType.NullReference, IntPtr.Zero, CreateFlags.HardwareVertexProcessing, new PresentParameters() { BackBufferWidth = 1, BackBufferHeight = 1, DeviceWindowHandle = renderForm.Handle })) { _direct3DVirtualFunctionTable = new VirtualFunctionTable(direct3D.NativePointer, Enum.GetNames(typeof(Interfaces.IDirect3D9)).Length); _direct3DDeviceVirtualFunctionTable = new VirtualFunctionTable(device.NativePointer, Enum.GetNames(typeof(Interfaces.IDirect3DDevice9)).Length); } // Hook D3D9 device creation. _createDeviceHook = _direct3DVirtualFunctionTable.TableEntries[(int)Interfaces.IDirect3D9.CreateDevice].CreateFunctionHook86 <CreateDevice>(CreateDeviceImpl).Activate(); //_resetDeviceHook = _direct3DDeviceVirtualFunctionTable.TableEntries[(int)Interfaces.IDirect3DDevice9.Reset].CreateFunctionHook86<Direct3D9DeviceResetDelegate>(ResetDeviceImpl).Activate(); }
/// <summary> /// Constructor for the hooking class. /// Creates the Direct3D9/Direct3D9Ex devices inside the function to get their /// native pointer for hooking purposes. /// </summary> public DX9Hook() { // Obtain the pointer to the IDirect3DDevice9 instance // by creating our own blank windows form and creating a IDirect3DDevice9 // targeting that form. The returned device should be the same one as used by the game. using (Direct3D direct3D = new Direct3D()) using (Form renderForm = new Form()) using (Device device = new Device(direct3D, 0, DeviceType.NullReference, IntPtr.Zero, CreateFlags.HardwareVertexProcessing, new PresentParameters() { BackBufferWidth = 1, BackBufferHeight = 1, DeviceWindowHandle = renderForm.Handle })) { DirectXFunctions = new VirtualFunctionTable(device.NativePointer, Enum.GetNames(typeof(Direct3DDevice9)).Length); } // Obtain the pointer to the IDirect3DDevice9Ex instance // by creating our own blank windows form and creating a IDirect3DDevice9Ex // targeting that form. The returned device should be the same one as used by the game. using (Direct3DEx direct3D = new Direct3DEx()) using (var renderForm = new Form()) using (DeviceEx device = new DeviceEx(direct3D, 0, DeviceType.NullReference, IntPtr.Zero, CreateFlags.HardwareVertexProcessing, new PresentParameters() { BackBufferWidth = 1, BackBufferHeight = 1, DeviceWindowHandle = renderForm.Handle })) { try { DirectXFunctions.TableEntries.AddRange(VirtualFunctionTable.GetObjectVTableAddresses(device.NativePointer, Enum.GetNames(typeof(Direct3DDevice9Ex)).Length)); SupportsDirect3D9Ex = true; } catch { SupportsDirect3D9Ex = false; } } }
public void TestVTableHook() { var vTable = VirtualFunctionTable.FromAddress(_nativeCalculator.VTable, 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); 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); } _addHook = vTable.CreateFunctionHook <NativeCalculator.AddFunction>((int)NativeCalculator.VTableFunctions.Add, addHook).Activate(); _subHook = vTable.CreateFunctionHook <NativeCalculator.SubtractFunction>((int)NativeCalculator.VTableFunctions.Subtract, subHook).Activate(); _multiplyHook = vTable.CreateFunctionHook <NativeCalculator.MultiplyFunction>((int)NativeCalculator.VTableFunctions.Multiply, mulHook).Activate(); _divideHook = vTable.CreateFunctionHook <NativeCalculator.DivideFunction>((int)NativeCalculator.VTableFunctions.Divide, divHook).Activate(); 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)); } } }
/// <summary> /// Constructor for the DX11 hooking class. /// Creates the Direct3D11 device and DXGI swapchain inside the function to get their /// native pointer for hooking purposes. /// </summary> public DX11Hook() { /* * Target: Obtain the pointer to the ID3D11Device and IDXGISwapChain instances * by creating our own blank windows form and creating a ID3D11Device with Swapchain * targeting that form. The returned device should be the same one as used by the game. */ // Declare the Swapchain, Windows form, DX11 device. Form renderForm = new Form(); SwapChain dxgiSwapChain; Device dx11Device; // Create the Device and SwapChain Device.CreateWithSwapChain( DriverType.Hardware, DeviceCreationFlags.BgraSupport, new SharpDX.DXGI.SwapChainDescription { BufferCount = 1, Flags = SharpDX.DXGI.SwapChainFlags.None, IsWindowed = true, ModeDescription = new SharpDX.DXGI.ModeDescription(100, 100, new Rational(60, 1), SharpDX.DXGI.Format.R8G8B8A8_UNorm), OutputHandle = renderForm.Handle, SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0), SwapEffect = SharpDX.DXGI.SwapEffect.Discard, Usage = SharpDX.DXGI.Usage.RenderTargetOutput }, out dx11Device, out dxgiSwapChain ); // Get our VTable function pointers. DirectX11DeviceFunctions = new VirtualFunctionTable(dx11Device.NativePointer, Enum.GetNames(typeof(ID3D11Device)).Length); DXGISwapChainFunctions = new VirtualFunctionTable(dxgiSwapChain.NativePointer, Enum.GetNames(typeof(IDXGISwapChain)).Length); // Dispose of the native objects. renderForm.Dispose(); dxgiSwapChain.Dispose(); dx11Device.Dispose();; }
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 VirtualFunctionTableFromAddress(IntPtr tableAddress, int numberOfMethods) => VirtualFunctionTable.FromAddress(tableAddress, numberOfMethods);
public IVirtualFunctionTable VirtualFunctionTableFromObject(IntPtr objectAddress, int numberOfMethods) => VirtualFunctionTable.FromObject(objectAddress, numberOfMethods);
public unsafe void TestExternalVTableCallAfterFunctionHookButWithDirectCall() { 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 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 TestVTableCallsAfterHookingVTablePointer var vTableHook = HookedObjectVirtualFunctionTable.FromObject(fakeObject.ToUnsigned(), 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(); // In this test we access our vtable directly // As the vtable itself is never changed, this should not hook any functions var vTable = VirtualFunctionTable.FromAddress(_nativeCalculator.VTable, 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; 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)); } } }