[Gamehacking] Gamehacking mit C++ für Anfänger.

01/09/2009 11:33 BlackFog#1
Moin,
Da hier ziemlich wenig los ist, möchte ich sie mal mit einem kleinen Tutorial zum Thema "Gamehacking" bereichern. Dabei habe ich mir ein Programm als "Opfer" ausgesucht, dass eigentlich jeder hat und jeder kennt: Windows Solitär :).

Zuerst mal was ihr braucht/wissen müsst:

- Grundlegende C++ Kentnisse

- Eine C++ IDE. Ich benutze Visual C++ Express Edition 2008. (Gibts hier: [Only registered and activated users can see links. Click Here To Register...])

- TSearch (Gibts hier: [Only registered and activated users can see links. Click Here To Register...])

- Windows XP (Das Offset ist unter anderen Windows Versionen (wahrscheinlich) anders. Jedoch sollte es kein Problem sein, dass auch für andere Windows Versionen umzusetzen ;).

- Ihr müsst wenigstens Ansatzweise verstehen, wie man bei Solitär Punkte macht :D. Wenn nicht -> Wikipedia ;).
-Etwas Zeit :)

Was wir machen möchten:

Wir möchten die Speicheradresse des Punktestandes in Solitär herausfinden und dann eine C++ Programm schreiben, dass den Wert in unseren Wert verändert.


Also, los geht's :).

Zuerst öffnen wir TSearch und Solitär. Dann wählen wir in Tsearch den Solitär Prozess aus([Only registered and activated users can see links. Click Here To Register...])

Jetzt müssen wir das Offset, die Speicheradresse in der die Punktzahl gespeichert ist, finden.
Zuerst klicken wir hierfür auf die kleine Lupe und wählen als unseren Startwert 0 ein. Logisch , oder ? Wir starten ja mit 0 Punkten ;)([Only registered and activated users can see links. Click Here To Register...])

Jetzt müssen wir etwas machen, dass die Punkte erhöht. Dann klicken wir auf die Lupe mit den drei Punkten und wählen "Has Increased"( deu: "Hat sich erhöht" ) aus. Also suchen wir nach einem Wert, der mal 0 war aber sich nun erhöht hat. ([Only registered and activated users can see links. Click Here To Register...])
Klickt auf Ok und anschließen wir euch ein kleines Fenster angezeigt, dass sagt, wieviele "Kanidaten" noch zur Auswahl stehen. Schließt das Fenster mit einem Klick auf OK.

So nun lassen wir unseren Punktestand wieder auf 0 sinken und dann erhöhen wir die Punkte wieder. Dann klicken wir schnell wieder auf die kleine Lupe mit den drei Punkten und wählen "Exact Value" im Dropdown Menü. Dann geben wir schnell den momentanen PunkteWert ein und klicken auf OK. Dann sollte eigentlich nur noch ein Wert übrig bleiben. Falls das nicht so ist, führt ihr das Spielchen weiter, bis nur noch ein Wert übrig ist.

Eure Speicheradresse müsste unter Windows XP eigentlich "A5060" sein. Ich habe das ganze mehr als 10mal getestet(Mit neustart des Systems und der Programme) und die Adresse hat sich nicht verändert. Deswegen denke ich, dass die Adresse statisch ist. D.H, dass egal auf welchem Windows XP(Durch Servicepacks könnte das ganze abweichen) ihr das Offset sucht; es sollte überall gleich sein.

Nun erhöhen wir noch einmal den Punktestand und gucken, ob sich der Wert der Adresse ändert. In meinem fall tut es das :). ([Only registered and activated users can see links. Click Here To Register...])

Jetzt da wir unsere Adresse kennen, können wir beginnen ein Programm zu schreiben, dass diesen Wert verändert.


Unser kleiner Hack:


Viele werden sich jetzt warscheinlich Fragen: Wie zum Teufel änder ich einen Wert mit C++ ???
Keine Sorge, es ist garnicht mal so schwert :).

