[Problem] D3D9-Hook funzt nur manchmal

01/30/2012 01:26 Jeoni#1
Hallo Leute,
ich wende mich voller Verzweifelung an euch, da mal wieder etwas nicht funktioniert. :o
Ich habe gerade einen D3D9 Endscene Hook aus dem Tutorial von SilverDeath fertiggestellt.
Ich habe den vom Autor empfohlenen Injector benutzt, um meine DLL in ein D3D9-Testprogramm (Credits an wen von ****) zu injizieren (im Anhang + [Only registered and activated users can see links. Click Here To Register...]). Am Anfang ist das Testprogramm immer wieder abgeschmiert. Erst als ich den "add_log"-Aufruf in der gehookten Funktion reingestellt habe, ist es nicht mehr abgeschmiert, sondern unverändert geblieben. Ich war gelinde gesagt sehr überrascht, da ich das Tutorial eigentlich genaustens befolgt habe. Auch hatte ich daran gedacht den Injector als Admin zu starten (nutze Win7 64Bit) und ich hatte es auch ausprobiert das Testprogramm als Admin zu starten. Als ich mal Olly an das Testprogramm gehangen habe und meine DLL dann injiziert hatte, ging es plötzlich (also das grüne Rechteck war wunderbar zu sehen).
Lange Rede, kurzer Sinn: ich habe keine Ahnung woran es scheitert oder wie man es behebt. Es wäre nett, wenn mir jemand helfen könnte.

Hier erstmal der Code (eig. nur C&P vom Tutorial, aber was hätt' ich denn groß verändern sollen?):
Code:
// dllmain.cpp : Defines the entry point for the DLL application.
#include "windows.h"
#include "stdafx.h"
#include <cstdio>
#include <time.h>
#include <d3d9.h>
#include <d3dx9.h>
#define _CRT_SECURE_NO_WARNINGS

void add_log(char* format, ...);
DWORD WINAPI HookThread(void);
void* DetourFunc(PBYTE src, const PBYTE dst, const int len);
DWORD dwFindPattern(DWORD dwAddress,DWORD dwLen,BYTE *bMask,char * szMask);
bool bDataCompare(const BYTE* pData, const BYTE* bMask, const char* szMask);

HRESULT __stdcall hkEndScene(LPDIRECT3DDEVICE9 pDevice);
typedef HRESULT(__stdcall* EndScene_t)(LPDIRECT3DDEVICE9);
EndScene_t pEndScene;

HANDLE tmpHandle = NULL;
HMODULE hModD3D9 = NULL;
FARPROC dwEndScene = NULL;
DWORD* VTableStart = NULL;
DWORD tempadd = NULL;
bool bMessageSent = false;
const D3DCOLOR txtGreen = D3DCOLOR_ARGB(255, 0, 255, 0);

BOOL APIENTRY DllMain( HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
	switch (ul_reason_for_call)
	{
		case DLL_PROCESS_ATTACH:
			add_log("==========LOG START==========");
			add_log("DLL Attached");
			add_log("Creating Thread...");
			tmpHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&HookThread, 0, 0, 0);
			if (!tmpHandle)
			{ 
				add_log("ThreadCreation Failed!");
			}
			break;
		case DLL_PROCESS_DETACH:
			add_log("DLL Detached");
			add_log("==========LOG END==========\n\n\n");
			break;
	}
	return TRUE;
}

DWORD WINAPI HookThread(void)
{ 
	add_log("Thread Created");
	while (!hModD3D9)
	{
		add_log("Searching d3d9.dll...");
		hModD3D9 = GetModuleHandle(L"d3d9.dll");
		Sleep(100);
	}
	add_log("Found d3d9.dll: %x !", hModD3D9);

	tempadd = dwFindPattern( (DWORD)hModD3D9, 0x128000, (PBYTE)"\xC7\x06\x00\x00\x00\x00\x89\x86\x00\x00\x00\x00\x89\x86", "xx????xx????xx");
	VTableStart = (DWORD*) *(DWORD*)(tempadd+2);
	dwEndScene = (FARPROC) VTableStart[42];
	add_log("Found EndScene: %x !", dwEndScene);
	pEndScene = (EndScene_t) DetourFunc((PBYTE) dwEndScene, (PBYTE)hkEndScene, 5);
	return 0;
}

