Endscene Hook Problem

05/09/2013 11:54 TheAldi#1
Mein Problem ist , dass das Programm sofort abstürzt wenn ich die Endscene hooke.
Bezogen von diesem TuT :[Only registered and activated users can see links. Click Here To Register...]

Es muss aber aufjedenfall an meiner eigenen Endscene liegen , denn wenn ich die gefundene Endscene auf sich selbst leite , entsteht eine endlosschleife :p

Meine eigene Endscene wird nur einmal aufgerufen und dann stürzt das Programm ab (Getestet mit 5 verschiedenen DirectX Testprogrammen)

Code:
#define _CRT_SECURE_NO_WARNINGS 
#include <Windows.h> 
#include <cstdio> 
#include <time.h> 
#include <d3d9.h> 
#include <d3dx9.h>

const D3DCOLOR txtGreen = D3DCOLOR_ARGB(255,0,255,0);
HRESULT __stdcall hkEndScene(LPDIRECT3DDEVICE9 pDevice);

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

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

HMODULE hModD3D9 = NULL;
FARPROC dwEndScene = NULL;
HANDLE tmpHandle = NULL;
DWORD* VTableStart = NULL;
DWORD tempadd = NULL;

BOOL WINAPI DllMain(HINSTANCE hinstDll,DWORD Reason,LPVOID Reserved)
{ 
	switch(Reason)
	{
	case DLL_PROCESS_ATTACH:
		tmpHandle = CreateThread(0,0,(LPTHREAD_START_ROUTINE)&HookThread,0,0,0);
		break;
	case DLL_PROCESS_DETACH:
		break;
	}
	return 1;
}

DWORD WINAPI HookThread(void)
{
	while(!hModD3D9)
	{
		hModD3D9 = GetModuleHandle(L"d3d9.dll");
		Sleep(100);
	}
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];
pEndScene = (EndScene_t) DetourFunc((PBYTE) dwEndScene, (PBYTE)hkEndScene, 5);
while (true)
{
	Sleep(500);
}
return 0;
}
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);
}
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; 
}
HRESULT __stdcall hkEndScene(LPDIRECT3DDEVICE9 pDevice) 
{ 
Beep(750,300);
	return pEndScene(pDevice); 
}
05/09/2013 16:46 Dr. Coxxy#2
komisch, in welchem spiel denn?

solltest vllt aus:
Code:
VirtualProtect(src, len, PAGE_READWRITE, &dwback);
das hier:
Code:
VirtualProtect(src, len, PAGE_EXECUTE_READWRITE, &dwback);
machen.

gerade bei mir im ms dx9 sampleprogramm MultiAnimation ausprobiert, funktioniert einwandfrei.
vllt solltest du aber nicht Beep in endscene benutzen, die funktion hängt nämlich, vllt hat das spiel probleme damit.
05/09/2013 16:51 TheAldi#3
Habs auf "PAGE_EXECUTE_READWRITE" gesetzt aber trotzdem gleicher Fehler :p
Ich versuchs auch im MS Sampleprogramm aber das stürzt sofort ab

Das Beep war nur zum testen drinne ob der überhaupt in die gehookte Funktion geht


Evtl liegts daran , dass ich Win8 x64 nutze :p
05/09/2013 16:56 Dr. Coxxy#4
Quote:
Originally Posted by TheAldi View Post
Habs auf "PAGE_EXECUTE_READWRITE" gesetzt aber trotzdem gleicher Fehler :p
Ich versuchs auch im MS Sampleprogramm aber das stürzt sofort ab

Das Beep war nur zum testen drinne ob der überhaupt in die gehookte Funktion geht


Evtl liegts daran , dass ich Win8 x64 nutze :p
hmm gute frage.
hab leider kein windoof 8 zum testen, kompilierst du als 32 bit und im release modus?
injector als admin gestartet, die release dll ausgewählt und zielprozess auch 32 bit programm?
05/09/2013 17:02 TheAldi#5
DLL : Find ich grad keine Option zum einstellen der ZielCPU
Realese Mode : Nein
Admin : Jap alles als Admin
Ziel : 32Bit DirectX Sample (im 64Bit Sample wird nichts ausgelöst mit der DLL auch kein Absturz bzw. veränderung wenn ich ein Rechteck zeichnen lasse)

