Trainers Tutorials by NiCk.Ø 1/3

Select your platform and your letter

0-9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z


Become a Patron!   Amazon.com    Amazon Prime    Gamesplanet Shop

Trainers Tutorials by NiCk.Ø 1/3
TUTORIAL DE TRAINERS PAR NiCk.Ø
TUTORIAL : CREATION DE TRAINERS EN C++ 3/3

Explication du fonctionnement :

Je vais expliquer ici comment va fonctionner le programme, c'est relativement simple mais il faut correctement assimiler ca afin de comprendre ce que fais le code après.

On attends que le jeu s'ouvre
Une fois le jeu lancé on ouvre un accès en mémoire dessus
Si l'accès n'a pu être ouvert on coupe le trainer et on envoie le code erreur
Si il a été ouvert on tente de lire en mémoire
Si on peut lire on tente d'écrire sinon on coupe et envoie le code erreur
Si la tentative d'écriture fonctionne on fait une boucle qui vérifie si la valeur rechange et si elle rechange on retente d'écrire si ca fonctionne on poursuit la boucle tant que le jeu est lancé ; si pas on arrête envoie le code erreur.
Si la tentative d'écriture échoue on arrête et envoie le code erreur

Comme vous avez du le remarquer, il y a beaucoup de "si" en effet le code va comporter pas mal de test mais ca nous allons le voir juste aprés
Essayer de bien comprendre comme ça fonctionne d'un point de vue logique c'est vraiment important avant d'attaquer le point de vue technique.

Rédaction du code :

Nous y voila ; la troisième et dernière partie du tutoriel ; nous allons coder notre trainer !

Tout d'abord il vous faut un logiciel pour écrire en C++, le bloc note est suffisant mais il existe des "groupes de logiciels" appelé EDI pour Environnement de Développement Intégré qui font ça très bien.
Dans ces EDIs on retrouve généralement un éditeur de texte, un compilateur et un debogger.

Pour ma part j'utilise Microsoft Visual C++ Express disponible sur le site de Microsoft gratuitement ; non pas que je sois Pro Microsoft mais cette EDI me convient très bien et il est gratuit après qu'il soit de Microsoft, d'Apple ou meme d'Ikea on s'en moque tant qu'il fait ce qu'on lui demande et qu'il le fait bien !
Je précise qu'il faut un minimum de base en C++ mais vraiment un minimum :
Savoir ce qu'est une directive de préprocesseur comme #include <iostream>
Savoir utiliser le "cout" meme si je réeplique briévenement
Savoir utiliser une fonction et leur valeur de retour
Connaitre à quoi sert "using namespace std"

J'essayerai d'être le plus clair possible mais si vous ne comprenez pas quelque chose n'hésitez pas à demander j'essaierai de vous répondre au mieux
Tout d'abord lancer Visual C++ express édition ; à l'heure ou j'écris nous somme à la version 2008
Faites Fichier -> Nouveau -> Projet



Remplissez la fenêtre de cette façon
Type de projets : Win32
Modèles : Application console Win32
Donnez un nom à votre projet
Faite OK



Une fenêtre va s'ouvrir vous souhaitant la bienvenue, faites suivant
Dans la fenêtre suivante, cochez Application Console et Projet vide
Cliquez sur Terminer


Votre projet est désespérément vide même pas un petit fichier dedans mais nous allons remédier à ça !
Faites un clique droit sur Fichiers sources -> Ajouter -> Nouvel élement


Sélectionnez Fichier C++ (.cpp) et appelez votre fichier main puis cliquez sur Ajouter



Votre fichier est maintenant ouvert, et c'est dans ce fichier qu'on va écrire notre code
Nous allons en tout premier lieu inclure les deux en-têtes de préprocesseur qui vont nous être nécessaire pour réaliser ce trainer :
iostream pour le flux cout
windows.h pour toute les fonctions relatives à Windows
Pour ce faire il suffit d'écrire #include suivi du nom de l'en-tête entre chevrons < et >,dans certain cas il faut mettre des guillemets à la place des cheuvrons mais je ne traiterai pas de ca dans ce tutorial
Les deux premières lignes sont donc
 <>
