.NET 4.x Реализовать хук на D3D9 (DirectX9), чтобы выводить сообщения в чужом окне (игре) - C#
Формулировка задачи:
Здравствуйте уважаемые гуру дотНЕТа.
Помогите плиз.
Хочу реализовать хук на D3D9 (DirectX9), чтобы выводит сообщения в чужом окне (игре) из моего программы.
Для этого нашел пример и взял нужную часть кода, но он то работает то не работает, и даже если заработает, через некоторые время игра кращится, в чем причина?
using System.Threading; using System.Runtime.InteropServices; using EasyHook; using System.Windows.Forms; using System.Diagnostics; using SharpDX.Direct3D9; public class Main : EasyHook.IEntryPoint { Device device; const int D3D9_DEVICE_METHOD_COUNT = 119; const int D3D9Ex_DEVICE_METHOD_COUNT = 15; bool _supportsDirect3D9Ex = false; LocalHook Direct3DDevice_EndSceneHook = null; LocalHook Direct3DDevice_ResetHook = null; LocalHook Direct3DDevice_PresentHook = null; LocalHook Direct3DDeviceEx_PresentExHook = null; List<IntPtr> id3dDeviceFunctionAddresses = new List<IntPtr>(); protected List<LocalHook> Hooks = new List<LocalHook>(); FileMonInterface Interface; public Main(RemoteHooking.IContext InContext, String InChannelName) { Interface = EasyHook.RemoteHooking.IpcConnectClient<FileMonInterface>(InChannelName); Interface.Ping(); } public void Run(RemoteHooking.IContext InContext, String InChannelName) { id3dDeviceFunctionAddresses = new List<IntPtr>(); using (Direct3D d3d = new Direct3D()) { using (var renderForm = new System.Windows.Forms.Form()) { using (device = new Device(d3d, 0, DeviceType.NullReference, IntPtr.Zero, CreateFlags.HardwareVertexProcessing, new PresentParameters() { BackBufferWidth = 1, BackBufferHeight = 1, DeviceWindowHandle = renderForm.Handle })) { id3dDeviceFunctionAddresses.AddRange(GetVTblAddresses(device.NativePointer, D3D9_DEVICE_METHOD_COUNT)); } } } try { using (Direct3DEx d3dEx = new Direct3DEx()) { using (var renderForm = new System.Windows.Forms.Form()) { using (var deviceEx = new DeviceEx(d3dEx, 0, DeviceType.NullReference, IntPtr.Zero, CreateFlags.HardwareVertexProcessing, new PresentParameters() { BackBufferWidth = 1, BackBufferHeight = 1, DeviceWindowHandle = renderForm.Handle }, new DisplayModeEx() { Width = 800, Height = 600 })) { id3dDeviceFunctionAddresses.AddRange(GetVTblAddresses(deviceEx.NativePointer, D3D9_DEVICE_METHOD_COUNT, D3D9Ex_DEVICE_METHOD_COUNT)); _supportsDirect3D9Ex = true; } } } } catch (Exception ex) { _supportsDirect3D9Ex = false; MessageBox.Show( ex.ToString()); } Direct3DDevice_EndSceneHook = LocalHook.Create( id3dDeviceFunctionAddresses[(int)d3d9_indexes.Direct3DDevice9FunctionOrdinals.EndScene], new Direct3D9Device_EndSceneDelegate(EndSceneHook), this); unsafe { if (_supportsDirect3D9Ex) { Direct3DDeviceEx_PresentExHook = LocalHook.Create( id3dDeviceFunctionAddresses[(int)d3d9_indexes.Direct3DDevice9ExFunctionOrdinals.PresentEx], new Direct3D9DeviceEx_PresentExDelegate(PresentExHook), this); } Direct3DDevice_PresentHook = LocalHook.Create( id3dDeviceFunctionAddresses[(int)d3d9_indexes.Direct3DDevice9FunctionOrdinals.Present], new Direct3D9Device_PresentDelegate(PresentHook), this); } Direct3DDevice_ResetHook = LocalHook.Create( id3dDeviceFunctionAddresses[(int)d3d9_indexes.Direct3DDevice9FunctionOrdinals.Reset], new Direct3D9Device_ResetDelegate(ResetHook), this); Direct3DDevice_EndSceneHook.ThreadACL.SetExclusiveACL(new Int32[1]); Hooks.Add(Direct3DDevice_EndSceneHook); Direct3DDevice_PresentHook.ThreadACL.SetExclusiveACL(new Int32[1]); Hooks.Add(Direct3DDevice_PresentHook); if (_supportsDirect3D9Ex) { Direct3DDeviceEx_PresentExHook.ThreadACL.SetExclusiveACL(new Int32[1]); Hooks.Add(Direct3DDeviceEx_PresentExHook); } Direct3DDevice_ResetHook.ThreadACL.SetExclusiveACL(new Int32[1]); Hooks.Add(Direct3DDevice_ResetHook); } protected IntPtr[] GetVTblAddresses(IntPtr pointer, int numberOfMethods) { return GetVTblAddresses(pointer, 0, numberOfMethods); } protected IntPtr[] GetVTblAddresses(IntPtr pointer, int startIndex, int numberOfMethods) { List<IntPtr> vtblAddresses = new List<IntPtr>(); IntPtr vTable = Marshal.ReadIntPtr(pointer); for (int i = startIndex; i < startIndex + numberOfMethods; i++) vtblAddresses.Add(Marshal.ReadIntPtr(vTable, i * IntPtr.Size)); // using IntPtr.Size allows us to support both 32 and 64-bit processes return vtblAddresses.ToArray(); } [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)] delegate int Direct3D9Device_EndSceneDelegate(IntPtr device); bool _isUsingPresent = false; int EndSceneHook(IntPtr devicePtr) { Device device = (Device)devicePtr; if (!_isUsingPresent) DoCaptureRenderTarget(device, "EndSceneHook"); device.EndScene(); return SharpDX.Result.Ok.Code; } ..................... // ТУТ УБРАЛ НЕКОТОРЫЕ КОДЫ КОТОРЫЕ СЧИТАЛ НЕ НУЖНЫМ, ИЗ ЗА ОГРАНИЧЕНИЕ НА ФОРУМЕ ..................... [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)] delegate int Direct3D9Device_ResetDelegate(IntPtr device, ref PresentParameters presentParameters); object _lockRenderTarget = new object(); Surface _renderTarget; int ResetHook(IntPtr devicePtr, ref PresentParameters presentParameters) { //Device device = (Device)devicePtr; try { lock (_lockRenderTarget) { if (_renderTarget != null) { _renderTarget.Dispose(); _renderTarget = null; } } device.Reset(presentParameters); return SharpDX.Result.Ok.Code; } catch (SharpDX.SharpDXException sde) { return sde.ResultCode.Code; } catch (Exception e) { MessageBox.Show(e.ToString()); return SharpDX.Result.Ok.Code; } } void DoCaptureRenderTarget(Device device, string hook) { try { FontDescription f = new FontDescription() { Height = 16, FaceName = "Arial", Italic = false, Width = 0, MipLevels = 1, CharacterSet = FontCharacterSet.Default, OutputPrecision = FontPrecision.Default, Quality = FontQuality.Antialiased, PitchAndFamily = FontPitchAndFamily.Default | FontPitchAndFamily.DontCare, Weight = FontWeight.Bold }; SharpDX.Direct3D9.Font font1 = new Font(device, f); font1.DrawText(null, "Hooked", 50, 60, new SharpDX.ColorBGRA(255f,100f,100f,1f)); } catch (Exception e) { MessageBox.Show(e.ToString()); } }
Решение задачи: «.NET 4.x Реализовать хук на D3D9 (DirectX9), чтобы выводить сообщения в чужом окне (игре)»
textual
Листинг программы
#include "stdafx.h" #include <windows.h> #include <cstdio> #include <d3d9.h> #include <d3dx9.h> #pragma comment(lib, "d3d9.lib") #pragma comment(lib, "d3dx9.lib") /*Color's*/ #define GREEN D3DCOLOR_ARGB(255, 000, 255, 000)//Trans(250=SOLID,0=INVISIBLE),Red,Green,Blue #define BLUE D3DCOLOR_ARGB(255, 000, 000, 255) LPD3DXFONT m_font = NULL; boolean DrawMessage(LPD3DXFONT font, unsigned int x, unsigned int y, int alpha, unsigned char r, unsigned char g, unsigned char b, LPCSTR Message) { // Create a colour for the text D3DCOLOR fontColor = D3DCOLOR_ARGB(alpha, r, g, b); RECT rct; //Font rct.left=x; rct.right=150; rct.top=y; rct.bottom=rct.top+150; font->DrawTextA(NULL, Message, -1, &rct, 0, fontColor); return true; } //======ВОТ ТУТ void stuff(LPDIRECT3DDEVICE9 pDevice, D3DCOLOR Color) //Crosshair function by: Hans211 { // D3DCOLOR rectColor = D3DCOLOR_XRGB(255,0,255); //No point in using alpha because clear & alpha dont work! // D3DRECT BarRect = { 10, 10, 40, 40 }; // pDevice->Clear(1,&BarRect, D3DCLEAR_TARGET | D3DCLEAR_TARGET ,rectColor,0,0); DrawMessage(m_font,40,40,255,255,0,255, "Привет, Мир!"); } //======ВОТ ТУТ void *DetourFunc(BYTE *src, const BYTE *dst, const int len) // Old detour from GD Forums. { BYTE *jmp = (BYTE*)malloc(len+5); DWORD dwback; VirtualProtect(src, len, PAGE_READWRITE, &dwback); memcpy(jmp, src, len); jmp += len; jmp[0] = 0xE9; *(DWORD*)(jmp+1) = (DWORD)(src+len - jmp) - 5; src[0] = 0xE9; *(DWORD*)(src+1) = (DWORD)(dst - src) - 5; VirtualProtect(src, len, dwback, &dwback); return (jmp-len); } typedef HRESULT(__stdcall* EndScene_)(LPDIRECT3DDEVICE9); EndScene_ pEndScene;//our define typedef HRESULT (WINAPI* Reset_) (LPDIRECT3DDEVICE9 pDevice, D3DPRESENT_PARAMETERS* pPresentationParameters); Reset_ pReset; /*Hooked Endscene*/ HRESULT __stdcall EndScene(LPDIRECT3DDEVICE9 pDevice) {//Calling our Hook.EndScene makes us able to draw. D3DXCreateFont( pDevice, 17, 0, FW_BOLD, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("Arial"), &m_font ); stuff(pDevice,BLUE); //Drawing return pEndScene(pDevice); } /*Tools for Hooking by Gordon`*/ bool bCompare(const BYTE* pData, const BYTE* bMask, const char* szMask)//by Gordon` { for(;*szMask;++szMask,++pData,++bMask) if(*szMask=='x' && *pData!=*bMask) return 0; return (*szMask) == NULL; } DWORD FindPattern(DWORD dwAddress,DWORD dwLen,BYTE *bMask,char * szMask)//by Gordon` { for(DWORD i=0; i<dwLen; i++) if (bCompare((BYTE*)(dwAddress+i),bMask,szMask)) return (DWORD)(dwAddress+i); return 0; } DWORD GetAddressPtr(int index) //by Gordon` { DWORD* VTableStart = 0; DWORD dwDevicePointer = FindPattern((DWORD)GetModuleHandle(L"d3d9.dll"), 0x1280000, (PBYTE)"\xC7\x06\x00\x00\x00\x00\x89\x86\x00\x00\x00\x00\x89\x86", "xx????xx????xx"); memcpy(&VTableStart, (void*)(dwDevicePointer+2), 4); return VTableStart[index]; } DWORD FindDevice(DWORD Len)//by Gordon` { DWORD dwObjBase = 0; dwObjBase = (DWORD)LoadLibrary(L"D3D9.DLL"); while (dwObjBase++ < dwObjBase + Len) { if ( (*(WORD*)(dwObjBase + 0x00)) == 0x06C7 && (*(WORD*)(dwObjBase + 0x06)) == 0x8689 && (*(WORD*)(dwObjBase + 0x0C)) == 0x8689 ) { dwObjBase += 2; break; } } return( dwObjBase ); } /*The Hook*/ void Hook() { PDWORD VTable; *(DWORD*)&VTable = *(DWORD*)FindDevice(0x128000); pEndScene = ( EndScene_ )DetourFunc((PBYTE) VTable[42],(PBYTE)EndScene, 5);//Hooking our endscene Sleep( 100 ); } /*DLL Main*/ int WINAPI DllMain(HINSTANCE hInst,DWORD reason,LPVOID reserved) { switch(reason) { case DLL_PROCESS_ATTACH: CreateThread(0, 0, (LPTHREAD_START_ROUTINE) Hook, 0, 0, 0);//Starting our Hook break; } return true; }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д