Edit:
Aber unterschied machts nich zwischen Debug/Release Mode stürzen beide ab ^^
05/09/2013 17:44 Dr. Coxxy#6
Quote:
Originally Posted by TheAldi View Post
DLL : Find ich grad keine Option zum einstellen der ZielCPU
Realese Mode : Nein
Admin : Jap alles als Admin
Ziel : 32Bit DirectX Sample (im 64Bit Sample wird nichts ausgelöst mit der DLL auch kein Absturz bzw. veränderung wenn ich ein Rechteck zeichnen lasse)

Edit:
Aber unterschied machts nich zwischen Debug/Release Mode stürzen beide ab ^^
dann mal debugger nehmen und gucken wo/was schiefgeht :P
05/09/2013 17:59 TheAldi#7
Laut Olly :

"Access violation when writing to [Address]"

Ist doch richtig wenn ich Olly an die exe hänge und dann injecte oder ? :D

Edit: Fehler laut Olly nach Häufigkeit (immer gleiche Bedingungen)
1. "Access violation when writing to [Address]"
2. "Access violation when reading [Address]"
3. Iwas mit Priveligiert (erst einmal aufgetreten)
05/09/2013 19:00 Dr. Coxxy#8
lad mal deine kompilierte dll hoch.
kannst auch mal konsole attachen und mit cout/printf mal adressen ausgeben lassen von endscene etc., auf nen tastendruck warten und erst danach hooken.
in der zwischenzeit kannst du olly/cheatengine attachen, auf endscene nen breakpoint machen und gucken ob dein hook korrekt installiert wird, also ersten 5 bytes mit nem e9 <adresse> überschrieben werden, ob evtl. schon vorher ein hook/relative adresse an der adresse stand, ob der jump zu deiner funktion führt, ob deine funktion korrekt das trampolin callt, ob im trampolin die 5 bytes aus der origfunktion sind, ob die 5 bytes ein sinnvoller befehl ohne relative adresse ist, etc.
05/09/2013 19:26 TheAldi#9
OK meld mich dann morgen wieder sobald ich dazu zeit gefunden habe ^^

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

Source der DLL:
Code:
#define _CRT_SECURE_NO_WARNINGS 
#include <Windows.h> 
#include <cstdio> 
#include <time.h> 
#include <d3d9.h> 
#include <d3dx9.h>

const D3DCOLOR txtGreen = D3DCOLOR_ARGB(255,0,255,0);
HRESULT __stdcall hkEndScene(LPDIRECT3DDEVICE9 pDevice);

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

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

HMODULE hModD3D9 = NULL;
FARPROC dwEndScene = NULL;
HANDLE tmpHandle = NULL;
DWORD* VTableStart = NULL;
DWORD tempadd = NULL;

BOOL WINAPI DllMain(HINSTANCE hinstDll,DWORD Reason,LPVOID Reserved)
{ 
	switch(Reason)
	{
	case DLL_PROCESS_ATTACH:
		tmpHandle = CreateThread(0,0,(LPTHREAD_START_ROUTINE)&HookThread,0,0,0);
		break;
	case DLL_PROCESS_DETACH:
		break;
	}
	return 1;
}

DWORD WINAPI HookThread(void)
{
	while(!hModD3D9)
	{
		hModD3D9 = GetModuleHandle(L"d3d9.dll");
		Sleep(100);
	}
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];
pEndScene = (EndScene_t) DetourFunc((PBYTE) dwEndScene, (PBYTE)hkEndScene, 5);
while (true)
{
	Sleep(500);
}
return 0;
}
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_EXECUTE_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);
}
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; 
}
HRESULT __stdcall hkEndScene(LPDIRECT3DDEVICE9 pDevice) 
{
	D3DRECT rect = {10,10,110,110};
	pDevice->Clear(1,&rect,D3DCLEAR_TARGET,txtGreen,0,0);
	return pEndScene(pDevice); 
}
05/09/2013 19:56 Master674b#10
Als erstes würde ich vorschlagen mit etwas leichterem anzufangen. Du hast da einen wahnsinnig schlechten Aufbau und Stil auch wenns nur die paar Zeilen sind.