#include <iostream>     
#include <windows.h>
Jusque la tout va bien
Ensuite nous allons ajouter
using namespace std;
Cette ligne permet d'utiliser le flux cout sans le faire précéder de std:: je ne vais pas rentrer dans les détails, mais d'utiliser l'éspace de nommage std de façon globale, si vous ne comprenez pas trop ce n'est pas vital pour le reste du code loin de la.
Je rapelle que les instructions se finissent par un ";" un seul caractére manquant à votre ligne et la compilation plante ...
Un programme C++ commence toujours par la fonction main( ) or, nous n'en avons pas donc nous allons en créer une
Créer une fonction est simple il faut d'abord définir un type de valeur de retour, cela permet à votre fonction de renvoyer une valeur du type de votre choix via l'instruction return.
L'instruction return marque la fin de la fonction, ici comme nous utiliserons qu'une seule fonction à chaque fois que le programme rencontrera l'instruction return il s'arretera.
On fait suivre l'instruction return d'une valeur pour envoyer une valeur de retour à la fonction qui l'a appellé, pour le moment si vous ne comprenez pas ca ce n'est oas grave mais vous devriez vite comprendre quand nous allons attaquer les fonctions windows car elle renvoie toujours une valeur qui nous servira à faire des tests.
Question d'habitude ma fonction main( ) est toujours de type int, cela veut dire qu'elle va renvoyer un entier (un chiffre sans virgule)

