Creation d'une DLL-Proxy pour Cheat / hack

    Publicités

Users Who Are Viewing This Thread (Total: 0, Members: 0, Guests: 0)

Mar 30, 2011
1,014
1
944
In Your Ass
Infos :
Ceci est l'adaptation en partie du tuto de Thiesius de Elitepvp
Sur la creation d'un cheat sous forme de dll



Let's go .....

Pour ce Tuto je continue d'utiliser Rumerstrike
(déjà utiliser pour ce tuto --> http://www.cheat-gam3.com/tutoriel/tuto-creer-un-cheat-de-z-163096/ )

1] THEORIE

Le principe de la DLL-proxy est de se placer entre le programme cible
(jeu , logiciel ect ...) et la vrai DLL
Le programme charge la dll et dans celle ci il y a notre code en plus d'un pont
vers les fonctions de la vrai dll

Pour Romustrike j'ai opté pour la SDL.DLL (pour plus tard je veux bidouiller les fonctions graphiques)


Je ne maitrise pas encore tres bien les meandres du C++ il y a certaine partie (comme celle ci ) qui vont etre tres .... light ;)

Pour creer le la dll il nous faut toutes les infos de l'originale
Pour les exports on utilise un wrapper qui vas faire ca pour nous
( en piece jointe )

2] CREATION DE LA DLL-PROXY

Copiez dans votre repertoire de travail la dll qui se trouve dans le jeu
Monrep\SDL.dll

Etape 1:
On recupere la liste des export grace a visual studio
Demarer/Tout les programmes/Microsoft Visual Studio xxxx/Visual Studio Tools/Visual Studio Command Prompt (xxxx).
(ouverture d'une console Dos)

Etape 2:
Changer de repertoire pour arriver dans votre repertoire de travail
Tapez la commande suivante :
DUMPBIN /EXPORTS SDL.dll > EXPORTS.txt

Par curiosité regardez dans le fichier exports.txt vous avez toutes les fonction de la dll ;)


Etape 3:
Renommer la dll originale ex : SDL_.DLL



Etape 4:
On est pret pour utiliser le wrapper . La syntaxe est la suivante :
<dll><convention><nouveau nom de la dll><cpp><def>
<dll> Ancien nom de la dll originale
<txt> l'export.txt creer juste avant
<convention> Convention d'appel des fonctions
<nouveau nom de la dll> donc le nom (sdl.dll)
<cpp>nom du fichier .cpp generer
<def>nom du fichier .def generer

La commande : wrappit.exe SDL.dll EXPORTS.txt __stdcall SDL_.dll sdl.cpp Exports_Def.def

(perso sa fini en erreur il ne trouve pas le fichier sdl.cpp.obj mais ca ne gene pas )

Etape 5:
Le repertoire contient 2 nouveaux fichier : SDL.cpp and Exports_Def.def

Felicitation le squelette de la DLL est cree ;)

3] CREATION DU CHEAT/HACK/MENU

1] Le projet

Dans visual studio (express fonctionne aussi) creer une dll vide et ajoutez le code source SDL.cpp
Faite un clic droit sur votre projet et propriétés
Proprietes de configuration>general>Jeu de caracteres>caractere multioctet

Proprietes de configuration>Editeur de liens>entrée>Fichier de definition de module> Entrez : Exports_Def.def

Sauvez et fermez

Code:
#include <windows.h>
#pragma pack(1)


HINSTANCE hLThis = 0;
HINSTANCE hL = 0;
FARPROC p[202] = {0};

