Chalut chers lecteurs,
Ces derniers temps la mode fait que je m'interesse de plus en plus au Reverse Engineering. C'est vrai que je vois de plus en plus de tutorials fleurir à ce sujet. Ca m'a donné envie de m'y mettre. L'été arrive (je reconnais le début de cette période à la tenue vestimentaire des filles...mes demoiselles vous êtes ravissantes!! (Dédicace à Anne-Laure) ) mais avec lui aussi la période des exams, c'est donc entre 2 révisions que je rédige ce tutorial à propos de Web Construction Kit 3.0. J'ai en effet constaté que ce programme comporte quelques bugs à éliminer et quelques améliorations pourraient être envisageable...Bonne Lecture (je retourne réviser un peu sinon demain je vais être mal!!).
Au lancement du logiciel...
A chaque fois qu'on désire utiliser Web Construction Kit 3.0, un NagScreen surgit. Il vous indique le nombre de fois que vous avez utilisé le logiciel. A partir de ce moment vous avez le choix entre continuer en version non enregistrée (je précise qu'il n'y a pas de limitations des fonctions) ou de vous enregistrer. Si vous désirez vous enregistrer, une fenêtre apparaitra vous demandant votre nom et votre code d'enregistrement. Lorsque vous quittez Web Construction Kit, ce NagScreen est affiché de nouveau!! C'est vraiment ennuyeux et il va falloir changer tout ça.
Les endroits clés de la protection...
La protection de ce logiciel est vraiment minable et ce n'est vraiment pas difficile de trouver les endroits sensibles du programme qui permettront à n'importe quels crackeurs venus de passer d'une version non enregistrée à une version enregistrée.
La méthode que j'ai utilisé pour contre carrer la protection est ultra-classique : BPX Hmemcpy après avoir rempli soigneusement les 2 champs : nom d'utilisateur et code d'enregistrement. Voici sur quoi on tombe :
:00538FE4 8B45EC mov eax, dword ptr [ebp-14] > Nom utilisateur
:00538FE7 E884B0ECFF call 00404070 > Calcul longueur nom utilisateur
:00538FEC 83F808 cmp eax, 00000008 > longueur=8 ?
:00538FEF 7D1A jge 0053900B > Si < 8 pas bon sinon calcul le code
:00538FF1 6A00 push 00000000
:00538FF3 668B0D74925300 mov cx, word ptr [00539274]
:00538FFA 33D2 xor edx, edx
* Possible StringData Ref from Code Obj ->"Nom d'utilisateur invalide..."
|
:00538FFC B880925300 mov eax, 00539280
:00539001 E836F4F0FF call 0044843C
:00539006 E8E52FEDFF call 0040BFF0
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00538FEF(C)
|
:0053900B C645F300 mov [ebp-0D], 00
:0053900F 8D55F4 lea edx, dword ptr [ebp-0C]
:00539012 8B45FC mov eax, dword ptr [ebp-04]
:00539015 8B80DC010000 mov eax, dword ptr [eax+000001DC]
:0053901B E860C2EEFF call 00425280
:00539020 8B45F4 mov eax, dword ptr [ebp-0C]
:00539023 E848B0ECFF call 00404070
:00539028 8BF8 mov edi, eax
:0053902A 85FF test edi, edi
:0053902C 0F8ECD000000 jle 005390FF
:00539032 BB01000000 mov ebx, 00000001
.
. > Ici on a la routine de calcul du bon sérial
.
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0053902C(C)
|
:005390FF 8D45F8 lea eax, dword ptr [ebp-08]
:00539102 8B55F4 mov edx, dword ptr [ebp-0C]
:00539105 E882ADECFF call 00403E8C
:0053910A 8D55E8 lea edx, dword ptr [ebp-18]
:0053910D 8B45FC mov eax, dword ptr [ebp-04]
:00539110 8B80E0010000 mov eax, dword ptr [eax+000001E0]
:00539116 E82916F1FF call 0044A744
:0053911B 8B45E8 mov eax, dword ptr [ebp-18] > Code rentré
:0053911E 8B55F8 mov edx, dword ptr [ebp-08] > Bon code
:00539121 E85AB0ECFF call 00404180 > Comparaison code rentre et bon code
:00539126 0F85E9000000 jne 00539215 > Pas bon !
:0053912C 8D55E8 lea edx, dword ptr [ebp-18]
:0053912F 8B45FC mov eax, dword ptr [ebp-04]
:00539132 8B80E0010000 mov eax, dword ptr [eax+000001E0]
:00539138 E80716F1FF call 0044A744
:0053913D 837DE800 cmp dword ptr [ebp-18], 00000000
:00539141 0F84CE000000 je 00539215
:00539147 8D55EC lea edx, dword ptr [ebp-14]
:0053914A 8B45FC mov eax, dword ptr [ebp-04]
:0053914D 8B80DC010000 mov eax, dword ptr [eax+000001DC]
:00539153 E828C1EEFF call 00425280
:00539158 837DEC00 cmp dword ptr [ebp-14], 00000000
:0053915C 0F84B3000000 je 00539215
:00539162 6A00 push 00000000
:00539164 668B0D74925300 mov cx, word ptr [00539274]
:0053916B B202 mov dl, 02
* Possible StringData Ref from Code Obj ->"Licence d'utilisation accept"
|
:0053916D B8A8925300 mov eax, 005392A8
Nul besoin d'être un génie pour s'apercevoir qu'il suffit de changer l'instruction JNE à l'adresse :00539126 par un JMP 0053916D pour passer à une version enregistrée de Web Construction Kit 3.0. Enfin, ici ce n'est pas le crack en lui-même qui nous interesse mais plutôt la façon dont on pourrait améliorer ce programme.
Idées d'amélioration...
En réfléchissant un peu (mais vraiment un tout petit peu) sur ce qui pourrait être améliorer dans ce logiciel. J'ai eu les idées suivantes :
1) Prévenir l'utilisateur qu'il faut qu'il entre un nom d'utilisateur supérieur ou égal à 8 caractères.
2) Au lieu que le logiciel affiche la fenêtre avec le message "vous avez dû vous tromper lors de la saisie du code d'enregistrement, Veuillez réessayer..." on pourrait afficher une fenêtre avec "Votre code d'enregistrement est : le_bon_code. Merci de votre confiance. Freud"
Vous pouvez laisser libre cours à votre imagination pour rajouter d'autres stuff à laquelle j'ai poa eu l'idée.
Bref, pour le point numéro 1, il va falloir : trouver la gestion des boutons pour que quand l'utilisateur clique sur le bouton "Enregistrement", une MessageBox apparaissent pour l'avertir qu'il doit rentrer un nom d'utilisateur supérieur ou égal à 8 caractères.
Pour le point numéro 2, il va juste suffir de prendre le controle au moment ou le programme affiche le message d'erreur puis de revenir dans le programme original juste apres l'affichage de la fenetre normal.
Si malgré l'avertissement, l'utilisateur rentre tout de même un nom d'utilisateur inférieur à 8 caractères alors on laisse le message originel c'est à dire : "Nom d'utilisateur Invalide".
Reverse Engineering
Pour traiter le point numéro 1, j'ai besoin de savoir ou se fait la gestion des boutons dans le programme pour pouvoir prendre la main au moment ou l'utilisateur clique sur le bouton "enregistrer" in order to display a MessageBox with the following message "You must enter a user name containing 8 at least"...oups 'tain je pète les plombs avec ces partiels vl'a qu'j'me mets à écrire en anglais. Bon autant vous le dire tout de suite, pour trouver la gestion des boutons de ce logiciel j'ai galéré un long long moment car comme vous le savez pas (encore), il est écrit en Delphi (on le voit notament lorsque qu'on ouvre le programme dans un editeur de ressource, il y a des TForm caracteristiquent de Delphi) ce qui signifie pour être plus clair que BPX MessageBoxA, BPX DialogBoxA et autres ne fonctionneront pas!! J'ai failli abandonner le reverse de ce logiciel juste pour ca...mais heureusement j'ai rencontré TeeJi par hasard sur l'IRC et je lui ai exposé mon problème. Il m'a alors répondu : "Te prends pas la tête a essayé de trouver la WindowsProc (qui gère les évenements provenants des fenêtres) et autres DispathMessageA, GetMessage, etc...Il existe un très bon décompilateur Delphi nommé DeDe (dispo sur le site Protools) qui t'indique ou sont géré les boutons dans le programme.
En effet, il m'a seulement fallu 2 secondes + (5 minutes de téléchargement de DeDe) + (45 sec. si me recuerdo bien de decompilation) pour trouver l'endroit ou le programme atterrissait après un clic sur le bouton "Enregistrer". Eh bien, il atterit à l'adresse suivante :00539714. Il reste plus qu'à prendre le contrôle des opérations à cette adresse pour afficher une belle MessageBox. Mais voyons comment fonctionne une MessageBox avant :
The MessageBox function creates, displays, and operates a message box.
The message box contains an application-defined message and title,
plus any combination of predefined icons and push buttons.
int MessageBox(
HWND hWnd, // handle of owner window
LPCTSTR lpText, // address of text in message box
LPCTSTR lpCaption, // address of title of message box
UINT uType // style of message box
);
Pour résumer, hWnd sert à affecter la MessageBox a une fenêtre existante, en général mettre ce champ à 00 convient très bien inutile d'attribuer cette MessageBox à une fenêtre en particulier.
lpText correspond à l'adresse mémoire de la chaîne de caractère qui va s'afficher dans notre MessageBox (i.e. Attention à bien rentrer un nom d'utilisateur comprenant 8 caractères au minimun).
lpCaption : adresse du titre de la MessageBox chez moi c'est "Cracked by Freud".
uType définit le type de la MessageBox. C'est à dire ces boutons, éventuellement une icône information ou avertissement des choses comme ca quoi.
On passe tous ces paramètres à la fonction MessageBoxA tout simplement avec des PUSH. Attention, toutefois, les PUSH doivent se faire dans le sens inverse par rapport à celui définit plus haut c'est à dire de la manière suivante :
PUSH uType
PUSH lpCaption
PUSH lpText
PUSH hWnd
Call user32!MessageBoxA
Maintenant que l'on sait "Comment ca marche?" va falloir trouver un endroit pour stocker tout ca. On va faire un petit tour à la fin des sections pour voir ce que l'on trouve.
Voici les sections de Web Construction Kit 3.0
Number of Objects = 0008 (dec), Imagebase = 00400000h
Object01: CODE RVA: 00001000 Offset: 00000400 Size: 00188A00 Flags: 60000020
Object02: DATA RVA: 0018A000 Offset: 00188E00 Size: 00004200 Flags: C0000040
Object03: BSS RVA: 0018F000 Offset: 0018D000 Size: 00000000 Flags: C0000000
Object04: .idata RVA: 00198000 Offset: 0018D000 Size: 00003400 Flags: C0000040
Object05: .tls RVA: 0019C000 Offset: 00190400 Size: 00000000 Flags: C0000000
Object06: .rdata RVA: 0019D000 Offset: 00190400 Size: 00000200 Flags: 50000040
Object07: .reloc RVA: 0019E000 Offset: 00190600 Size: 00018800 Flags: 50000040
Object08: .rsrc RVA: 001B7000 Offset: 001A8E00 Size: 0016AE00 Flags: 50000040
Section CODE (d'après ProcDump)
* Virtual Size : 001888DC
* Virtual Offset : 00001000
* Image Base : 00400000
Pour ma part, j'ai choisi de placer le code correspondant à l'affichage de MessageBox à la fin de la section CODE. En effet, si on regarde bien à la fin de cette section sous SoftIce par exemple c'est à dire en Image Base+RVA (Virtual Offset)+Virtual size=00400000h+00001000h+001888DCh=005898DC, on s'apercoit qu'avant le début de l'autre section, a savoir DATA, on a toute une série de 00 ce qui nous laisse de la place pour nous exprimer. J'ai choisi l'adresse :589900 qui se situe quelques bytes après l'adresse :005898DC pour laisser un peur d'air à Web Construction Kit.
Maintenant, cherchons une place à la fin de la section .idata pour écrire nos 2 chaines de caractères qui vont servir à la MessageBox (le titre de celle-ci+le texte qu'elle contient).
Section .iata (d'après ProcDump)
* Virtual Size : 0000322C
* Virtual Offset : 00198000
* Image Base : 00400000
Soit la fin de la section .idata en 00400000+322C+198000=59B22C.
J'ai choisi de les placer à l'adresse :59B22C (juste à la fin de la section quoi!!).
Prenez votre éditeur Hexa préféré (moi j'ai pris HexWorkShop mais c'est pas mon préféré), et aller à l'adresse 59B22C pour y entrer les 2 chaines de caractères. Voila ce que ca donne chez iom :
00190220 43 5F 69 6E 69 74 48 54 4D 4C 00 00 43 72 61 63 C_initHTML..Crac
00190230 6B 65 64 20 62 79 20 46 72 65 75 64 00 41 74 74 ked by Freud.Att
00190240 65 6E 74 69 6F 6E 20 61 20 62 69 65 6E 20 72 65 ention a bien re
00190250 6E 74 72 65 72 20 75 6E 20 6E 6F 6D 20 64 27 75 ntrer un nom d'u
00190260 74 69 6C 69 73 61 74 65 75 72 20 64 27 61 75 20 tilisateur d'au
00190270 6D 6F 69 6E 73 20 38 20 63 61 72 61 63 74 65 72 moins 8 caracter
00190280 65 73 20 70 6F 75 72 20 71 75 27 69 6C 20 73 6F es pour qu'il so
00190290 69 74 20 76 61 6C 69 64 65 20 21 00 00 00 00 00 it valide !.....
Eh bien, je crois que nous avons bel et bien rassemblé toutes les informations dont nous avons besoin pour faire fonctionner cette MessageBox :
* Le moment ou il faut prendre le controle (juste apres le clic), c'est à dire en :539714. A cet endroit on place un JMP 589900. Il faudra pas oublier de réécrire les instructions effacés provoqué par ce JMP dans notre routine d'affichage de la MessageBox.
* L'adresse de notre routine : :589900
* Les adresses des 2 chaines de caractères :0059B2C2 et :0059B23D
Dernière petite chose : et l'adresse de l'API MessageBox, comment on la connait?? C'est tout simple dans notre cas car WCK y fait appel donc on regarde sous Wdasm en effectuer une recherche sur MessageBoxA dans le code desassemble et on trouve :
* Reference To: user32.MessageBoxA, Ord:0000h
|
:00403C8E E889D6FFFF Call 0040131C
Voila la on a vraiment tout. Voici donc ce que ca donne une fois codé :
:539714 JMP 00589900 > Prise de controle du prog
:539719 NOP
:53971A NOP
:53971B ... > Adresse de retour de notre routine
:589900 PUSHAD > sauvegarde des registres
PUSH 00 > 00 = MB_OK
PUSH 0059B22C > @Titre
PUSH 0059B23D > @Message
PUSH 00 > Pas de fenêtre propriétaire
CALL user32!MessageBoxA
POPAD > Restitution des registres
PUSH EBP > Instructions effacées par le jump
MOV EBP,ESP
PUSH ECX
MOV ECX,[EAX+04]
JMP 0053971B > retour au programme d'origine
Nous avons traité le point 1, reste à traiter le point 2 : afficher une fenetre qui nous indique le bon code d'apres le nom d'utilisateur que l'on a entre a la place de la fenetre habituelle qui nous dit que l'on sait planter dans le code d'enregistrement.
Dans la premiere partie j'ai deja mis en lumiere l'endroit ou le programme compare les deux codes (le bon et le pas bon). Donc le saut vers l'affichage de la fenetre t'es pas un bon gars t'as rentre un mauvais code on l'a. Il suffit de detourner le programme a cet endroit. Regardez :
:0053911B 8B45E8 mov eax, dword ptr [ebp-18] > Code rentré
:0053911E 8B55F8 mov edx, dword ptr [ebp-08] > Bon code
:00539121 E85AB0ECFF call 00404180 > Comparaison code rentre et bon code
:00539126 0F85E9000000 jne 00539215 > Pas bon !
Le JNE en :00539126 on va donc le faire aller vers notre routine. J'ai choisi de placer le code de notre routine a la suite du code qu'on a rajouter pour effectuer le point numero 1. On va donc placer notre routine en :589921 si mes calculs sont bons. Au fait l'adresse du bon code on la trouve en [EBP-08].
Mais au fait que veux t-on afficher? Moi j'ai choisi d'afficher "Votre code d'enregistrement est le suivant : XXXX Merci de votre confiance. Freud".
Vous voyer peut etre qu'il va y avoir un petit probleme pour afficher cette chaine de caracteres. En effet, etant donne que le code peut avoir une longueur variable, il est hors de question de code en dur dans le programme une chaine du style "Votre code d'enregistrement est le suivant : ...des espaces pour le code... Merci de votre confiance. Freud" car on s'apercoit que si le code depasse le nombre d'espace que l'on a reserve, le Merci de votre confiance va etre emputé. Il va donc falloir faire des manipulations de chaines de caracteres en memoire c'est assez chiant mais une fois qu'on a compris le principe ca peut etre utile et en plus c'est plus sport!!
J'ai opte pour la solution suivante : coder en dur la chaine "Merci de votre confiance. Freud", puis ensuite coder en dur "Votre code d'enregistrement est le suivant : ". J'utiliserai ensuite une fonction du programme qui calcule la longueur d'une chaine de caractere, j'aurai ainsi la longueur du bon code. je deplacerai ce code juste apres "Votre code d'enregistrement est le suivant :", puis juste apres je deplacerai la chaine "Merci de votre confiance. Freud" pour la placer a la suite!! J'aurai donc au final une belle grande chaine de caracteres : "Votre code d'enregistrement est le suivant : XXXXXXXX Merci de votre confiance. Freud" qui s'adapte a n'importe quel longueur de code et qui est utilisable par une MessageBox.
Bon ben ya plus ka comme on dit...D'abord ecrire les chaines de caracteres dont on a besoin a la suite de celles qu'on a ecrit pour le traiter le point 1 (n'oubliez pas de relever les adresse de debut de ces chaines), chez moi ca donne au final :
00190220 43 5F 69 6E 69 74 48 54 4D 4C 00 00 43 72 61 63 C_initHTML..Crac
00190230 6B 65 64 20 62 79 20 46 72 65 75 64 00 41 74 74 ked by Freud.Att
00190240 65 6E 74 69 6F 6E 20 61 20 62 69 65 6E 20 72 65 ention a bien re
00190250 6E 74 72 65 72 20 38 20 63 61 72 61 63 74 65 72 ntrer 8 caracter
00190260 65 73 20 70 6F 75 72 20 61 76 6F 69 72 20 75 6E es pour avoir un
00190270 20 6E 6F 6D 20 64 27 75 74 69 6C 69 73 61 74 65 nom d'utilisate
00190280 75 72 20 76 61 6C 69 64 65 20 21 00 4D 65 72 63 ur valide !.Merc
00190290 69 20 64 65 20 76 6F 74 72 65 20 63 6F 6E 66 69 i de votre confi
001902A0 61 6E 63 65 2E 20 46 72 65 75 64 00 56 6F 74 72 ance. Freud.Votr
001902B0 65 20 63 6F 64 65 20 64 27 65 6E 72 65 67 69 73 e code d'enregis
001902C0 74 72 65 6D 65 6E 74 20 65 73 74 20 6C 65 20 73 trement est le s
001902D0 75 69 76 61 6E 74 20 3A 20 00 00 00 00 00 00 00 uivant : .......
On a tout ce qu'il nous faut. On va pouvoir code maintenant. Plutot que d'entrer dans des explications longues et ennuyeuses sur la manipulation des chaines de caracteres je vous ecrit directement le programme que j'ai fait et je le commenterai apres. Je pense que vous comprendrez mieux de cette maniere. Le voici :
@ 589921
--------
60 PUSHAD > Sauve les registres EAX,EBX, etc...
8B45F8 MOV EAX,[EBP-08] > Adresse du bon code dans EAX
E846A7E7FF CALL 404070 > Appel d'une fct qui calcule la longueur du bon code
8BC8 MOV ECX,EAX > Resultat dans ECX
8B75F8 MOV ESI,[EBP-08] > @ du bon code dans ESI
BFD9B25900 MOV EDI,0059B2D9 > @ de la fin de la chaine "Votre code est..."
F3A4 REPZ MOVSB > Transfert du bon code a la fin de la chaine "Votre code est..."
C6070D MOV BYTE PTR [EDI],0D > 0D correspond à un retour chariot
B920000000 MOV ECX,20 > Longueur de la chaine "Merci de votre..."
BE8CB25900 MOV ESI,0059B28C > @ de la chaine "Merci de votre..."
47 INC EDI > Incrementation de EDI
F3A4 REPZ MOVSB > Transfert de la chaine "Merci de votre..." juste apres le bon code
6A00 PUSH 00 > MB_OK
682CB25900 PUSH 0059B22C > @ de "Cracked by Freud"
68ACB25900 PUSH 0059B2AC > @ de "Votre code...Merci de...Freud
6A00 PUSH 00 > Pas de fenetre proprietaire
E8C379E7FF CALL User32!MessageBoxA
61 POPAD > Restauration des registres
E9CBF8FAFF JMP 0053922A > Retour au programme principal
Explication du programme ci-dessus :
PUSHAD : on sauvegarde les registres EAX,EBX pour pouvoir les restaurer à la fin de la routine histoire de ne pas pertuber le programme principale.
CALL 404070 : C'est une procédure de Web Construction Kit que j'ai repris qui calcule la taille d'une chaine de caractere. L'adresse de la chaine est passée par EAX. C'est cette procédure qui est appelée par le programme pour savoir si le nom d'utilisateur est supérieur à 8 caractères. C'est cool!! Y'a des procédures déjà faites!!!
REPZ MOVSB :
Fonctionnement de l'instruction MOVSB
L'instruction MOVESB (Move String Byte) déplace une donnée depuis l'adresse formée par DS:ESI vers l'adresse formée par ES:EDI. ESI et EDI sont ensuite incrémenté automatiquement.
Fonctionnement de l'instruction REP
REP instruction (Repeat): le processeur exécute l'instruction spécifiée, décrémente le registre ECX d'une unité et recommence cette opération tant que ECX n'est pas nul.
On transfert donc le bon code vers notre zone de données caractere par caractere.
MOV BYTE PTR [EDI],0D :
On insère un retour chariot dans notre chaine...histoire de ne pas avoir une méga longue chaine de caracteres dans notre MessageBox (pis ca fait plus jolie).
Le reste vous devriez être capable de le comprendre en regardant le programme.
Etat des lieux après mes modifications, on a une MessageBox qui indique à l'utilisateur de se méfier et de rentrer un nom d'utilisateur d'au moins 8 caractères, puis quand un nom valide est rentré, le logiciel remercie l'utilisateur et lui fournit le bon code que celui-ci n'aura plus qu'à rentrer pour avoir sa version enregistrée. Alors il est quand même beaucoup plus agréable à utiliser ce soft vous trouvez pas?
Conclusion
En conclusion, un petit poème pour ma copine :
Si tu étais un parfum, tu serais ma lessive
Rapide, tu l'est, comme le caméléon sur sa branche
Si tu étais un légume, tu serais un petit pois
Car les petits pois ils leur arrivent plein de trucs dans les poèmes
Enfin, surtout dans mes poèmes qui veulent rien dire
D'ailleurs comme d'hab, It's hard to be a pea!!
Merci à Christal, Brénuche, et TeeJi pour tout le travail qu'ils réalisent, continuez, c'est vachement intéressant.
Au passage, si vous trouvez des absurdites,des erreurs dans ce tut (ce qui est loin d'être impossible)
ou que vous avez une remarque a faire, n'hesitez surtout pas a prendre contact avec moi
(French_Freud@Hotmail.com).