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:
)- TSearch (Gibts hier:
)- 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
-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(
)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
)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. (
)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
)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...
}
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...
}
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...
}
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...
}
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