BOOL WINAPI DllMain(HINSTANCE hInst,DWORD reason,LPVOID)
	{
	if (reason == DLL_PROCESS_ATTACH)
		{
		hLThis = hInst;
		hL = LoadLibrary("SDL_.dll");
		if (!hL) return false;


		p[0] = GetProcAddress(hL,"SDL_AddTimer");
		p[1] = GetProcAddress(hL,"SDL_AllocRW");
		p[2] = GetProcAddress(hL,"SDL_AudioDriverName");
		p[3] = GetProcAddress(hL,"SDL_AudioInit");
		p[4] = GetProcAddress(hL,"SDL_AudioQuit");
		p[5] = GetProcAddress(hL,"SDL_BuildAudioCVT");
		p[6] = GetProcAddress(hL,"SDL_CDClose");
		p[7] = GetProcAddress(hL,"SDL_CDEject");
		p[8] = GetProcAddress(hL,"SDL_CDName");
		p[9] = GetProcAddress(hL,"SDL_CDNumDrives");
		p[10] = GetProcAddress(hL,"SDL_CDOpen");
		p[11] = GetProcAddress(hL,"SDL_CDPause");
		p[12] = GetProcAddress(hL,"SDL_CDPlay");
		p[13] = GetProcAddress(hL,"SDL_CDPlayTracks");

le source généré charge la dll d origine et récupère toutes les adresses de fonction pour pouvoir faire le pont correctement

C'est a cet endroit qu on vas creer un autre thread pour activer notre cheat

je ne connais pas encore bien cette partie (la creation du thread et les attibut de securité)

Dans le principe c est assez claire
Si la dll d origine est bien chargée on creer le thread qui commence
par la routine declarer dans le createthread
ici CheatMain


Code:
void CheatMain()
{
	Sleep(10000); // 10 seconde d'attente
	CommandComm(); // Creation de la console
	SetConsoleTitleA("Proxy-dll v0.01"); // Change le titre de la console
	Menu(); // affiche le menu .help ;)
	CommandHandler(); // la gestion des commandes ;)
}

C est l'initialisation du cheat
La pause de 10 secondes est la pour eviter une détection du jeux apparemment dans le sujet initial

CommandComm() creer la console
Menu() affiche les commandes dispo
CommandHandler() c est la boucle principal qui attend les commandes

Code:
void CommandHandler()   // la boucle principale qui vas attendre les commandes
{
	while(true) // Ma boucle principale
	{
		char chCommand[255]={0}; // Ma variable qui vas stocké les commandes claviers

		scanf("%s", &chCommand); // Attente l'entré clavier et stock le resultat dans chCommand (maxi 254 caracteres .... ca vas la pire de commande passe ;) )
	    // pour les pro du C++ la ligne d origine c est scanf_s("%s%*c", &chCommand);  mais sa fait planter le prog , j ai tester plusieur syntaxe sans resultats
		// visual c++ emet un warning avec les scanf mais ca passe pour ce que j en fait


		if (strcmp ( chCommand , ".Cmd01" ) == 0) // si la chaine contenu dans chCommand est eqale a .Cmd01 alors j execute les commandes dans les accolades
		{

			printf_s("Message recu OK: .Cmd01 ");
			printf_s("\nEnter Command: ");
		}

		if (strcmp ( chCommand , ".Cmd02" ) == 0) // idem dessus
		{
            printf_s("Message recu OK: .Cmd02 ");
			printf_s("\nEnter Command: ");

		}

		if (strcmp ( chCommand , ".Help" ) == 0) // idem dessus
		{
			printf_s("\n");
			Menu(); // appel du menu d'affichage de la liste des commandes
		}
	}
}



Si quelqu un peut me dire pourquoi la syntaxe d'origine ne fonctionne pas ça m'interesse

Code:
scanf_s("%s%*c", &chCommand);

Vous compilez tout ca et c'est bon !!!
Copiez la dll dans le repertoire du jeux sous le nom SDL.dll

Lancez romustrike et au bout de 10 secondes la console s ouvre ;)

ci-joint le projet et le wrapper ;)

prochaine étape le cheat par lui meme , peut etre un menu dans le jeux ;)
 

Attachments

  • C++.rar
    19.9 KB · Views: 10
Last edited:

TheHardButcher

Programmeur C/C++
V
Dec 14, 2009
1,461
58
964
France
Un tuto très intéressant, surtout que je ne connaissais pas cette façon de modifier les fonctions d'une dll, mais il manque certain précision selon moi :)

Tout d'abord, wrappit.exe n'est pas vraiment rependu, et il pourrais être très intéressant d'en partager les sources ici (j'ai trouvé quelques chose sur codeproject, mais je te laisse nous montrer quels sont tes sources)

Ensuite pour ce qui est de la création de thread, tu crées des fonctions, mais je ne comprend pas vraiment comment tu les appels (j'aurais bien lut les sources, mais le fichier .rar n'est pas dispo)

Néanmoins, cela fait vraiment plaisir de voir un vrai tuto dans la section C++, bien joué :)


EDIT : Le fichier est maintenant dispo (down temporaire ^^)
1. wrappit est donc bien avec, merci, dommage qu'il n'y ai pas les sources
2. Aucune source réel dans le .rar donc toujours pas de réponse a ça !
Merci ;)
 