Erstellt eine neue, leere Konsolenapplikation.
Zuerst beginnen wir mal mit unserem Grundgerüst:
Code:
#include <windows.h> // Hier sind die Funktionen die wir später noch brauchen
#include <iostream> // Sollte klar sein

using namespace std; // Sollte auch klar sein ...

int main()  // Unsere Main Funktion...
{




cin.get(); //Damit sich unser Programm nicht sofort schließt...
}
Das sollte jeder kennen. Nun werden einige warscheinlich etwas neues lernen. Zu allererst möchten wir das Fensterhandle von Solitär herausfinden. Das Fensterhandle ist ein ganzzahliger Wert, der ein Fenster oder ein Steuerelement identifiziert. In C++ werden solche Fensterhandles in dem Variablentyp "HWND" gespeichert. Mit der Funktion FindWindow können wir dann das Fensterhandle bekommen.

Code:
#include <windows.h> // Hier sind die Funktionen die wir später noch brauchen
#include <iostream> // Sollte klar sein

using namespace std; // Sollte auch klar sein ...

int main()  // Unsere Main Funktion...
{
HWND hwnd; // Unsere Variable die das Fensterhandle speichert.
hwnd = FindWindow(0,L"Solitär");

// Der Fenstertitel vom Solitärfenster ist "Solitär". Das erste Parameter ist der "ClassName" den wir aber getrost ignorieren können. Das zweite Parameter ist unser Fenstername. Das "L" steht für eine Typkonvertierung.. 

if(!hwnd) // Also das Fenster nicht vorhanden ist...
{
	cout << "Solitär nicht gefunden!" << endl; // Gebe das aus
}
else  // ansonsten...
{
	cout << "Solitär gefunden!" << endl; // gebe das aus
        cout << "Fensterhandle: " << hwnd << endl; // Wir können uns das Handle auch nochmal angucken ...
}


cin.get(); //Damit sich unser Programm nicht sofort schließt...
}
So diesen Code ausprobieren und dann gehts weiter. Jetzt müssen wir die ID des Thread's bekommen, den das Fenster erzeugt hat. Die ID brauchen wir später noch. (Wenn ihr nicht wisst was ein Thread ist, ist nicht ganz so tragisch. Bei Gelegenheit mal bei Wikipedia nachlesen ;) )
Also los, hier der Code:

Code:
#include <windows.h> // Hier sind die Funktionen die wir später noch brauchen
#include <iostream> // Sollte klar sein

using namespace std; // Sollte auch klar sein ...

int main()  // Unsere Main Funktion...
{
HWND hwnd; // Unsere Variable die das Fensterhandle speichert.
hwnd = FindWindow(0,L"Solitär");
DWORD Id; // Die ID wird in einer Variable des Typ's DWORD gespeichert.

// Der Fenstertitel vom Solitärfenster ist "Solitär". Das erste Parameter ist der "ClassName" den wir aber getrost ignorieren können. Das zweite Parameter ist unser Fenstername. Das "L" steht für eine Typkonvertierung.. 

if(!hwnd) // Also das Fenster nicht vorhanden ist...
{
	cout << "Solitär nicht gefunden!" << endl; // Gebe das aus
}
else  // ansonsten...
{
	cout << "Solitär gefunden!" << endl; // gebe das aus
        cout << "Fensterhandle: " << hwnd << endl; // Wir können uns das Handle auch nochmal angucken ...
       
        GetWindowThreadProcessId(hwnd,&Id); // Mit GetWindowThreadProcessId kann man die ID herausfinden. Das erste Parameter ist unser Fensterhandle. Das zweite gibt an, wo die ID gespeichert werden soll.

        cout << Id << endl;

}


cin.get();//Damit sich unser Programm nicht sofort schließt...
}
So jetzt ist es nicht mehr weit :D. Jetzt öffnen wir den Prozess damit wir endlich hineinschreiben können... Zuerst erstellen wir uns eine Variable die unser Handle zum offenen Prozess hält. Diese ist vom Typ "Handle". Dann öffnen wir den Process mit OpenProcess.