Danach auf jeden Fall von der Detours Funktion verabschieden und am besten eine eigene machen (ansonsten tuts auch MS Detours 3.0 - threadsicher).

Falls du eine eigene Detours Funktion machen möchtest brauchst du erst mal einen Längendisassembler damit du dein Trampolin zum Rücksprung richtig aufsetzen kannst. Für das Trampolin empfiehlt sich HeapAlloc auf einem Heap der mit HEAP_CREATE_ENABLE_EXECUTE erstellt wurde.

Um das ganze noch Threadsicher zu machen kannst du dann noch alle Threads suspendieren und mal schauen ob gerade einer über der Instruktion verweilt, auf die du deinen Detour setzen willst. Mache das momentan so:

Code:
const auto &lstThreads = threadGrabber.threads();
std::list<std::shared_ptr<Thread>> lstCriticalThreads;
_detourSuspendThreads(lstThreads);

do {
	lstCriticalThreads = _threadExecutingInstruction(lstThreads, dwAddress, uSize);
	for (const auto& thread: lstCriticalThreads) {
		if (thread->open(thread->access() | THREAD_SUSPEND_RESUME)) {
			thread->resume();
			Sleep(rand() % 10); // give him some time to move along... :D
			thread->suspend();
		}
	}
}
while (!lstCriticalThreads.empty());

ByteBuffer jump(uSize, 0xCC);
jump << byte(0xE9);
jump << reinterpret_cast<DWORD_PTR>(pRedirect) - (dwAddress + 5);

WriteMemory_Safe(dwAddress, jump);
_detourResumeThreads(lstThreads);
Um rauszufinden, wo ein Thread gerade ist kannst du EIP (Extended Instruction Pointer) auslesen.

Code:
std::list<std::shared_ptr<Thread>> SharkMemory::_threadExecutingInstruction(
						const std::list<std::shared_ptr<Thread>> &threads,
						DWORD_PTR dwAddress, DWORD_PTR dwLength) const {
	uint32 curThreadId = GetCurrentThreadId();
	std::list<std::shared_ptr<Thread>> lstThreads;
	for (const auto& thread: threads) {
		if (thread->id() != curThreadId &&
			thread->open(thread->access() | THREAD_GET_CONTEXT)) {
			CONTEXT ctx = {0};
			if (GetThreadContext(thread->handle(), &ctx) == FALSE)
				continue;

			if (ctx.Eip >= dwAddress && ctx.Eip < dwAddress + dwLength)
				lstThreads.push_back(thread);
		}
	}

	return lstThreads;
}
05/10/2013 00:57 Omdi#11
Die DLL funktioniert wunderbar bei mir ;o

Windows 7 64 Bit
05/10/2013 09:49 TheAldi#12
Ok scheint also wirklich iwie an win 8 zu liegen :/

Ich lad mir Grad mal win xp aus der msdnaa runter und Haus mal in ne vm :p

Aber naja 250kb/s Download dauert :D
05/10/2013 14:24 Master674b#13
Quote:
Originally Posted by TheAldi View Post
Ok scheint also wirklich iwie an win 8 zu liegen :/

Ich lad mir Grad mal win xp aus der msdnaa runter und Haus mal in ne vm :p

Aber naja 250kb/s Download dauert :D
Das es dabei zu Fehlern kommt wundert dich noch?! Du solltest dir besser mal meinen Post durchlesen, dann klappts auch.
05/10/2013 15:24 TheAldi#14
Hab deinen Beitrag schon wahrgenommen war ich noch nicht wirklich am pc ums mir genau anzuschauen

Handy formatiert das So unschön :D

Edit 11.05.2013 - 15:30 :
Nun läufts :D
Danke an alle Beteiligten

[Only registered and activated users can see links. Click Here To Register...]
05/17/2013 15:51 MrSm!th#15
#moved