HRESULT __stdcall hkEndScene(LPDIRECT3DDEVICE9 pDevice)
{
	if (bMessageSent == false)
	{
		add_log("Message from inner EndScene!");
		bMessageSent = true;
	}
	D3DRECT rect = {10, 10, 310, 310};
	pDevice->Clear(1, &rect, D3DCLEAR_TARGET, txtGreen, 0, 0);
	return pEndScene(pDevice);
}

void add_log(char* format, ...)
{ 
	HANDLE filehandle;
	DWORD dwReadBytes;
	char buffer[2048];
	char writebuffer[2048];
	va_list args;
	va_start(args, format);
	vsprintf (buffer, format, args);
	filehandle = CreateFile(L"Log.txt", GENERIC_WRITE, 0, 0, OPEN_ALWAYS, 0, 0);
	SetFilePointer(filehandle, 0, 0, FILE_END);
	char date[18];
	_strdate(date);
	date[8] = ' ';
	_strtime(date+9);
	sprintf_s(writebuffer, 2048, "Log Added (%s): %s\r\n", date, buffer);
	WriteFile(filehandle, writebuffer, strlen(writebuffer), &dwReadBytes, 0);
	CloseHandle(filehandle);
}

void* DetourFunc(PBYTE src, const PBYTE dst, const int len)
{
	DWORD dwback;
	BYTE* jmp = (BYTE*)malloc(len+5);
	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);
	VirtualProtect(jmp-len, len+5, PAGE_EXECUTE_READWRITE, &dwback);
	return (jmp - len);
}

bool bDataCompare(const BYTE* pData, const BYTE* bMask, const char* szMask) 
{
	for(;*szMask;++szMask,++pData,++bMask)
	{
		if(*szMask=='x' && *pData!=*bMask )
		{
			return false;
		} 
	} 
	return (*szMask) == NULL;
}

DWORD dwFindPattern(DWORD dwAddress,DWORD dwLen,BYTE *bMask,char * szMask)
{
	for(DWORD i=0; i < dwLen; i++) 
	{
		if( bDataCompare( (BYTE*)( dwAddress+i ),bMask,szMask) )
		{
			return (DWORD)(dwAddress+i); 
		}
	}
	return 0; 
}
Und der Inhalt des Logfiles:
Code:
Log Added (01/30/12 01:21:06): ==========LOG START==========
Log Added (01/30/12 01:21:06): DLL Attached
Log Added (01/30/12 01:21:06): Creating Thread...
Log Added (01/30/12 01:21:06): Thread Created
Log Added (01/30/12 01:21:06): Searching d3d9.dll...
Log Added (01/30/12 01:21:06): Found d3d9.dll: 6b050000 !
Log Added (01/30/12 01:21:06): Found EndScene: 6b07279f !
//hier wäre es ohne der add_log Zeile in der gehookten Funktion zu Ende gewesen
Log Added (01/30/12 01:21:06): Message from inner EndScene!
//hier hatte ich dann das Programm geschlossen
Log Added (01/30/12 01:21:09): DLL Detached
Log Added (01/30/12 01:21:09): ==========LOG END==========
Ich hoffe sehr, dass mir jemand helfen kann und verbleibe mit freundlichen Grüßen
Jeoni

P.S.: Ich hoffe, dass meine Problemerläuterung detailliert genug war. :)
01/30/2012 01:53 Dr. Coxxy#2
Quote:
Log Added (01/30/12 01:21:06): Message from inner EndScene!
die zeile hätte eigtl ein paar 100x in der logdatei stehen müssen, da (anscheinend vsync an) endscene rund 60x pro sekunde aufgerufen wird.
oder hast du den rest rausgeschnitten?
EDIT:
nvm, zuerst code ansehen - dann antworten...

