Direct3DCreate9 - Hook fail

10/30/2010 17:11 xNopex#1
Hallo ihr mehr oder weniger begabten Leute,

Ich brauche Hilfe. Und zwar wollte ich ein bisschen mit dem D3D-Hooking rumspielen und habe mich daran gemacht die im Titel beschriebene Funktion zu entern, um mir die Adresse ihres return Wertes zu schnappen, um dann weiter zu verfahren, ihr kennt das bestimmt alle. Habe mir dazu eine schöne, schnuckelige kleine Klasse geschrieben und will das ganze bei WarRock testen. Kenn mich da nicht aus, wenn mich jemand schlägt, weil Warrock D3D8 ist, oder weiß was ich was die ENtwickler da machen, dann kann er das ja in seinem Lösungsvorschlag berücksichtigen.
So, wo liegt das eigentliche Problem? Tjoa.. Ich gelange zwar an die Adresse des Objekts, aber kurz darauf stürzt Warrock immer ab. Ohne Fehlermeldung, nichts. Zur Idee: Ich hole mir die Adresse zu Direct3DCreate9, wird ja exportiert, überschreibe die ersten 5Bytes, sodass man, wenn die Funktion aufgerufen wird, zu meiner Funktion springt, in der ich die überschriebenen Bytes der Originalfunktion wieder mit den ürsprünglichen überschreibe, sodass eig. alles wie vorher sein müsste. In der Funktion rufe ich dann die Original Funktion auf, speichere ihren return-Wert in einem Zeiger und returne dann meinen Zeiger zurück zu Warrock.
Ich finde das klingt von der Theorie sehr schön, und wenn ich von meiner Funktion NULL returne, dann spuckt mir warrock auch ne nette Fehlermeldung aus, dass das Objekt nicht erstellt werden konnte. Also alles, wie geplant. Nur scheint die Adresse, die ich returne, doch iwie nicht zu stimmen, weil Warrock, wie gesagt, einfach mal so abkackt. Auch nach längerer Fehleranalyse bin ich zu keinem Ergebniss gekommen.

Also ich hoffe ich treffe hier auf jemanden, der mir erklären kann, wo mein Denkfehler liegt. Falls den jemand sehen will, mein bisheriger Sourcecode von den wichtigen Stellen (leider weder auskommentiert, noch optimiert):

Code:
#include "d3dHook.h"

#pragma comment( lib, "d3d9.lib" )
typedef IDirect3D9* (CALLBACK* OrigDirect3DCreate9)(UINT);
D3D9HOOK* pObject = NULL;

IDirect3D9* MyD3DCreateFunc( UINT SDKVersion )
{
	IDirect3D9* pD3D9 = NULL;

	BYTE* pDirect3DCreate9 = pObject->GetDirect3DCreate9Pointer();
	BYTE* memoryBackup = pObject->GetMemoryBackup();
	HMODULE hD3D9 = pObject->GetD3D9Module();

	if( pDirect3DCreate9 == NULL || memoryBackup == NULL || hD3D9 == NULL )
		return NULL;

	pDirect3DCreate9[0] = memoryBackup[0];
	pDirect3DCreate9[1] = memoryBackup[1];
	pDirect3DCreate9[2] = memoryBackup[2];
	pDirect3DCreate9[3] = memoryBackup[3];
	pDirect3DCreate9[4] = memoryBackup[4];

	OrigDirect3DCreate9 pOrigFunc = OrigDirect3DCreate9( GetProcAddress( hD3D9, "Direct3DCreate9" ) );
	pD3D9 = pOrigFunc( SDKVersion );
	pObject->SetD3D9Object( pD3D9 );
	return pD3D9;
}


D3D9HOOK :: D3D9HOOK()
{
	this->pD3D9 = NULL;
	this->hD3D9 = NULL;
	this->pDirect3DCreate9 = NULL;
	ZeroMemory( this->memoryBackup, 5 );
}


bool D3D9HOOK :: CreateHook()
{
	try
	{
		if( ! this->GetD3D9ModuleHandle() )
			throw( DWORD( ERR_INVALID_MODULE_HANDLE ) );
		
		if( ! this->GetD3D9CreatePointer() )
			throw( DWORD( ERR_INVALID_POINTER ) );

		this->TryToInstallJump();
		this->WaitForSingleObject();

	}catch( DWORD err )
	{
		switch( err )
		{
		case ERR_INVALID_MODULE_HANDLE:
			break;
		case ERR_INVALID_POINTER:
			break;
		}
		return false;
	}

	return true;
}


bool D3D9HOOK :: GetD3D9ModuleHandle()
{
	this->hD3D9 = NULL;
	for( DWORD i = 0; i < 40 && this->hD3D9 == NULL; i++ )
	{
		this->hD3D9 = GetModuleHandle( L"d3d9.dll" );
		Sleep( 250 );
	}

	if( this->hD3D9 == NULL )
		return false;

	return true;
}