Last edited:
Mar 30, 2011
1,014
1
944
In Your Ass
Hello !
Tout d'abord, wrappit.exe n'est pas vraiment rependu, et il pourrais être très intéressant d'en partager les sources ici (j'ai trouvé quelques chose sur codeproject, mais je te laisse nous montrer quels sont tes sources)

Comme dit tout au debut ceci vient de chez Elitepvp
Le wrapper est fournis pas l'auteur mais je ne sais pas si c'est de lui
Cela doit etre destiné a autre chose j'imagine (au vue du message d erreur)
Ici sa nous simplifie la tache ;)

Ensuite pour ce qui est de la création de thread, tu crées des fonctions, mais je ne comprend pas vraiment comment tu les appels (j'aurais bien lut les sources, mais le fichier .rar n'est pas dispo)
Effectivement le source etait hors projet et j ai zapper de l'importer
C'est rectifier , j ai ré up l'archive

En faite a l'initialisation de la dll le thread est lancer avec comme
Routine d'execution : CheatMain()

Code:
CreateThread(&SCAttrib, NULL, (LPTHREAD_START_ROUTINE)[COLOR="Red"][B]CheatMain[/B][/COLOR], NULL, NULL, NULL)

Ca lance l'initialisation et la suite decrite dans la section 3

(ma boucle principale etant CommandHandler() )


J'ai volontairement reduit le tuto d'origine a cette partie pour l'instant
Je n ai pas encore tester le reste .

pour l export des fonction il y a des truc pas mal ici :

Ce lien n'est pas visible, veuillez vous connecter pour l'afficher. Je m'inscris!
Ce lien n'est pas visible, veuillez vous connecter pour l'afficher. Je m'inscris!

et le sujet sur le quel je m appuis

Ce lien n'est pas visible, veuillez vous connecter pour l'afficher. Je m'inscris!
 
Last edited:

TheHardButcher

Programmeur C/C++
V
Dec 14, 2009
1,461
58
964
France
Ok merci, pour le moment j'ai juste (ré)installé VS12 et ça compile correctement, je lirais a l'occasion le reste des infos, et je te tiendrais au courant si je trouve des trucs cool, merci :)

PS : pour ce qui est du wrapper, je pense que l'article de elitepvp qui fait référence a "Michael Chourdakis" fait référence a cette article :
Ce lien n'est pas visible, veuillez vous connecter pour l'afficher. Je m'inscris!

Je vous conseil de lire le tout, ce n'est pas très long, mais super intéressant :)
 
Mar 30, 2011
1,014
1
944
In Your Ass
Oui !! merci pour le lien !
Je cherchais comment intercepter les variables des appel d'origine :)
Je vais pouvoir recup les infos d affichage ;)

Tu sais si ce system fonctionne avec du .net ?
 
May 23, 2013
508
0
322
'merica
C'est plus du C que du C++ :/

Sinon c'est la première fois que je vois cette technique de hooking, IMO ce n'est pas très "propre", vaut mieux utiliser des pointeurs vers fonctions, comme ça on peut manipuler les arguments plus facilement.

Pour le "problème" avec scanf, c'est le code original qui est incorrect, il n'y a qu'un seul argument (qui est un char* ), donc il faut un seul '%', suivi d'un 's' pour une chaine de caractères.

Et oui c'est possible en .NET, en utilisant des délégués.
 
May 23, 2013
508
0
322
'merica
Bah tu définit un pointeur vers une fonction comme ça :
Code:
typedef int (WINAPI *pMessageBoxA) (HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);

Puis tu définis ta fonction de hook avec les mêmes arguments, comme ça quand ta fonction est exécutée, tu contrôles l’exécution (tu peux modifier les arguments, retourner une valeur bidon etc ...)
 
Mar 30, 2011
1,014
1
944
In Your Ass
Bah tu définit un pointeur vers une fonction comme ça :
Code:
typedef int (WINAPI *pMessageBoxA) (HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);

Puis tu définis ta fonction de hook avec les mêmes arguments, comme ça quand ta fonction est exécutée, tu contrôles l’exécution (tu peux modifier les arguments, retourner une valeur bidon etc ...)

Ok , si je comprend c'est dans le cas ou je remplace la fonction que je choisis c'est ca ?