hmm ne weiß ich nicht, wieso es bei dir nicht geht, bei mir gehts auch mit deinem code problemlos ohne die meldung.

[Only registered and activated users can see links. Click Here To Register...]

einzige womit ich schon öfters probleme hatte ist die data execution prevention von windows, aber eigtl setzt die detourfunc aus dem tut da die rechte auf execute_read_write, das einzige was ich mir vorstellen kann, da das ganze aus nem thread aufgerufen wird, die originalfunktion aber vorher überschrieben wird, und danach erst die rechte gesetzt werden, dass dann ganz kurz noch die falschen rechte im trampolin herrschen.
deswegen hält man das prog normalerweise an, während man detourt...
kannst du evtl. fixxen indem du entweder DIP deaktivierst:
[Only registered and activated users can see links. Click Here To Register...]

oder die funktion umschreibst:
Code:
void* DetourFunc(PBYTE src, const PBYTE dst, const int len)
{
	DWORD dwback;
	BYTE* jmp = (BYTE*)malloc(len+5);
	VirtualProtect(jmp, len+5, PAGE_EXECUTE_READWRITE, &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);
}
01/30/2012 02:00 Jeoni#3
Bei mir kam die Zeile auch erst ziemlich oft, aber da mir dann 1mal reicht habe ich eben diese If-Abfrage reingebaut:
Code:
	if (bMessageSent == false)
	{
		add_log("Message from inner EndScene!");
		bMessageSent = true;
	}
Bir mir funktioniert es jedenfalls nicht :(
Kann das am Injector liegen (hat bestimmt irgendwas mit Rechten zu tun)? Ich nutze ja den HolzIgto Injector (im Anhang + [Only registered and activated users can see links. Click Here To Register...]).

Gehe jetzt schlafen. Bis später.
01/30/2012 02:10 Dr. Coxxy#4
sry, hab meinen post nochmal aktualisiert :P
01/30/2012 11:54 Jeoni#5
Kein Problem.
Die DEP möchte ich nicht deaktivieren, da der Hook ebenfalls ohne Probleme auf anderen Rechnern laufen soll (ohne dass vorher an Windows gedreht werden muss).
Ich kam jetzt zur Erkenntnis, dass es zwar funktioniert (egal welche Detourfunktion man nutzt), aber nur wenn man den Injector vor dem Testprogramm startet (dann auch ohne Olly oder ähnlichem). Heisst das, dass das Problem beim Injector liegt?

Danke trotzdem
MfG
Jeoni
01/30/2012 17:33 Dr. Coxxy#6
kann ich mir nicht vorstellen, startest du beide programme mit administratorrechten?
aber schon seltsam, probier mal winject.
01/31/2012 22:31 Omdi#7
Quote:
Originally Posted by Jeoni View Post
Kein Problem.
Die DEP möchte ich nicht deaktivieren, da der Hook ebenfalls ohne Probleme auf anderen Rechnern laufen soll (ohne dass vorher an Windows gedreht werden muss).
Ich kam jetzt zur Erkenntnis, dass es zwar funktioniert (egal welche Detourfunktion man nutzt), aber nur wenn man den Injector vor dem Testprogramm startet (dann auch ohne Olly oder ähnlichem). Heisst das, dass das Problem beim Injector liegt?

Danke trotzdem
MfG
Jeoni
Wenn in der Log Datei was geschrieben wird, kann es eigentlich nicht an deinen Injektor liegen. Falls du doch nochmal einen anderen testen willst, kann ich dir winject empfehlen.
01/31/2012 23:35 Jeoni#8
Bei Winject ist es das selbe. Allerdings bin ich darauf gekommen, dass es wohl am Zielprogramm (also "D3D Test.exe") lag, da es bei anderen Programmen ohne Probleme funktioniert (egal mit welchen Injector). Dummer Fehler, aber naja.
Trotzdem danke an euch für die Hilfe :D
MfG
Jeoni

#Kann jetzt geclosed werden