En plus de son type il lui faut un nom vu que c'est la fonction principale de notre programme elle s'appellera obligatoirement main
Et pour fini la liste des arguments qu'elle prend comme dans notre cas je ne vais pas en mettre, je vais laisser la liste des arguments vide
Pour créer la fonction main ajouter ceci :
int main ()
{
L'accolade délimite le début de la fonction à la fin de la fonction il y aura une accolade inversée pour fermer la fonction
Maintenant que notre fonction est crée il nous suffit de suivre le plan établie à l'étape 2,notez que pour le moment je n'ai déclaré aucune variable celles si viendront au fur et à mesure qu'on en aura besoin ; il faudra déclarer les variables juste en
dessous de l'accolade
D'aprés notre plan quand le trainer se lance il attend que le jeu s'ouvre
On va détecter le lancement du jeu grace à la fonction FindWindow( ) :

https://msdn.microsoft.com/en-us/library/ms633499.aspx

Cette fonction prend 2 arguments de type LPCTSTR le premier argument est un nom de classe et le second le titre d'une fenetre ; cette fonction renvoit un HWND, qu'est ce qu'un HWND ? C'est grosso modo un numéro qui identifie une fenêtre.
Dans notre cas nous utiliserons le deuxieme argument de la fonction FindWindow()
Comme expliqué plus haut la fonction prend donc 2 LPCTSTR et renvoie un HWND or nous n'avons encore rien déclarer.
Retournons à notre fonction main et déclarons un HWND que l'on va initialiser à 0
et un LPCTSTR (sachant qu'on utilise qu'un argument) que nous initialiserons avec le nom de la fenêtre du jeu
Ajoutez donc

LPCTSTR Titrefenetre = (L"Tom Clancy's H.A.W.X");
HWND Handlefenetre = 0;
Remarquer que j'ai mis le titre entre guillemets précéder d'un "L" le tout entre parenthèses, cela permet la conversion du titre en LPCTSTR
votre code doit être

#include <iostream>     
#include <windows.h>   
using namespace std;
int main ()
{	
	LPCTSTR Titrefenetre = (L"Tom Clancy's H.A.W.X");
	HWND Handlefenetre = 0;
Nous allons maintenant écrire le code permettant de détecter la fenêtre il est très simple :
	Handlefenetre = FindWindow(0,(Titrefenetre));
Quand l'ordinateur doit exécuter cette instruction d'abord il exécute la fonction FindWindow avec les paramètres qu'on lui à donner et il affecte le résultat à la variable Handlefenetre
Cela ne permet pas de vérifier si une fenêtre est lancée ou plutôt ça ne le permet pas de cette façon.
Cette fonction retourne 0 si il n'a rien trouvé et un handle si il a trouvé il suffit donc de faire un test sur la valeur retournée.
Ce test on va le faire dans une boucle do … While .
Ce type de boucle exécute les instructions tant que la condition n'est pas remplie
N'oubliez pas le ";" en fin de condition !
il suffit donc de faire

do
{	Handlefenetre = FindWindow(0,(Titrefenetre));
}		
	while (Handlefenetre == NULL);
Le programme n'ira pas plus loin tant que FindWindow n'a pas renvoyé un handle valide le souci c'est que écrite comme ça cette boucle va littéralement surcharger le processeur car il fait plusieurs fois la boucle par seconde pour vous donner une idée en compilant juste cette partie du code et en l'exécutant mon processeur tournait déjà à 50% …

La solution est de dire au programme de se mettre en pause avant de refaire un tour de boucle grâce à la fonction Sleep( ).

Pour utiliser cette fonction il suffit d'écrire Sleep avec entre parenthèses le nombres de milli secondes à attendre avant de continuer l'exécution du programme la boucle devient donc

do
{	Handlefenetre = FindWindow(0,(Titrefenetre));
	Sleep (500);
}		
	while (Handlefenetre == NULL);
Comme vous le voyez j'ai juste mis une "pause" de 500ms et grâce à ça l'utilisation du processeur tombe à 0%
Le code jusque maintenant est donc :

#include <iostream>     
#include <windows.h>   
using namespace std;
int main ()
{	
	LPCTSTR Titrefenetre = (L"Tom Clancy's H.A.W.X");
	HWND Handlefenetre = 0;
	do
{	
	Handlefenetre = FindWindow(0,(Titrefenetre));
	Sleep (500);
}		
	while (Handlefenetre == NULL);
On pourrait avertir l'utilisateur que l'on a bien détecté le jeu avec un texte :
En dessous du while ajoutons :

cout << "Fenetre du jeu trouvee ... "<< endl;
Une fois que la fenêtre est trouvée par le trainer nous en serons avertie.
Bon c'est bien beau on arrive désormais à savoir si le jeu est lancé on fait quoi maintenant?

Maintenant on va ouvrir un accès en mémoire grâce à la fonction OpenProcess()

https://msdn.microsoft.com/en-us/library/ms684320(VS.85).aspx

Cette fonction prend comme argument 2 DWORD et un BOOL et renvoie un HANDLE ; le premier argument est le type d'accès désiré,le second permet de spécifier si dans le cas ou le processus qu'on ouvre crée un autre processus celui si sera aussi ouvert avec notre OpenProcess() ( enfin moi je l'ai compris comme ça ^^ ) le dernier argument est le PID du processus le PID est le numéro qui identifie un processus c'est différent du HANDLE récupérer avant.

Le souci c'est que le PID on l'a pas !

Donc avant d'appeler OpenProcess() nous devons appeler GetWindowThreadProcessId()

https://msdn.microsoft.com/en-us/library/ms633522.aspx

Cette fonction est vraiment très simple d'utilisation, elle prend deux argument : un Handle sur fenêtre comme nous retourne FindWindow et un pointeur sur un DWORD qui contiendra le PID

Je rappelle qu'un pointeur n'est ni plus ni moins qu'une variable contenant l'adresse mémoire d'une autre variable ; il nous faut donc déclarer un DWORD que nous initialiserons à 0

On retourne la ou on avait déclarer les deux autre variables et on ajoute

DWORD Pid = 0;
Ce qui doit donner :

#include <iostream>     
#include <windows.h>   
using namespace std;
int main ()
{	
	LPCTSTR Titrefenetre = (L"Tom Clancy's H.A.W.X");
	HWND Handlefenetre = 0;
	DWORD Pid = 0;
	do
{	
	Handlefenetre = FindWindow(0,(Titrefenetre));
	Sleep (500);
}		
	while (Handlefenetre == NULL);
	cout << "Fenetre du jeu trouvee ... "<< endl;

et on ajoute en dessous du cout

GetWindowThreadProcessId(Handlefenetre,&Pid);
Si j'ai mis un "&" devant Pid c'est pour préciser que je donne comme argument L'ADRESSE de la variable et non sa valeur qui elle contiendra le PID du processus.

On peut maintenant qu'on a le PID du processus revenir à la fonction OpenProcess()

J'ai dis tout à l'heure que OpenProcess() renvoyer un HANDLE mais nous n'en avons pas déclaré Encore une fois on remonte au niveau des précédentes déclarations et on ajoute
HANDLE Handleprocess = 0;
On va donc appeler OpenProcess() de cette facon :
Handleprocess = OpenProcess (0x10+0x20+0x8,true,Pid);
Si vous vous demandez ce que sont que tout ces 0x machin chose c'est juste l'équivalent DWORD des droits d'accès dispo ici :

https://msdn.microsoft.com/en-us/library/ms684880(VS.85).aspx

Ces droit d'accès sont nécessaire pour lire et écrire en mémoire.

Et pour utilise plusieurs accès il suffit de mettre des "+" entre les valeurs :)

Tout comme FindWindow(), OpenProcess() renvoie 0 en cas d'échec

Nous allons donc réaliser un test mais cette fois avec If qui s'utilise comme ceci :

if (condition)
{
instruction si la condition est vrai
}
else
{
Instruction si la condition est fausse
}
Ce qui donne

#include <iostream>     
#include <windows.h>   
using namespace std;
int main ()
{	
	LPCTSTR Titrefenetre = (L"Tom Clancy's H.A.W.X");
	HWND Handlefenetre = 0;
	DWORD Pid = 0;
	HANDLE Handleprocess = 0 ;
	do
{	
	Handlefenetre = FindWindow(0,(Titrefenetre));
	Sleep (500);
}		
	while (Handlefenetre == NULL);
		
	GetWindowThreadProcessId(Handlefenetre,&Pid);
	cout << "Fenetre du jeu trouvee ... "<< endl;
	Handleprocess = OpenProcess (0x10+0x20+0x8,true,Pid);
	
	if (Handleprocess != NULL)
	{
	cout << "Processus ouvert" << endl;
	}
	else
	{
	cout << "Erreur à l'ouverture du processus "<< endl;
	cout << "Code erreur : " << GetLastError() << endl;
	cout << "Arret du trainer" << endl;
	system ("PAUSE");
	return 0;
	}
Petite explication au sujet de cout : tout ce qui est entre guillemets est affiché, à contrario du reste qui est interprété :
endl signifie fin de ligne et ici la fontion GetLastError() renvoie le dernier code d'erreur rencontré c'est assez utilise pour déboguer une application qui fonctionne chez vous mais pas chez les autres ou qui compile mais ne fonctionne pas comme on le voudrait.

J'ai ajouter trois petites lignes qui permette d'avertir que l'on va arrêter le trainer si le test n'a pas abouti et que l'on ajoute pas ces lignes même si le test échoue le programme continuera de s'exécuter

Maintenant, on va essayer de lire en mémoire grâce à la fonction ReadProcessMemory()

https://msdn.microsoft.com/en-us/library/ms680553.aspx

Cette fonction prend 5 arguments mais nous n'en utiliserons que 4 ce qui est amplement suffisant pour notre utilisation

Le premier argument est un HANDLE sur processus que l'on a obtenu via OpenProcess(), le second l'adresse à lire caster en void* ( je ne pourrais pas trop vous aider sur le pourquoi du comment j'ai juste compris que ça fonctionné comme ça :/ ) , un pointeur vers une variable qui recevra les une copie des données écrites en mémoire et le quatrième la nombre d'octet à lire .
Avec WriteProcessMemory, ReadProcessMemory seront les deux fonctions les plus compliqué à utiliser à ce stade du tuto nous somme à mis chemin du but .

N'hésitez pas à faire des pauses le bourrage de crane c'est pas idéal ;),

On va avoir besoin de déclaré deux Int l'un pour l'adresse mémoire, l'autre pour les données lu.

Vous savez ou aller je vous donne les deux lignes ;)

int Adressememoire = 0x7C8F77;
int Valeurlue = 0;
Vous avez surement reconnu l'adresse obtenu via Tsearch et l'AutoHack window il faut juste la faire précéder de "0x" car nous allons travailler en base héxadécimal au niveau de la mémoire.

ReadProcessMemory renvoie 0 si la lecture en mémoire à échouer

Nous allons donc faire un test de lecture en mémoire, préparez le petit papier ou vous avez notez les résultat de Tsearch nous allons en avoir besoin .

Pour faire un test nous allons donc réutiliser if mais cette fois si avec deux conditions le test sera négatif si les deux condition ne sont pas remplie && signifie AND ( et) et || signifie OR (ou)

if ((condition1)&&(condition2))
{
instruction si les conditions sont vrais
}
else
{
Instruction si les conditions sont fausses
}
Voici le test :

if ((ReadProcessMemory(Handleprocess,reinterpret_cast<void*>(Adressememoire),&Valeurlue,3,0) != 0)&&(Valeurlue == 0x286e01))
HandleProcess c'est ce que l'on a obtenu avec

 OpenProcess ,reinterpret_cast<void*>(Adressememoire) c'est l'adresse mémoire réinterprété par la fonction pour qu'elle puisse l'utiliser
Ensuite le pointeur pour recevoir les données et enfin 3
car nous voulons lire 3 octets, l'instruction de base que nous souhaitons modifier est codé sur 3 octets.

Le 0 de fin signifie à la fonction d'ignorer ce paramètre mais il est obligatoire de le mettre

Le test sera donc positif si la lecture a fonctionné et si la valeur lue est égale à 0x286e01 qui est enfaite la valeur trouvé via Tsearch mais placé en ordre inversé et précédé de "0x"

Je ne sais pas pourquoi l'ordre est inversé mais j'ai découvert ça car j'ai un peu bloqué dessus.

Le code est donc maintenant

#include <iostream>     
#include <windows.h>   
using namespace std;
int main ()
{	
	LPCTSTR Titrefenetre = (L"Tom Clancy's H.A.W.X");
	HWND Handlefenetre = 0;
	DWORD Pid = 0;
	HANDLE Handleprocess = 0 ;
	int Adressememoire = 0x7C8F77;
	int Valeurlue = 0;
	do
{	
	Handlefenetre = FindWindow(0,(Titrefenetre));
	Sleep (500);
}		
	while (Handlefenetre == NULL);
	cout << "Fenetre du jeu trouvee ... "<< endl;
	GetWindowThreadProcessId(Handlefenetre,&Pid);
	Handleprocess = OpenProcess (0x10+0x20+0x8,true,Pid);
	if (Handleprocess != NULL)
	{
	cout << "Processus ouvert" << endl;
	}
	else
	{
	cout << "Erreur à l'ouverture du processus "<< endl;
	cout << "Code erreur : " << GetLastError() << endl;
	cout << "Arret du trainer" << endl;
	system ("PAUSE");
	return 0;
	
	}
	
		if ((ReadProcessMemory(Handleprocess,reinterpret_cast<void*>(Adressememoire),&Valeurlue,3,0) != 0)&&(Valeurlue == 0x286e01))
	{
		cout << "Lecture en mémoire possible !" << endl;
	}
	else 
	{
		cout << "Erreur de lecture en mémoire, assurez vous d'utiliser la version 1.02 du jeu."<< endl;
		cout << "Ou que le trainer n'est pas deja lancé" << endl;
		cout << "Code erreur : " << GetLastError() << endl;
		cout << "Arret du trainer" << endl;
		system ("PAUSE");
		return 0;
	}
Si je fais un test pour savoir si la valeur est égale à 0x286e01 c'est pour détecter une éventuel utilisation du trainer sur une mauvaise version du jeu.
Je sais que ça commence à faire beaucoup mais accrochez vous c'est bientôt fini à ce stade on détecte le jeu et on arrive à lire la mémoire il nous reste qu'à écrire.

Pour écrire nous allons utiliser la fonction WriteProcessMemory () qui prend 5 paramètres lui aussi mais nous n'en utiliserons que 4.

https://msdn.microsoft.com/en-us/library/ms681674(VS.85).aspx

Le premier est un handle sur processus le même que celui qu'on à fourni à ReadProcessMemory
Le seconde l'adresse mémoire casté de la même façon que pour ReadMemory
Le troisième est un pointeur sur une variable de type BYTE qui contient les données à écrire en mémoire
Le 4eme est la taille du patch qu'on récupérera via l'opérateur sizeof
On a tous ce qu'on a besoin sauf le patch donc on repart au niveau de toute les déclarations et on ajoute
BYTE patch[] = "\x90\x90\x90";
Vous aurez reconnu les 909090 trouvé par Tsearch juste précédé par "\x"
Nous avons donc maintenant :

#include <iostream>     
#include <windows.h>   
using namespace std;
int main ()
{	
LPCTSTR Titrefenetre = (L"Tom Clancy's H.A.W.X");
HWND Handlefenetre = 0;
DWORD Pid = 0;
HANDLE Handleprocess = 0 ;
int Adressememoire = 0x7C8F77;
int Valeurlue = 0;
BYTE patch[] = "\x90\x90\x90";	
do
{	
Handlefenetre = FindWindow(0,(Titrefenetre));
Sleep (500);
}		
while (Handlefenetre == NULL);
cout << "Fenetre du jeu trouvee ... "<< endl;
GetWindowThreadProcessId(Handlefenetre,&Pid);
Handleprocess = OpenProcess (0x10+0x20+0x8,true,Pid);
if (Handleprocess != NULL)
{
cout << "Processus ouvert" << endl;
}
else
{
cout << "Erreur à l'ouverture du processus "<< endl;
cout << "Code erreur : " << GetLastError() << endl;	
}

if ((ReadProcessMemory(Handleprocess,reinterpret_cast<void*>(Adressememoire),&Valeurlue,3,0) != 0)&&(Valeurlue == 0x286e01))
{
cout << "Lecture en mémoire possible !" << endl;
}
else 
{
cout << "Erreur de lecture en mémoire, assurez vous d'utiliser la version 1.02 du jeu."<< endl;
cout << "Ou que le trainer n'est pas deja lancé" << endl;
cout << "Code erreur : " << GetLastError() << endl;
}

0x286e01
Nous allons maintenant tenter d'écrire en mémoire

Donc on va re faire un test je ré-explique pas tout, c'est semblable à ce qui a déjà été traité ; si valeur de retour = 0 ça a fonctionné

Je vais juste m'attarder sur l'opérateur sizeof() qui permet de savoir la taille d'une variable ou d'un objet sachant que c'est ce qui est attentu comme 4eme argument dans cette fonction, son utilisation nous facilite la tache

if (WriteProcessMemory(Handleprocess,reinterpret_cast<void*>(Adressememoire),&patch,sizeof(patch),0) != 0)
{
cout << "Injection reussie" << endl;
}
else
{
cout << "Injection ratee code erreur :" << GetLastError() << endl ;
cout << "Arret du trainer" << endl;
system ("pause");
return 0;
}
Ce qui donne donc jusque ici :

#include <iostream>     
#include <windows.h>   
using namespace std;
int main ()
{	
LPCTSTR Titrefenetre = (L"Tom Clancy's H.A.W.X");
HWND Handlefenetre = 0;
DWORD Pid = 0;
HANDLE Handleprocess = 0 ;
int Adressememoire = 0x7C8F77;
int Valeurlue = 0;
BYTE patch[] = "\x90\x90\x90";	
do
{	
Handlefenetre = FindWindow(0,(Titrefenetre));
Sleep (500);
}		
while (Handlefenetre == NULL);
cout << "Fenetre du jeu trouvee ... "<< endl;
GetWindowThreadProcessId(Handlefenetre,&Pid);
Handleprocess = OpenProcess (0x10+0x20+0x8,true,Pid);
if (Handleprocess != NULL)
{
cout << "Processus ouvert" << endl;
}
else
{
cout << "Erreur à l'ouverture du processus "<< endl;
cout << "Code erreur : " << GetLastError() << endl;	
}	
if ((ReadProcessMemory(Handleprocess,reinterpret_cast<void*>(Adressememoire),&Valeurlue,3,0) != 0)&&(Valeurlue == 0x286e01))
{
cout << "Lecture en mémoire possible !" << endl;
}
else 
{
cout << "Erreur de lecture en mémoire, assurez vous d'utiliser la version 1.02 du jeu."<< endl;
cout << "Ou que le trainer n'est pas déja lancé" << endl;
cout << "Code erreur : " << GetLastError() << endl;
cout << "Arret du trainer" << endl;
system ("pause");
}
if (WriteProcessMemory(Handleprocess,reinterpret_cast<void*>(Adressememoire),&patch,sizeof(patch),0) != 0)
{
cout << "Injection reussie" << endl;
}
else
{
cout << "Injection ratee code erreur :" << GetLastError() << endl ;
cout << "Arret du trainer" << endl;
system ("pause");
return 0;
}

Il ne reste plus qu'a faire une boucle de contrôle au cas ou la valeur change et puis c'est fini !

On va donc faire une boucle Do ... While qui aura comme condition la détection du jeu

Et dans cette boucle on va faire un test sur la valeur qui est en mémoire,
Si elle a pas changé on ne fait rien
Si elle a changé on tente de réécrire si ça fonctionne on repars pour un tour de boucle si ça na pas fonctionné on arrête le trainer on affiche un message avec un code d'erreur.
do
{
ReadProcessMemory(Handleprocess,reinterpret_cast<void*>(Adressememoire),&Valeurlue,3,0);
if (Valeurlue != 0x909090)
{
cout << "Les donnees injectees en memoire on ete remplacees" << endl;
cout << "Tentative de reinjection ..." << endl;
if (WriteProcessMemory(Handleprocess,reinterpret_cast<void*>(Adressememoire),&patch,sizeof(patch),0) != 0)
{
cout << "Reinjection reussie" << endl;
}
else
{
cout << "Reinjection ratee code erreur :" << GetLastError() << endl ;
cout << "Arret du trainer" << endl;
system ("pause");
return 0;
}
}
Sleep (500);
}
while (FindWindow(0,(Titrefenetre)) == Handlefenetre);

cout << "Le jeu a ete coupe "<< endl;
cout << "Arret du trainer ..." << endl;
CloseHandle(Handleprocess);
system("PAUSE");
return 0;
}


Cette dernière partie est la plus compliquée car il y a deux if imbriquer l'un dans l'autre relisez calmement et vous comprendrez, j'y ai ajouté un "Sleep" pour ne pas surcharger mon processeur inutilement.

Vous remarquerez que j'appelle CloseHandle avec le nom de l'handle retourné par OpenProcess car il faut refermer un Handle ouvert, pour le handlefenetre c'est différent on n'a pas à le refermer ,

Je vous donne mon code que vous êtes libres de modifier à votre guise la seule chose que je demande c'est de savoir ce que vous avez modifier ça pourrait me permettre de m'améliorer.


#include <iostream>     
#include <windows.h> 			

using namespace std;

int main ()
{
LPCTSTR Titrefenetre = (L"Tom Clancy's H.A.W.X");
HWND Handlefenetre = 0;
BYTE patch[] = "\x90\x90\x90";						
int Adressememoire = 0x7C8F77;					
DWORD Pid = 0;										
int Valeurlue = 0;				
HANDLE Handleprocess = 0;

SetConsoleTitleA ("Tom Clancy's H.A.W.X V 1.02 trainer By NiCk.0"); 
cout << "Lancement du trainer" << endl;
cout << endl;
cout << "Pour toute remarque ou suggestion -> geek-59600 @ hotmail.fr" << endl;
cout << endl;
cout << "En attente du jeu ..." << endl;

do{											

Sleep (500);

Handlefenetre = FindWindow(0,(Titrefenetre));}	

while (Handlefenetre == NULL);	

GetWindowThreadProcessId(Handlefenetre,&Pid);	
											
cout << "Fenetre trouvee ... "<< endl;
cout << "Tentative d'ouverture du processus" << endl;
Handleprocess = OpenProcess (0x10+0x20+0x8,true,Pid);	

if (Handleprocess != NULL)
{
cout << "Processus ouvert " << endl;
}
else
{
cout << "Erreur à l'ouverture du processus code erreur :" << GetLastError() << endl;
cout << "Arret du trainer " << endl;
system ("pause");
return 0;
}

cout << "Tentative de lecture en memoire" << endl;

if ((ReadProcessMemory(Handleprocess,reinterpret_cast<void*>(Adressememoire),&Valeurlue,3,0) != 0)&&(Valeurlue == 0x286e01))
{
cout << "Ok !" << endl;
}
else 
{
cout << "Erreur de lecture en memoire, assurez vous d'utiliser la version 1.02 du jeu."<< endl;
cout << "Ou que le trainer n'est pas deja lancé" << endl;
cout << "Arret du trainer" << endl;
system ("pause");
return 0;
}
cout << "Tentative d'injection du patch" << endl;
												 
if  (WriteProcessMemory(Handleprocess,reinterpret_cast<void*>(Adressememoire),&patch,sizeof(patch),0) != 0)
{
cout << "Injection reussie" << endl;
}
else
{
cout << "Injection ratee code erreur :" << GetLastError() << endl ;
cout << "Arret du trainer" << endl;
system ("pause");
return 0;
}

do
{
ReadProcessMemory(Handleprocess,reinterpret_cast<void*>(Adressememoire),&Valeurlue,3,0);
if (Valeurlue != 0x909090)
{
cout << "Les donnees injectees en memoire on ete remplacees" << endl;
cout << "Tentative de reinjection ..." << endl;
if (WriteProcessMemory(Handleprocess,reinterpret_cast<void*>(Adressememoire),&patch,sizeof(patch),0) != 0)
{
cout << "Reinjection reussie" << endl;
}
else
{
cout << "Reinjection ratee code erreur :" << GetLastError() << endl ;
cout << "Arret du trainer" << endl;
system ("pause");
return 0;
}
}
Sleep (500);
}
while (FindWindow(0,(Titrefenetre)) == Handlefenetre);

cout << "Le jeu a ete coupe "<< endl;
cout << "Arret du trainer ..." << endl;
CloseHandle(Handleprocess);
system("PAUSE");
return 0;
}
La fonctione SetConsoleTitleA () permet de modifier le titre de notre application console.

Have Fun

Introduction et prérequi
Recherche de l'adresse mémoire à l'aide de Tsearch


Partners