Code:
#include <windows.h> // Hier sind die Funktionen die wir später noch brauchen
#include <iostream> // Sollte klar sein

using namespace std; // Sollte auch klar sein ...

int main()  // Unsere Main Funktion...
{
HWND hwnd; // Unsere Variable die das Fensterhandle speichert.
hwnd = FindWindow(0,L"Solitär");
DWORD Id; // Die ID wird in einer Variable des Typ's DWORD gespeichert.
HANDLE ProcessHandle;

// Der Fenstertitel vom Solitärfenster ist "Solitär". Das erste Parameter ist der "ClassName" den wir aber getrost ignorieren können. Das zweite Parameter ist unser Fenstername. Das "L" steht für eine Typkonvertierung.. 
if(!hwnd) // Also das Fenster nicht vorhanden ist...
{
	cout << "Solitär nicht gefunden!" << endl; // Gebe das aus
}
else  // ansonsten...
{
	cout << "Solitär gefunden!" << endl; // gebe das aus
        cout << "Fensterhandle: " << hwnd << endl; // Wir können uns das Handle auch nochmal angucken ...
       
        GetWindowThreadProcessId(hwnd,&Id); // Mit GetWindowThreadProcessId kann man die ID herausfinden. Das erste Parameter ist unser Fensterhandle. Das zweite gibt an, wo die ID gespeichert werden soll.

        cout << Id << endl;
        ProcessHandle = OpenProcess(PROCESS_VM_WRITE |PROCESS_VM_OPERATION ,false,Id);
	
	cout << "ProcessHandle: " << ProcessHandle << endl;


}


cin.get(); //Damit sich unser Programm nicht sofort schließt...
}
Die ersten Parameter sind unsere "Rechte" die wir für den Prozess haben. PROCESS_VM_WRITE bedeutet, dass wir in den Prozess schreiben dürfen und PROCESS_VM_OPERATION bedeutet, dass wir im Prozess operieren dürfen. Das zweite Parameter gibt an, ob von unserem "Opfer" Prozess erzeugte Prozesse das Handle erben sollen. Setzen wir auf false. Das dritte Parameter ist unsere ThreadID.
So jetzt wo der Prozess offen ist können wir nun endlich in ihn schreiben. Das machen wir mit "WriteProcessMemory".

Code:
#include <windows.h> // Hier sind die Funktionen die wir später noch brauchen
#include <iostream> // Sollte klar sein

using namespace std; // Sollte auch klar sein ...

int main()  // Unsere Main Funktion...
{
HWND hwnd; // Unsere Variable die das Fensterhandle speichert.
hwnd = FindWindow(0,L"Solitär");
DWORD Id; // Die ID wird in einer Variable des Typ's DWORD gespeichert.
HANDLE ProcessHandle;
int value; // Der Wert den wir schreiben wollen.
unsigned adress = 0x0A5060; // Unsere Adresse

// Der Fenstertitel vom Solitärfenster ist "Solitär". Das erste Parameter ist der "ClassName" den wir aber getrost ignorieren können. Das zweite Parameter ist unser Fenstername. Das "L" steht für eine Typkonvertierung.. 

if(!hwnd) // Also das Fenster nicht vorhanden ist...
{
	cout << "Solitär nicht gefunden!" << endl; // Gebe das aus
}
else  // ansonsten...
{
	cout << "Solitär gefunden!" << endl; // gebe das aus
        cout << "Fensterhandle: " << hwnd << endl; // Wir können uns das Handle auch nochmal angucken ...
       
        GetWindowThreadProcessId(hwnd,&Id); // Mit GetWindowThreadProcessId kann man die ID herausfinden. Das erste Parameter ist unser Fensterhandle. Das zweite gibt an, wo die ID gespeichert werden soll.

        cout << Id << endl;
        ProcessHandle = OpenProcess(PROCESS_VM_WRITE |PROCESS_VM_OPERATION ,false,Id);
	
	cout << "ProcessHandle: " << ProcessHandle << endl;

       cout << "How much points to add? "; // Wieviel Punkte sollen geschrieben werden ???
	cin >> value; // Den Wer übernehmen
	fflush(stdin);

	
	
	WriteProcessMemory(ProcessHandle,(LPVOID)adress,&value,sizeof(int),NULL);  // Den Wert schreiben !
	cout << "Wert geschrieben" << endl;
	cin.get();// Damit sich unser Programm nicht sofort schließt...
}



}

