Addresse von D3dendScene bekommen



  • moin!
    ich möchte gerne einen DetourFunc auf IDirect3DDevice9::EndScene setzen.
    so mache ich das zurzeit:

    DetourFunction((PBYTE)0x4FDD71B0, (PBYTE)EndScene_detour);
    

    das funktioniert zwar, aber kann ich annehmen, dass die Addresse überall die gleiche ist? Auch auf Vista? Ich habe schon versucht mit GetProcAddress die Addresse zu bekommen aber das klappt irgendwie nicht mit EndScene



  • Ich denke, du solltest lieber Direct3DCreate9() hooken, dann hast du das Interface und kannst weitere Funktionen wie ->CreateDevice() hooken und bekommst alles, was du willst.



  • nein ich will EndScene hooken und will die Addresse davon bekommen



  • Ja, EndScene kannst du dann sicher hooken.
    Ich kann mir nicht vorstellen, wie du ohne Interface eine Memberfunktion hooken willst.
    Die ändert sich bestimmt pro Anwendung, und vllt. pro Betriebssystem, keine Ahnung.
    Aber der sichere Weg ist:

    Direct3DCreate9() hooken -> IDirect3D9 Interface hooken

    Dann in IDirect3D9::CreateDevice() das IDirect3DDevice9 Interface hooken

    Und schon hast du HookIDirect3DDevice9::EndScene(), von dem aus du dann die Original EndScene() aufrufst.

    Google mal nach "d3d starterkit v3.0".



  • hört sich sehr aufwendig an, gibt es da nix leichteres o_O



  • Naja, mehr oder weniger aufwendig.
    Hast du den starter kit gecheckt?

    Achtung Halbwissen:

    Wenn du willst, dass du immer die richtige Adresse kriegst, kommst du um komplette Interface-Hooks nicht herum.

    Eine Klassenfunktion braucht ja ein Objekt, damit sie aufgerufen werden kann. Und dieses Objekt musst du dir halt holen.



  • Guten Abend,

    also man muss ned unbedingt das Direct3DCreate9() usw hooken, da ja die Offsets der Funktionen relative zur Dllbase gleich bleiben. Soll heissen wenn z.B. das EndScene vom Device Interface beim Offset 0xabcde in einer Testanwendung liegt, liegt diese immer auf 0xabcde. Ich hab au mal versucht DirectX zu hooken und hab mir damals eine Testanwendung geschrieben die die Offsets in die Registry schreibt. Hat alles wunderbar geklappt.

    Und was soll das mit einem Objekt zu tun haben. Eine Memberfunktion is ja au nur ein Fuktion die zusaetzlich eine "this-Pointer" mit den Klassen relevanten Daten als ersten Parameter nimmt. Und sobald du eine Funktion gehookt hast kannste dir halt Addresse des "this-Pointers" speichern und hast zusaetzlich dein Objekt fallste das brauchst.

    Und hier noch ein Codeausschnitt von mir:

    hdEndScene.pvOrginalFunc = (PVOID) ((DWORD)dwDXDllBase+ GetOffset(DX_9,"Device", "EndScene")); /*getoffset holt das offset aus der reg*/
    ....
    typedef enum dx_ver{ DX_8 = 8, DX_9 = 9} DX_VER;
    #define SAVE_OFFSET(BASE,VER,IF_NAME,IF_POINTER,IF_FUNC) SaveOffset(VER, IF_NAME, ""#IF_FUNC, (DWORD)((unsigned char*)IF_POINTER->lpVtbl->IF_FUNC - BASE)) /*SaveOffset speichert das Offset in die reg
    
    if( (dwDXDllBase = (DWORD) GetModuleHandle("d3d9.dll")) != NULL)
    
    SAVE_OFFSET(dwDXDllBase,DX_9,"Device",d3ddev,Reset);
    

    Wie man sieht alles in C geschriebn, aber ich denk das kann man in C++ genaus umsetzen.

    Peace & Blessd Love C0de4Fun



  • Aber die Funktionsadresse IDirect3DDevice9::EndScene() der Anwendung, in der IDirect3DDevice9 verwendet wird, variiert doch (jenachdem, wo die DLL in der Anwendung die Basis hat), oder?
    Mist, habe viel zu wenig Grundwissen.



  • Help0r schrieb:

    Aber die Funktionsadresse IDirect3DDevice9::EndScene() der Anwendung, in der IDirect3DDevice9 verwendet wird, variiert doch (jenachdem, wo die DLL in der Anwendung die Basis hat), oder?
    Mist, habe viel zu wenig Grundwissen.

    joa genau deswegen hab ich ja die Offsets gespeichert ;).

    Gruess C0de4Fun



  • Achso, also mir wurde gesagt, ohne Interface kann ich auch keine (COM-)Methoden hooken.
    (Wahrscheinlich) wieder was gelernt.



  • Help0r schrieb:

    Achso, also mir wurde gesagt, ohne Interface kann ich auch keine (COM-)Methoden hooken.
    (Wahrscheinlich) wieder was gelernt.

    joa ansich haste da schon recht sage ich mal. Grad bei wechselnder Version z.B. 9.b und 9.c sag ich mal sind hardcoded values ned schoen. Deswegen hab ich das in ein Programm ausgelagert das mir die Offsets der jeweiligen Funktion die ich brauch in die Registry speichert. Klar erstellt ich da au ein DDevice usw. aber wird beim hooken dann nicht mehr benoetigt.

    Ich kann dir au mal mein Bspl posten wo ich die Zeit anzeige:

    #include <windows.h>
    #include <Psapi.h>
    #include <stdio.h>
    #include <time.h>
    #include <d3d9.h>
    #include <d3dx9.h>
    #include "Log.h"
    #include "Hook.h"
    #include "DXOffset.h"
    
    #pragma comment(lib, "Psapi.lib")
    
    #define LOG TEXT("./HookLog.log")
    
    typedef HRESULT (__stdcall *FPCREATEFONT) (LPDIRECT3DDEVICE9, int, UINT, UINT, UINT,  BOOL,
    										   DWORD, DWORD, DWORD, DWORD, LPCTSTR, LPD3DXFONT *);
    typedef HRESULT (__stdcall *FPENDSCENE) (LPDIRECT3DDEVICE9);
    typedef LPDIRECT3D9 (__stdcall *FPDIRECTXCREATE) (UINT);
    
    BOOL DoHookProcess(void);
    
    HANDLE g_hLog;
    HANDLE g_hD3D9;
    HINSTANCE g_hInst;
    LPD3DXFONT dxfont;
    LPDIRECT3DDEVICE9 dxDevice;
    
    FPCREATEFONT fpCreateFont;
    FPDIRECTXCREATE fpCreateDirectX;
    
    FPENDSCENE fpOldEndScene;
    
    BOOL g_bShow;
    
    DWORD g_dwCount;
    
    BOOL GetFunction(void)
    {
    	HANDLE hDllCreateFont;
    	HMODULE haDlls[128];
    	HANDLE hCurProc = GetCurrentProcess();
    	DWORD dwNeeded;
    	DWORD dwWholeLen;
    	DWORD dwLen;
    
    	char szDllName[MAX_PATH];
    	int i = 0;
    
    	BOOL bError = FALSE;
    
    	if(EnumProcessModules(hCurProc, haDlls, 128*sizeof(HMODULE), &dwNeeded))
    	{
    		while(i < (dwNeeded / sizeof(HMODULE)))
    		{
    			GetModuleFileNameA(haDlls[i], szDllName, MAX_PATH);
    
    			dwWholeLen = strlen(szDllName);
    			dwLen = 0;
    			while( szDllName[dwWholeLen--] != '\\')
    				dwLen++;
    
    			memcpy(szDllName, &szDllName[dwWholeLen+2], dwLen+1);
    			if( memcmp(szDllName, "d3dx9", 5) == 0)
    			{
    				hDllCreateFont = haDlls[i];
    				break;
    			}
    			i++;
    		}
    
    		if( hDllCreateFont != NULL)
    		{
    			fpCreateFont = (FPCREATEFONT) GetProcAddress(hDllCreateFont, "D3DXCreateFontA");
    
    			if(fpCreateFont != NULL)
    				return TRUE;
    		}
    
    	}
    
    	return FALSE;
    }
    
    BOOL APIENTRY DllMain( HINSTANCE hInstance, DWORD  ul_reason_for_call, LPVOID lpReserved)
    {
    	HANDLE hDll;
    	BOOL bError;
    	char szLog[128] = "";
    
    	switch (ul_reason_for_call)
    	{
    		case DLL_PROCESS_ATTACH:
    		{
    			g_bShow = TRUE;
    			dxDevice = NULL;
    			g_hInst = hInstance;
    			dxfont = NULL;
    			g_dwCount = 0;
    			g_dwHideCur = 0;
    			g_hLog = OpenLog(LOG);
    			APPEND_A(LOG_TEXT_A("<----------->Start Logging<----------->"));
    			if( (g_hD3D9 = GetModuleHandle("d3d9.dll")) != NULL)
    			{
    				if(GetFunction())
    					return DoHookProcess();
    				else
    				{
    					sprintf(szLog, "eror get func: %u\r\n", GetLastError());
    					APPEND_A(szLog);
    				}
    			}
    			else
    				APPEND_A(LOG_TEXT_A("d3d9.dll isnt loaded"));
    
    			return FALSE;
    		}
    
    		case DLL_THREAD_ATTACH:
    			APPEND_A(LOG_TEXT_A("DLL_THREAD_ATTACH"));
    			break;
    		case DLL_THREAD_DETACH:
    			APPEND_A(LOG_TEXT_A("DLL_THREAD_DETACH"));
    			break;
    
    		case DLL_PROCESS_DETACH:
    		{	
    
    			RemoveHooks();
    			APPEND_A(LOG_TEXT_A("<----------->End Logging<----------->"));			
    			CloseLog(g_hLog);
    			break;
    		}
    
    	}
    	return TRUE;
    }
    
    HRESULT __stdcall NewEndScene(LPDIRECT3DDEVICE9 pDevice)
    {
    	RECT textbox; 
    	time_t CurTime;
    	struct tm* timeinfo;
    	char szTime[64];
    
    	if( GetAsyncKeyState(VK_F7) & 1)
    	{
    		if(g_dwHideCur < 6)
    			g_dwHideCur++;
    		else
    			g_dwHideCur = 0;
    	}
    
    	if( GetAsyncKeyState(VK_F6) & 1)
    		g_bRenderInWireFrame = !g_bRenderInWireFrame;
    
    	if(dxfont == NULL)
    	{
    		//dxDevice = pDevice;
    		fpCreateFont(pDevice,    // the D3D Device
                       30,    // font height of 30
                       0,    // default font width
                       FW_NORMAL,    // font weight
                       1,    // not using MipLevels
                       TRUE,    // italic font
                       DEFAULT_CHARSET,    // default character set
                       OUT_DEFAULT_PRECIS,    // default OutputPrecision,
                       DEFAULT_QUALITY,    // default Quality
                       DEFAULT_PITCH | FF_DONTCARE,    // default pitch and family
                       TEXT("Arial"),    // use Facename Arial
                       &dxfont);    // the font object
    
    	}
    	else
    	{
    		if(g_bShow)
    		{
    			time(&CurTime);
    			timeinfo = localtime(&CurTime);
    			sprintf(szTime, "%02i:%02i:%02i", timeinfo->tm_hour, timeinfo->tm_min,
    				timeinfo->tm_sec);
    			SetRect(&textbox, 100, 100, 300, 300); 
    
    			dxfont->lpVtbl->DrawTextA(dxfont, NULL,
    					  szTime,
    					  8,
    					  &textbox,
    					  DT_VCENTER,
    					  D3DCOLOR_ARGB(175, 255, 255, 255));
    		}
    	}
    
    	return fpOldEndScene(pDevice);
    }
    
    BOOL DoHookProcess(void)
    {
    	HOOK_DATA hdEndScene;
    
    	memset(&hdEndScene, 0, sizeof(hdEndScene));
    
    	strcpy(hdEndScene.szDllName, "D3DX9_41.dll");
    	strcpy(hdEndScene.szFunctionName, "EndScene");
    	hdEndScene.pvInsteadFunc = (PVOID) &NewEndScene;
    	hdEndScene.pvOrginalFunc = (PVOID) ((DWORD)g_hD3D9 + GetOffset(DX_9,"Device", "EndScene")); /*hier dll base von d3d9.dll + das offset aus der reg*/
    
    	fpOldEndScene = (FPENDSCENE) HookFunction(&hdEndScene); /* selbst geschriebene Hook Funktion die ein einfachen jmp hook implementiert*/
    
    	return TRUE;
    }
    

    Vielleicht hilfts dir ja ein bissle ;).
    Wenn noch Fragen da sind sag bescheid.

    Peave & Blessed Love C0de4Fun


Anmelden zum Antworten