bool D3D9HOOK :: GetD3D9CreatePointer()
{
	BYTE* pTemp = (BYTE*)(GetProcAddress( this->hD3D9, "Direct3DCreate9" ));
	if( pTemp == NULL )
		return false;

	this->pDirect3DCreate9 = pTemp;
	return true;
}


void D3D9HOOK :: TryToInstallJump()
{
	pObject = this;
	DWORD dwOld;
	DWORD p_dwMyFunc = DWORD(&MyD3DCreateFunc);
	VirtualProtect( pDirect3DCreate9, 5, PAGE_READWRITE, &dwOld );

	this->memoryBackup[0] = this->pDirect3DCreate9[0];
	this->memoryBackup[1] = this->pDirect3DCreate9[1];
	this->memoryBackup[2] = this->pDirect3DCreate9[2];
	this->memoryBackup[3] = this->pDirect3DCreate9[3];
	this->memoryBackup[4] = this->pDirect3DCreate9[4];

	this->pDirect3DCreate9[0] = 0xE9;
	*(DWORD*)(this->pDirect3DCreate9+1) = DWORD( p_dwMyFunc-(DWORD(this->pDirect3DCreate9))-5 );
}

void D3D9HOOK :: WaitForSingleObject()
{
	while( this->pD3D9 == NULL )
	{
		Sleep( 250 );
	}
	OutputDebugStr( L"---proxy:IDirect3D9-Object erhalten!!" );
}


HMODULE D3D9HOOK :: GetD3D9Module()
{
	return this->hD3D9;
}

BYTE* D3D9HOOK :: GetDirect3DCreate9Pointer()
{
	return this->pDirect3DCreate9;
}

BYTE* D3D9HOOK :: GetMemoryBackup()
{
	return this->memoryBackup;
}

void D3D9HOOK :: SetD3D9Object( IDirect3D9* pPara )
{
	this->pD3D9 = pPara;
}
10/30/2010 17:49 ms​#2
Quote:
Originally Posted by xNopex View Post
Code:
VirtualProtect( pDirect3DCreate9, 5, PAGE_READWRITE, &dwOld );
Müsste es hier nicht PAGE_EXECUTE_READWRITE heißen? Du veränderst ja was im Code. Aber wenn du sagst, dass er nicht crasht wenn du NULL returnst, sollte es eigentlich nicht daran liegen.

Quote:
Originally Posted by xNopex View Post
Code:
OrigDirect3DCreate9 pOrigFunc = OrigDirect3DCreate9( GetProcAddress( hD3D9, "Direct3DCreate9" ) );
pD3D9 = pOrigFunc( SDKVersion );
Callst du hier vielleicht mit der falschen Calling-Convention?
10/30/2010 18:14 xNopex#3
Die Calling-Convention sollte stimmen. Habe den Prototyp gemäß MSDN-Eintrag definiert. [Only registered and activated users can see links. Click Here To Register...]
10/30/2010 18:23 ms​#4
Dann kann ich mir auch nicht erklären warum es nicht funktioniert, außer vielleicht das mit dem VirtualProtect.

Code:
#include <iostream>
#include <d3d9.h>

typedef IDirect3D9 *(CALLBACK *OrigDirect3DCreate9)(UINT);

using namespace std;

int main()
{
    Direct3DCreate9(D3D_SDK_VERSION); //damit die DLL überhaupt erst geladen wird
    OrigDirect3DCreate9 pOrigFunc = OrigDirect3DCreate9(GetProcAddress(GetModuleHandle("d3d9.dll"), "Direct3DCreate9"));
    cout << hex << (uint32_t)pOrigFunc << endl;
    IDirect3D9 *pD3D9 = pOrigFunc(D3D_SDK_VERSION);
    cout << hex << (uint32_t)pD3D9 << endl;
    cout << pD3D9->GetAdapterCount() << endl;
    return 0;
}
Wenn ich deinen Code in MinGW teste funktioniert alles.
10/30/2010 18:32 xNopex#5
Dass es am Compiler von Microsoft liegt möchte ich iwie nicht glauben. Gerade Ausprobiert: Mit PAGE_EXECUTE_READWRITE - Rechten stürzt es ebenfalls ab. Einfach so. Keine Meldung, nichts.
10/30/2010 18:43 ms​#6
Dass es an Visual Studio liegt hab ich auch gar nicht behauptet, ich hab VS nur im Moment nicht installiert.

Mir ist aber gerade was anderes aufgefallen. Dein Detour (MyD3DCreateFunc) müsste ja auch die selbe Calling-Convention haben.

Code:
IDirect3D9* [B][COLOR="Red"]CALLBACK[/COLOR][/B] MyD3DCreateFunc(UINT SDKVersion)
Wenns immernoch nicht funktioniert, dann weiß ich auch nicht woran es liegt.
10/30/2010 18:49 xNopex#7
v.v Es geht :)
Dankesehr, da wäre ich von alleine dummerweise niemals drauf gekommen.