si je veux changer les infos et appeler la fonction normale ?

exemple une fonction avec comme variable int=5

le programme appel la fonction dans la dll avec

fonction(5) > ma fonction qui transforme en fonction(6) > appel de la fonction d'origine fonction(6) > et gestion du retour
 
May 23, 2013
508
0
322
'merica
C'est un peu plus complexe que ça ;)

Quand tu remplaces les premiers bytes d'une fonction (pour la rediriger vers ta fonction), elle devient inutilisable, donc tu ne peut pas l'appeler de ton propre code sinon ça fait un appel récursif infini.
Donc pour éviter ça on utilise un trampoline, c'est une fonction qui exécute les premiers bytes de la fonction originale, puis qui saute vers le reste de la fonction originale pour exécuter le reste.

En gros:

-Appel vers une fonction que tu as hook
-Appel de ta fonction
-Appel du trampoline / modification des arguments / log
-Exécution de la fonction originale.
-Modification de la valeur de retour

ah-trampoline.png

(source: jbremer, Juillet 2012, Ce lien n'est pas visible, veuillez vous connecter pour l'afficher. Je m'inscris!)
 

TheHardButcher

Programmeur C/C++
V
Dec 14, 2009
1,461
58
964
France
> Casimir : Tout d'abord, pour ce qui est des arguments, tu peux les avoir de deux façons.
1. Tu peux regarde la fin du lien que j'ai posté plus haut Ce lien n'est pas visible, veuillez vous connecter pour l'afficher. Je m'inscris!
Once the cpp is ready, you should replace functions that you know how to use. For example, If you want to spy on Wsock32.send():

// send, created by wrappit
extern "C" __declspec(naked) void __stdcall __E__69__()
{
__asm
{
jmp p[69*4];
}
}

// If you want to manipulate it, change to:
extern "C" int __stdcall __E__69__(SOCKET x,char* b,int l,int pr)
{
// manipulate here parameters

.....
// call original send
typedef int (__stdcall *pS)(SOCKET,char*,int,int);
pS pps = (pS)p[63*4];
int rv = pps(x,b,l,pr);

return rv;
}
2. Tu change de méthode comme le conseil davydavekk

> davydavekk : Je suis d'accord sur le faite que ce n'est pas très propre, mais ça a le mérite d'être très simple au niveau de la compréhension et de la mise en place
 
Mar 30, 2011
1,014
1
944
In Your Ass
Ha lol c est justement le passage concernat mon message privé ;)
tu sais pourquoi au moment d'appeler la fonction originale il se sert de la 63 et pas la 69 ?

---------- Message ajouté à 20h13 ---------- Le message précédent était à 20h10 ----------

C'est un peu plus complexe que ça ;)
Quand tu remplaces les premiers bytes d'une fonction (pour la rediriger vers ta fonction), elle devient inutilisable, donc tu ne peut pas l'appeler de ton propre code sinon ça fait un appel récursif infini.
Donc pour éviter ça on utilise un trampoline, c'est une fonction qui exécute les premiers bytes de la fonction originale, puis qui saute vers le reste de la fonction originale pour exécuter le reste.

En gros:

-Appel vers une fonction que tu as hook
-Appel de ta fonction
-Appel du trampoline / modification des arguments / log
-Exécution de la fonction originale.
-Modification de la valeur de retour


En faite dans l'immediat que jveux rester sur le principe de DLL-proxy pour avancer sur ce post ;)
Mais je note tes infos dans un coin ;)
 

TheHardButcher

Programmeur C/C++
V
Dec 14, 2009
1,461
58
964
France
Alors tout d'abord, dans le premier cas on utilise naked pour dire au compilo qu'on veux pas d'intro/outro. Si tu comprend pas bien, lit juste les intro des posts de la msdn :
Ce lien n'est pas visible, veuillez vous connecter pour l'afficher. Je m'inscris!
Ce lien n'est pas visible, veuillez vous connecter pour l'afficher. Je m'inscris!

Mais si on regarde bien la fonction send :
Ce lien n'est pas visible, veuillez vous connecter pour l'afficher. Je m'inscris!

On sais donc :
int send(
_In_ SOCKET s,
_In_ const char *buf,
_In_ int len,
_In_ int flags
);

On change donc dans le code "__declspec(naked) void" par "int"