Erstmal habe ich eine int Variable mit dem Namen "value" erstellt. Sie hält den Punktestand den wir schreiben wollen. Außerdem die Adresse von Typ unsigned (int). Dann wir der zu schreibende Wert mit einem cin abgefragt und dann die Funktion WriteProcessMemory aufgerufen.
Das erste Parameter ist unser Handle zum offenen Prozess. Das zweite Parameter unsere zu LPCVOID konvertierte Adresse. Das dritte Parameter der zu schreibende Wert. Das vierte Parameter gibt an, wieviel Bytes wir schreiben wollen. Das letzte Parameter gibt die geschriebenen Bytes an. Ist hier unwichtig also NULL.

Also das wars und ich hoffe ihr konntet etwas lernen. Bei Fragen etc. PN oder im Thread.


Mfg
Blackfog
01/09/2009 13:52 Vulcanraven#2
Bevorzuge aber eher Cheat Engine,
btw Quellen oder selber geschrieben?

#sticky
01/09/2009 14:01 BlackFog#3
Hmm mit Cheatengine habe ich keinen Wert raubekommen o_O. Und ja, ich habe alles selbst geschrieben. Hätte nicht gedacht, dass das soviel Arbeit wird ... ;D
01/11/2009 10:25 Daniiii#4
wow.. nett
01/11/2009 14:12 DamageBreaker#5
danke hilft mir sehr weiter obwohl ich einiges schon kenne^^ trotzdem niicee
01/11/2009 18:29 BlackFog#6
Danke, bin froh, dass ich helfen konnte :)
01/15/2009 17:15 Da_Killa#7
Sehr nice !!!!
Schön zu sehn das sich leute noch die mühe machen und solche tutorials schreiben ;)

+Thanks :P
01/20/2009 19:22 suyu#8
sehr schön =)
vielen dank für deine mühe war ja viel zu schreiben!!
hast mir echt weiter geholfen damit x)
weiter so *gg*

+thanks =)
01/20/2009 19:22 suyu#9
sehr schön =)
vielen dank für deine mühe war ja viel zu schreiben!!
hast mir echt weiter geholfen damit x)
weiter so *gg*

+thanks =)
01/20/2009 21:47 DamageBreaker#10
vllt kann mir ja jem helfen...wie friere ich einen wert ein per c++ muss imer ne while schleife nehmen gibt es da nichts effizienteres?
01/21/2009 08:45 verT!c4L#11
Wie sonst willste denn eine Variable "einfrieren", vorallem wenn es nicht dein eigener Prozess ist ?
Ich glaub ich poste mal was weiterführendes :D
01/21/2009 16:48 DamageBreaker#12
Quote:
Originally Posted by verT!c4L View Post
Wie sonst willste denn eine Variable "einfrieren", vorallem wenn es nicht dein eigener Prozess ist ?
Ich glaub ich poste mal was weiterführendes :D
denkste da an einen debugger? XD glaube mitm debugger würds gehen
02/25/2009 17:11 xBananex#13
also bai mir geht der download von der 2oo8 express dings net
02/26/2009 17:12 DamageBreaker#14
Quote:
Originally Posted by xBananex View Post
also bai mir geht der download von der 2oo8 express dings net
admin rechte oder inet probs?
03/08/2009 18:15 TrueYami#15
Super tutorial !
Hat mich viel neues gelehrt =]