so... ich denke mal, dass ich euch eine der wichtigsten teile in sachen gamehacking hier erklären kann, oder zumindest versuchen zu erklären:p
fangen wir mal damit an, was ich benutze:
-Visual Studio 2008 Professional + Visual Assist X
-IDA Pro Free
-ein game
los gehts:
erstellt euch eine struktur, wodrin ihr informationen über einen hook speichert.
bei mir sieht das so aus:
pBackup ist die kopie von dem überschriebenen speicher (später mehr)
lpOriginal ist die original funktions adresse
lpHook ist die funktion, die wir anspringen wollen!
lpSub ist eine zwischenfunktion, die lpHook ausführt, und auf lpReturn zurück springt.
lpReturn ist eine backup funktion, die den überschriebenen speicher ausführt, und zu der adresse von originalen+überschriebene byte länge springt.
als nächstes sollte ein globale variable erstellt werden, in der wir ALLE hook informationen speichern (auch mehrere). dazu nehme ich std::vector<typename>. das sieht so aus:
jetzt kommen wir zum interessanten teil, dem eigentlichen hook!
ein hook funktioniert so:
er überschreibt die ersten bytes einer funktion, mit den bytes die dafür sorgen dass die funktion als erstes an eine andere funktions adresse springt.
von dieser funktionsadresse KANN man die überschriebenen bytes ausführen, und an die original adresse + überschriebene byte länge springen, um die originale funktion aufzurufen.
da ich noch eine subfunktion habe die das alles für mich übernimmt (an neue adresse springen, und hinterher das backup ausführen), wird der letztere teil eher unnötig!
die subfunktion sieht bei mir so aus:
die platzhalter werden später durch die "richtigen" adressen ersetzt.
startet jetzt IDA, und analysiert das spiel! (könnte etwas dauern)
wenn IDA fertig ist, guckt mal in die register karte "Functions", und sucht nach einer funktion die interessant sein könnte. Ob die funktion euch interessiert, könnt ihr am namen lesen (wenn sie einen hat).
nehmen wir mal an, die funktion liegt an adresse 0x00618942.
dann muss euer code so aussehen:
ich hoffe da sind keine fehler drin, und dass es hilfreich war:D
fangen wir mal damit an, was ich benutze:
-Visual Studio 2008 Professional + Visual Assist X
-IDA Pro Free
-ein game
los gehts:
erstellt euch eine struktur, wodrin ihr informationen über einen hook speichert.
bei mir sieht das so aus:
Code:
[...]
typedef struct
{
BYTE* pBackup;
LPVOID* lpOriginal;
LPVOID* lpHook;
LPVOID* lpSub;
LPVOID* lpReturn;
}SHOOKINFO,*LPSHOOKINFO;
[...]
lpOriginal ist die original funktions adresse
lpHook ist die funktion, die wir anspringen wollen!
lpSub ist eine zwischenfunktion, die lpHook ausführt, und auf lpReturn zurück springt.
lpReturn ist eine backup funktion, die den überschriebenen speicher ausführt, und zu der adresse von originalen+überschriebene byte länge springt.
als nächstes sollte ein globale variable erstellt werden, in der wir ALLE hook informationen speichern (auch mehrere). dazu nehme ich std::vector<typename>. das sieht so aus:
Code:
#include <vector> [...] std::vector<SHOOKINFO> hooks; [...]
ein hook funktioniert so:
er überschreibt die ersten bytes einer funktion, mit den bytes die dafür sorgen dass die funktion als erstes an eine andere funktions adresse springt.
von dieser funktionsadresse KANN man die überschriebenen bytes ausführen, und an die original adresse + überschriebene byte länge springen, um die originale funktion aufzurufen.
da ich noch eine subfunktion habe die das alles für mich übernimmt (an neue adresse springen, und hinterher das backup ausführen), wird der letztere teil eher unnötig!
die subfunktion sieht bei mir so aus:
Code:
__declspec(naked) void hkSub()
{
__asm
{
pushfd //register backup
pushad //register backup
call 0xDEADBEEF //platzhalter für die neue funktion
popad //register backup laden
popfd //register backup laden
jmp 0xDEADBEEF //platzhalter für die backup funktion
}
}
Code:
[...]
#define ASM_JMP 0xE9 //byte-op-code für den JMP befehl!
[...]
SHOOKINFO AttachHook(LPVOID lpOriginal,LPVOID lpNew)
{
DWORD dwOldProtect;
SHOOKINFO info;
info.lpSub = VirtualAlloc(NULL,sizeof(&hkSub),MEM_COMMIT,PAGE_EXECUTE_READWRITE);
info.lpReturn = VirtualAlloc(NULL,10,MEM_COMMIT,PAGE_EXECUTE_READWRITE); //wie ich auf 10 komme? überschriebene bytes(5)+jmp(1)+DWORD(4)
VirtualProtect(lpOriginal,5,PAGE_EXECUTE_READWRITE,&dwOldProtect); //wie ich auf 5 komme? jmp(1)+DWORD(4)
info.pBackup = new BYTE[5];
memcpy(&info.pBackup[0],lpOriginal,5);
memcpy(lpOriginal,(void*)ASM_JMP,1); //jmp an den anfang schreiben
memcpy((void*)((DWORD)lpOriginal+1),info.lpSub,4); //adresse hinterher schreiben!
VirtualProtect(lpOriginal,5,dwOldProtect,0);
memcpy(info.lpSub,&hkSub,sizeof(&hkSub));
memcpy((void*)((DWORD)info.lpSub+3),lpNew,4); //das erste 0xDEADBEEF durch lpNew ersetzen!
memcpy((void*)((DWORD)info.lpSub+10),info.lpReturn,4); //das zweite 0xDEADBEEF durch info.lpReturn ersetzen!
memcpy(info.lpReturn,&info.pBuffer[0],5); //die überschriebenen bytes in die backup funktion schreiben
memcpy((void*)((DWORD)info.lpReturn+5),(void*)ASM_JMP,1); //jmp schreiben
memcpy((void*)((DWORD)info.lpReturn+6),(void*)((DWORD)lpOriginal+5),4); //die adresse hinterher schreiben, wo der jmp befehl auf die sub funktion zuende ist!
return info;
}
wenn IDA fertig ist, guckt mal in die register karte "Functions", und sucht nach einer funktion die interessant sein könnte. Ob die funktion euch interessiert, könnt ihr am namen lesen (wenn sie einen hat).
nehmen wir mal an, die funktion liegt an adresse 0x00618942.
dann muss euer code so aussehen:
Code:
__declspec(naked) void hkNothing()
{
//do something
}
[...]
AttachHook((void*)0x00618942,&hkNothing);