Ensuite, on a qu'a donné les params comme la fonction de base en changeant "__stdcall __E__69__()" par "__stdcall __E__69__(SOCKET x,char* b,int l,int pr)"


Après on défini un pointeur de fonction comme en parlait davy
"typedef int (WINAPI *pMessageBoxA) (HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);"

Donc ça donne notre "typedef int (__stdcall *pS)(SOCKET,char*,int,int);"

pS pps = (pS)p[63*4]; < Ici je pense qu'il y a une erreur, et que c'est p[69], mais vu que je n'ai pas testé, je ne peux pas m'avancer plus que ça
int rv = pps(x,b,l,pr);
 

Misuki

Git Wizard en freelance
V
Ancien staff
Jun 15, 2012
2,303
66
954
EDIT: J'ai réglé mon problème tous seul, parfois je suis un peu un tard x')
 
Last edited:
Mar 30, 2011
1,014
1
944
In Your Ass
il faut le mettre dans ton projet
sur ton message d erreur il dit ne pas le trouver ici :
Code:
c:\Users\MyHand\documents\visual studio 2013\Projects\Projet1\Projet1\

copie le dedans
et le source (fichier .cpp) met le dans le rep de ton projet aussi .
comme ca si tu bouge ou compresse ton projet tu ne perd rien

---------- Message ajouté à 21h58 ---------- Le message précédent était à 14h03 ----------

pS pps = (pS)p[63*4]; < Ici je pense qu'il y a une erreur, et que c'est p[69], mais vu que je n'ai pas testé, je ne peux pas m'avancer plus que ça
int rv = pps(x,b,l,pr);

d'apres mes premiers test non il n y a pas d erreur
ce n est pas un tableau de 4 octet par unité
c'est un tableau d adresse codé sur 4 byte
pour trouver l'adresse il faut multiplier par 4 son numero pour etre au bon endroit dans le tableau

par contre je pense que c est 69 et pas 63 ;)

je fait une bricole pour tester ;)

---------- Message ajouté à 23h37 ---------- Le message précédent était à 21h58 ----------

On sais donc :

On change donc dans le code "__declspec(naked) void" par "int"

Ensuite, on a qu'a donné les params comme la fonction de base en changeant "__stdcall __E__69__()" par "__stdcall __E__69__(SOCKET x,char* b,int l,int pr)"


Après on défini un pointeur de fonction comme en parlait davy
"typedef int (WINAPI *pMessageBoxA) (HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);"

Donc ça donne notre "typedef int (__stdcall *pS)(SOCKET,char*,int,int);"

pS pps = (pS)p[63*4]; < Ici je pense qu'il y a une erreur, et que c'est p[69], mais vu que je n'ai pas testé, je ne peux pas m'avancer plus que ça
int rv = pps(x,b,l,pr);

j ai tester avec ce code sur la fonction SDL_Delay
qui a pour argument un uint32 represetant le temps en MS pour une pause , retour nul

Code:
extern "C" void __stdcall __E__33__(int ms) // extern "C" int __stdcall __E__69__(SOCKET x,char* b,int l,int pr)
	{

		typedef void (__stdcall *pS)(int);
		pS pps = (pS)p[33*4];
		pps(ms);

    
	}

l'appel 33*4 est bon j ai tester
en faite quand je test sans essayer d intercepter les argument ca fonctionne
quand j essai de recup les info ca plante
 

TheHardButcher

Programmeur C/C++
V
Dec 14, 2009
1,461
58
964
France
l'appel 33*4 est bon j ai tester
en faite quand je test sans essayer d intercepter les argument ca fonctionne
quand j essai de recup les info ca plante

Tu as essayer de juste rajouter quelques commandes qui n'utilise pas les arguments ?
 
Mar 30, 2011
1,014
1
944
In Your Ass
oui , si tu rajoute du code avant "asm" ca fonctionne bien
par contre quand je change la fonction pour recuperer les argument ca plante
 

TheHardButcher

Programmeur C/C++
V
Dec 14, 2009
1,461
58
964
France
en faite quand je test sans essayer d intercepter les argument ca fonctionne
quand j essai de recup les info ca plante

Mais si tu test avec le code comme pour intercepter, mais sans rien toucher ça fonctionne, mais, et si tu rajoute des choses avant ?
Je parle pas de la version du code avec "asm"

Enfin pas sur qu'on se soit bien comprit ^^