Gamehacking Howto I
Das ist ein etwas größeres Tutorial über Gamehacking. Euch erwartet hier das finden eines Wertes im Speicher, das finden des Pointers und anschließend das Programmieren eines Hacks dafür in C++. Ich hoffe das ich den Anfängern hier eine gute Basis bieten kann andere Spiele zu hacken und eigene Hacks zu schreiben. Ohne AutoIt :P Außerdem ist das erst der erste Teil. Im zweiten Teil werden noch einige andere Techniken erwarten. Aber das zu gegebener Zeit :P
Das ist ein etwas größeres Tutorial über Gamehacking. Euch erwartet hier das finden eines Wertes im Speicher, das finden des Pointers und anschließend das Programmieren eines Hacks dafür in C++. Ich hoffe das ich den Anfängern hier eine gute Basis bieten kann andere Spiele zu hacken und eigene Hacks zu schreiben. Ohne AutoIt :P Außerdem ist das erst der erste Teil. Im zweiten Teil werden noch einige andere Techniken erwarten. Aber das zu gegebener Zeit :P
#Inhalt:
[-]Voraussetzungen & Programme
[-]Adresse finden
[-]Pointer finden
[-]Hack Programmieren
[-]Nachwort
[-]Voraussetzungen & Programme
Voraussetzungen:
- Grundlegende Erfahrung im Umgang mit Memory Search Programmen
- Grundlegende Erfahrung im Umgang mit Debuggern
- Grundlegende ASM Kenntnisse
- C++ / Visual C++ Kenntnisse
- Menschenverstand
Programme:
- Solitär
- Visual Studio 2005 oder höher
Als Opferspiel nehme ich dieses mal Solitär. Das sollte jeder auf seinem Rechner haben und es ist recht simpel. Und erfüllt auch alle unsere Ansprüche
[-]Adresse finden
Als erstes starten wir mal Solitär.
Wir sehen unten Rechts einmal eine Punkteanzeige und eine Zeitanzeige. Wenn wir nun z.B. das Ass oben hinlegen, bekommen wir Punkte und die Zeit fängt an zu laufen.
Ich werde mich in diesem Tutorial nur mit der Punktezahl befassen. Nach diesem Tutorial solltet ihr in der Lage sein die Zeit selbstständig zu hacken :P
Nun öffnen wir CheatEngine, wählen als Process sol.exe aus und machen uns bereit. Wir wechseln in Solitär und machen ein paar Punkte. Dann wechseln wir schnell in CE und suchen nach dem Wert der unten steht. Wir müssen uns natürlich beeilen, weil die Punkte mit der Zeit ja weniger werden.
Dann warten wir einfach ab bis die Punkte auf 0 gefallen sind und suchen nach 0. Aber was sehen unsere Augen da? Es wir kein Wert mehr angezeigt. CE hat nichts gefunden.
Aber nichts verzagen! Die Lösung ist recht simpel. Wenn wir uns die Memory Scan Options anschauen, haben wir dort 32 Bit gewählt.
Was in den meisten Fällen ja auch richtig ist. Aber wir haben nun das Problem das CE nichts findet. Also wählen wir "All" aus. Somit wird der ganze Speicher Bereich gescannt!
Also wechseln wir nun in Solitär, verschieben ein paar Karten um Punkte zu machen, wechseln wieder schnell in CE und suchen nach dem Punktestand!
Dann warten wir wieder bis die Punkte auf 0 sind und suchen nach 0!
Dann sollten wir dort 1 Adresse stehen haben. Mit einem Doppelklick gelangt diese nun in unsere Adressen Liste.
Wenn wir nun den Wert verändern, z.B. auf 100 haben wir auch in Solitär 100 Punkte.
Pointer finden
Aber unser Werk ist noch nicht vollendet. Wenn wir jetzt Solitär neustarten würde, könnten wir diese Adresse nicht mehr benutzten. Weil sie sich stätig ändert. Denn wir haben es hier mit einem Pointer oder auf deutsch mit einem Zeiger zu tun. Wir wissen auch nicht ob es mehrere Zeiger sind. Oftmals muss man über 2-3 oder auch 4 Adressen gehen bis wir zu unserem Wert kommen. Wir müssen also den Base Pointer finden. Das ist in den meisten fällen einfach. Wir haben nun zwei Möglichkeiten. Die erste ist wir benutzten den Pointer scanner. Er scannt automatisch den Speicher ab und sucht nach dem Pointer. In einigen Fällen wohl hilfreich, aber kann unter umständen auch ziemlich lang dauer. Aber dabei lernen wir ja nix. Wir machen es von Hand!
Wir machen also einen Rechtsklick auf die Adresse und wählen "Find out what access this address"
Dann öffnet sich der Debugger und wir sehen was auf diese Adresse zugreift.
Wir sehen:
PHP Code:
mov eax, [edi+30]
Also müssen wir wissen welche Adresse edi hat. Mit einem doppelklick auf die Zeile öffnet sich das "Extra Info" Fenster.
Und dort sehen wir das EDI den Wert 000AB640 beinhaltet. Jetzt müssen wir nur herausfinden, welche Adresse EDI hat. Also suchen wir nach diesem Wert.
Wichtig ist das wir bei der neuen Suche den Haken bei HEX gesetzt habe. Da unser Wert ja in HEX ist.
Jetzt sehen wir dort 3 Adressen. 1 von denen ist Grün. Das heißt diese Adresse ist der Base Pointer.
Nun müssen wir diese Adresse als Pointer hinzufügen. Wir klicken nun auf Add address manually. Dann öffnet sich ein PopUp und dort machen wir einen Haken bei Pointer.
Dann geben wir die Adresse 01007170 unten bei Address of Pointer ein.
Das war's aber noch nicht! Wir erinnern uns an die mov anweisung.
PHP Code:
mov eax, [edi+30]
Mit einem Klick auf Ok fügen wir die Adresse hinzu. Und haben nun unseren Pointer.
[-]Hack Programmieren
So natürlich ist es doof immer mittels CheatEngine Solitär zu verändern. Also schreiben wir uns einen kleinen hack dafür.
Ich verwende hier jetzt Visual Studio 2005. Außerdem benutzte ich MFC um die GUI zu machen. Ihr könnt auch eine neuere Version von Visual Studio nehmen. Aber beachtet bitte, das die Kosntelose Express Version kein MFC hat. Das heißt ihr könnt die GUI nicht so machen wie ich. Es gibt ja genügend andere GUI libs, aber wie gesagt ich beziehe mich jetzt hier nur auf MFC. Wie ihr es mit anderen GUIs macht müsst ihr selbst herausfinden :P
Also wir erstellen uns erstmal einen Dialog. Dazu geht ihr auf Datei -> Neu -> Projekt -> MFC -> MFC Anwendung.
Ich nenne mein Projekt "Solitär Hack".
Bei den Einstellungen, stellen wir auf Dialogfeld basierend:
Und machen den Haken bei ActiveX-Steuerelemente weg!
Dann klicken wir auf Fertigstellen.
Wir gehen in die Ressourcenansicht und fügen unserem Dialog 1 Static Textfeld, 1 Editfeld und 2 Buttons hinzu.
Das Static Feld benennen wir in "Punktestand" um. Und die Buttons in "Lesen" und "Schreiben".
Nun machen wir einen Rechtsklick auf das Editfeld und klicken auf Variable hinzufügen.
Dann öffnet sich ein Pop-Up mit dem Assistenten. Rechts bei Kategorie wählen wir Value.
Der Variablentyp bleibt CString. Und als Variablennamen geben wir m_Value ein.
Dann machen wir einen Rechtsklick auf den "Lesen" Button und klicken auf "Ereignishandler Hinzufügen".
Dann öffnet sich der Assistent und wir wählen (falls nicht schon automatisch ausgewählt ist) BN_CLICKED aus und fügen den Ereignishandler hinzu.
Das gleiche machen wir dann auch nochmal für den "Schreiben" Button.
Dann gehen wir in die Klassenansicht. Dort sehen wir die Klassen die unser Projekt hat.
CAboutDlg ist die Klasse des About Dialoges. Der About Dialog wird automatisch generiert.
CSolitärHackApp ist die Application Klasse. Die ist für uns uninteressant.
CSolitärHackDlg ist die Klasse von unserem Dilaog den wir erstellt haben. Wenn wir da drauf klicken sehen wir da drunter die ganzen Funktionen die in der Klasse sind und auch die Member Variablen. Wir machen einen Rechtsklick auf die Klasse -> Hinzufügen -> Funktion hinzufügen.
Dann öffnet sich unser altbekannter Assistent. Als Rückgabetyp schreiben wir void. Da die Funktion nichts zurückgeben muss. Als Name geben wir m_lesen ein und fügen die Funktion hinzu. Das selbe machen wir nun nochmal und fügen die Funktion m_schreiben hinzu.
So nun genug gespielt. Jetzt gehts an's programmieren.
Wie gehen in's code Fenster und sollten nun das da stehen haben:
PHP Code:
void CSolitärHackDlg::OnBnClickedButton1()
{
// TODO: Fügen Sie hier Ihren Kontrollbehandlungscode für die Benachrichtigung ein.
}
void CSolitärHackDlg::OnBnClickedButton2()
{
// TODO: Fügen Sie hier Ihren Kontrollbehandlungscode für die Benachrichtigung ein.
}
void CSolitärHackDlg::m_lesen(void)
{
}
void CSolitärHackDlg::m_schreiben(void)
{
}
PHP Code:
void CSolitärHackDlg::OnBnClickedButton1()
{
// TODO: Fügen Sie hier Ihren Kontrollbehandlungscode für die Benachrichtigung ein.
m_lesen();
}
PHP Code:
void CSolitärHackDlg::OnBnClickedButton2()
{
// TODO: Fügen Sie hier Ihren Kontrollbehandlungscode für die Benachrichtigung ein.
m_schreiben()
}
Was müssen wir machen?
Wir müssen uns einmal den Window Handle holen. Dann brauchen wir die ProcessID. Außerdem wir müssen die Pointer Adresse berechnen und den Wert holen.
Um den Window Handle zu holen müssen wir uns erstmal 2 Variablen anlegen. Dazu gehen wir in die Klassenansicht und machen einen Doppelklick auf die Klasse CSoliträHackDlg. Damit landen wir im SolitärHackDlg Header. Wenn wir runter scrollen sehen wir auch unsere 2 Funktionen m_lesen() und m_schreiben(). Da drunter legen wir uns 2 Variablen an.
Einmal eine CWnd und eine HWND.
PHP Code:
CWnd *pWnd;
HWND hWnd;
So dann sollte es nun so aussehen:
PHP Code:
...
...
public:
void m_lesen(void);
void m_schreiben(void);
CWnd *pWnd;
HWND hWnd;
Um uns den Handle zu holen schreiben wir:
PHP Code:
pWnd = CWnd::FindWindowExW(NULL,NULL,NULL,_T("Solitär"))
Wir müssen aber noch den Handle in die HWND Variable bekommen, das geschiet mit:
PHP Code:
hWnd = HWND(pWnd->GetSafeHwnd());
PHP Code:
if (pWnd = CWnd::FindWindowExW(NULL,NULL,NULL,_T("Solitär"))) {
hWnd = HWND(pWnd->GetSafeHwnd());
}else{
AfxMessageBox(_T("Fenster nicht gefunden!"));
}
So dann legen wir uns mal die Variablen an. Wir brauchen einmal eine Variable die, die Base Pointer adresse beinhaltet. Dann brauchen wir eine für das Offset und eine für die Adresse auf die der Pointer zeigt. Die unseren Wert beinhaltet. Da wir auch gerad bei Wert sind, dafür brauchen wir auch eine Adresse.
Dann brauchen wir eine Variable die den Process Handle Beinhaltet und eine für die Process Id. Und so sieht es dann aus.
PHP Code:
unsigned long address1 = 0x01007170;
unsigned long offset = 0x30;
unsigned long address2 ;
int value ;
DWORD numBytesRead;
HANDLE hProc;
DWORD procID;
PHP Code:
GetWindowThreadProcessId(hWnd,&procID);
PHP Code:
hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procID);
PHP Code:
ReadProcessMemory(hProc, (LPCVOID)address1, &address2, sizeof(long), &numBytesRead);
PHP Code:
address2 = address2+offset ;
PHP Code:
ReadProcessMemory(hProc, (LPCVOID)address2, &value, sizeof(int), &numBytesRead);
Wir erinnern uns an unser Editfeld, was wir angelegt haben. Und die Variable die wir diesem Feld zugewiesen haben. Nun müssen wir den inhalt von value in m_value schreiben.
PHP Code:
m_Value.Format(_T("%i"),value);
PHP Code:
UpdateData(false);
PHP Code:
UpdateData(true);
Und ein
PHP Code:
CloseHandle(hProc);
So das war's dann. Wir haben unsere Lesen Funktion fertig.
Hier nochmal im ganzen:
PHP Code:
void CSolitärHackDlg::m_lesen(void)
{
if (pWnd = CWnd::FindWindowExW(NULL,NULL,NULL,_T("Solitär"))) {
hWnd = HWND(pWnd->GetSafeHwnd());
}else{
AfxMessageBox(_T("Fenster nicht gefunden!"));
}
UpdateData(true);
unsigned long address1 = 0x01007170;
unsigned long offset = 0x30;
unsigned long address2 ;
int value ;
DWORD numBytesRead;
HANDLE hProc;
DWORD procID;
GetWindowThreadProcessId(hWnd,&procID);
hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procID);
ReadProcessMemory(hProc, (LPCVOID)address1, &address2, sizeof(long), &numBytesRead);
address2 = address2+offset ;
ReadProcessMemory(hProc, (LPCVOID)address2, &value, sizeof(int), &numBytesRead);
m_Value.Format(_T("%i"),value);
UpdateData(false);
CloseHandle(hProc);
}
Wir können eigentlich alles Kopieren aus der Lesen Funktion. Das Letzte ReadProcessMemory brauchen wir nicht, weil wir ja nicht den Aktuellen Stand lesen wollen. Stattdessen kommt da ein WriteProcessMemory hin.
Außerdem mussen wir uns die Eingabe holen. Also wenn man jetzt was in das Editfeld eingibt, wird das in die m_value geschrieben. m_value ist eine CString Variable und wir müssen diese erst in eine int variable konvertieren und in value schreiben. Das machen wir mit:
PHP Code:
value = _wtoi (m_Value);
Dann müssen wir noch das was in value steht in den Speicher schreiben. Das machen wir mit:
PHP Code:
WriteProcessMemory(hProc,(LPVOID)address2,&value,sizeof(value),NULL);
PHP Code:
void CSolitärHackDlg::m_schreiben(void)
{
if (pWnd = CWnd::FindWindowExW(NULL,NULL,NULL,_T("Solitär"))) {
hWnd = HWND(pWnd->GetSafeHwnd());
}else{
AfxMessageBox(_T("Fenster nicht gefunden!"));
}
unsigned long address1 = 0x01007170;
unsigned long offset = 0x30;
unsigned long address2 ;
int value ;
DWORD numBytesRead;
HANDLE hProc;
DWORD procID;
UpdateData(true);
GetWindowThreadProcessId(hWnd,&procID);
hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procID);
ReadProcessMemory(hProc, (LPCVOID)address1, &address2, sizeof(long), &numBytesRead);
address2 = address2+offset ;
value = _wtoi (m_Value);
WriteProcessMemory(hProc,(LPVOID)address2,&value,sizeof(value),NULL);
UpdateData(false);
CloseHandle(hProc);
}
Dann starten wir Solitär - falls es nicht mehr offen ist - und starten unseren Hack und drücken auf Lesen. Dann verschrieben wir ein paar Karten, machen Punkte und drücken wieder auf Lesen. Dann sollte sich der Wert in der Editbox ändern. Dann schreiben wir unseren eigenen Wert in die Editbox und drücken auf Schreiben. Dann sollte dieser Wert auch in Solitär unten Rechts stehen. Wenn das Funktioniert, ändern wir das Debug in Release und Kompelieren nochmal. Nun haben wir einen Fertigen Solitär Hack! Glückwunsch :P
[-]Nachwort
Puh, das war wohl bisher mein Längstes Tutorial. Ich hoffe es hat euch so die Basics von Cheat Engine , Pointern und Hacks Programmieren gezeigt.
Ich werde wenn ich mal wieder Lust habe, noch einen zweiten Teil schreiben, wo ich auch einige andere Techniken eingehen werde :P
Ich hoffe es hat euch gefallen. Falls ihr Fehler findet, könnt ihr euch melden. Bin ja auch nur ein Mensch und diese machen bekanntlich Fehler :P