Continuer en reverse engeneering
Bienvenue à tous, ce tuto est la suite de mon premier cours (ici)
Cette fois, on va apprendre a retrouver un numéro de série généré a partir d'un nom.
Pour ce faire, on va se servir des registres, visibles sur OllyDBG (si vous ne voyez pas où ils se situent, relisez le premier cours ! ) et surtout, on va faire un vrai boulot d'analyse de code, j'espère que vous êtes prêts !
Ce cours est un exemple, tout n'est pas comme ça dans la vie, ce crackme est vraiment facile comparé a ce que vous pourrez trouver plus tard si vous continuez dans cette voie. Il vous faudra souvent réfléchir a comment le programmeur a voulu sécuriser son programme... Vous rencontrerez des algorithme bien plus compliqués, avec chiffrement... Tout ça pour vous dire que ce n'est qu'avec la pratique que l'on progresse.
1) Le matos !
Bah comme pour le premier tuto, on se servira de OllyDBG.
Et comme exemple, ce crackme
Et pour faire un keygen, j'utiliserais le langage C, et donc un IDE pour ce langage, mais si vous préférez un autre langage, ne vous gênez pas
2) Here we go !
Pour commencer, on ouvre notre petit crackme pour voir de quoi il est question.
On note (ou retiens, si vous avez la flemme :p) les messages d'erreurs de ce que nous voulons modifier.
Bon, allez, on ouvre OllyDBG maintenant !
Le programme est assez court, vous n'aurez aucun mal a retrouver vos messages d'erreur préférés, mais vous pouvez tout de même faire un clic droit -> search for -> all referenced text strings.
Bon, alors on obtient ce code :
On nous demande notre nom, il est ensuite enregistré dans DWORD PTR SS:[ESP+14]
Donc, là, si vous voulez mettre un nom de moins de 2 ou plus de (0F)h soit 15 caractères, ben on va se démerder avec nos connaissances de base ! (J'en profite pour attirer votre attention sur le JA et le JBE, qui signifient respectivement "saute si inférieur ou égale" et "saute si supérieur ou égale")
Ici, plusieurs solutions, soit on nop tout (bande de barbares, je vous vois venir !) sinon, pour être un peu plus fin, on remplace le JA et le JBE par des JMP 00401397 (pour se retrouver juste après tout ce beau monde)
Ensuite, on trouve du code...
Puis on nous demande notre sérial, qui se trouve finalement enregistré dans EAX.
Puis arrive ces lignes :
On voit que en 004013F9 on retrouve le message de validation.
C'est donc cette ligne que l'ont va modifié pour bypasser le sérial... Mais, ce n'est pas le but de ce cours ! (Enfin, faites le si ça vous amuse.)
Le CMP nous donne ici une information importante, "DWORD PTR SS:[ESP+78]" -> nous indique où est stocké le véritable sérial.
Remontons un peu plus haut dans le code, nous y avons trouvé ceci :
Et bien ça mes cher amis, c'est l'algorithme qui nous génère le sérial a partir de notre nom.
Bon, analysons le !
Déjà, on peut voir qu'il est composé d'une boucle :
(00401397 étant l'adresse du début de la boucle)
En jetant un rapide coup d'œil plus haut dans le code, on peut observer cette ligne :
L'instruction MOV permet de déplacer une source vers une destination. On l'utilise comme ceci : MOV destination, source. (en assembleur, les instructions sont lues a "l'envers" c'est a dire qu'on a la destination avant la source.)
Içi, on va donc mettre la valeur 0 dans DWORD PTR SS:[ESP+7C]
Au tout début de l'algorithme, on peut voir que la valeur de DWORD PTR SS:[ESP+7C] est déplacée dans le registre EAX.
Ensuite, on récupère la première lettre (BYTE récupère un octet) du nom entré dans AL. Puis, l'instruction MOVSX va permettre au programme de changer le type de la chaine récupérer. C'est un peu compliqué, je ne le détaillerai pas ici, mais sachez juste que dans ce cas présent, on se retrouvera avec la valeur décimale du code ASCII de la lettre sélectionnée.
Ensuite, cette valeur hexa est récupérée et placée dans DWORD PTR SS:[ESP+78] grâce a l'instruction ADD (bah oui, ça ne fait qu'ajouter, additionner)
Puis, le programme incrémente DWORD PTR SS:[ESP+7C] qui est finalement passé dans EAX.
On place ensuite la lettre suivante du nom (BYTE PTR SS:[ESP+EAX+14]) dans AL.
On a ensuite un TEST. Pour que le JNZ suivant saute, il faudra que AL et la valeur 0. Or, la seule façon pour qu'il atteigne le 0, c'est d'arriver en fin de chaine, en effet, lorsque l'on enregistre une chaine, celle ci ce termine OBLIGATOIREMENT par un caractère NULL ; qui vaut 00 en hexa.
Donc, pour résumer, le programme parcours le nom entré, et additionne la valeur ASCII de chaque lettres.
On peut donc trouvé notre sérial !!
HOP HOP HOP, minute ! Je sais pas si vous avez remarqués, mais n'oublions pas cette ligne : ADD DWORD PTR SS:[ESP+78],0A410
On ajoute la valeur (0A410)h a la valeur précédemment calculée... N'oubliez pas une ligne ! C'est toujours très important ! bon, cette valeur vaut 42000 en décimal.
Le sérial sera donc composé de : Valeur ASCII de chaque lettres additionnés + 42000
Bon, ben maintenant, vous prenez une table ASCII, votre calculatrice Windows pour convertir l'hexa en décimal. Et vous trouvez le sérial pour votre nom !
Ou alors... si vous êtes flemmards, vous codez un keygen...
Allez ! Au boulot !
ça y est ?
bon, je vous passe le code de mon keygen en C... Mais j'espère bien que vous m'avez codé ça, parce que c'est pas bien compliqué ! :p
Voilà, c'est la fin de ce tuto, c'était plus une analyse de code qu'une manipulation, mais j'espère que ça vous a plut ! Sachez cependant que vous pouvez placer des breakpoint (en appuyant sur f2) sur les lignes de vos choix afin de pouvoir observer ce qu'il se passe dans les registres. Attention, une opération n'est faite qu'une fois passé a la ligne suivante.
Si vous avez des questions, des remarques, etc, faites m'en part !
Voilà maintenant, je vous conseille grandement de pratiquer, mangez du crackme !!
Cette fois, on va apprendre a retrouver un numéro de série généré a partir d'un nom.
Pour ce faire, on va se servir des registres, visibles sur OllyDBG (si vous ne voyez pas où ils se situent, relisez le premier cours ! ) et surtout, on va faire un vrai boulot d'analyse de code, j'espère que vous êtes prêts !
Ce cours est un exemple, tout n'est pas comme ça dans la vie, ce crackme est vraiment facile comparé a ce que vous pourrez trouver plus tard si vous continuez dans cette voie. Il vous faudra souvent réfléchir a comment le programmeur a voulu sécuriser son programme... Vous rencontrerez des algorithme bien plus compliqués, avec chiffrement... Tout ça pour vous dire que ce n'est qu'avec la pratique que l'on progresse.
1) Le matos !
Bah comme pour le premier tuto, on se servira de OllyDBG.
Et comme exemple, ce crackme
Et pour faire un keygen, j'utiliserais le langage C, et donc un IDE pour ce langage, mais si vous préférez un autre langage, ne vous gênez pas
2) Here we go !
Pour commencer, on ouvre notre petit crackme pour voir de quoi il est question.
On note (ou retiens, si vous avez la flemme :p) les messages d'erreurs de ce que nous voulons modifier.
Bon, allez, on ouvre OllyDBG maintenant !
Le programme est assez court, vous n'aurez aucun mal a retrouver vos messages d'erreur préférés, mais vous pouvez tout de même faire un clic droit -> search for -> all referenced text strings.
Bon, alors on obtient ce code :
Code :
00401318 /$ 55 PUSH EBP
00401319 |. 89E5 MOV EBP,ESP
0040131B |. 83E4 F0 AND ESP,FFFFFFF0
0040131E |. 83C4 80 ADD ESP,-80
00401321 |. E8 DA040000 CALL CrackKey.00401800
00401326 |. C74424 78 0000>MOV DWORD PTR SS:[ESP+78],0 ; ||||
0040132E |. C74424 7C 0000>MOV DWORD PTR SS:[ESP+7C],0 ; ||||
00401336 |. C70424 2430400>MOV DWORD PTR SS:[ESP],CrackKey.00403024 ; ||||ASCII "Entrez votre nom : "
0040133D |. E8 02070000 CALL <JMP.&msvcrt.printf> ; |||\printf
00401342 |. 8D4424 14 LEA EAX,DWORD PTR SS:[ESP+14] ; |||
00401346 |. 894424 04 MOV DWORD PTR SS:[ESP+4],EAX ; |||
0040134A |. C70424 3830400>MOV DWORD PTR SS:[ESP],CrackKey.00403038 ; |||ASCII "%s"
00401351 |. E8 F6060000 CALL <JMP.&msvcrt.scanf> ; ||\scanf
00401356 |. 8D4424 14 LEA EAX,DWORD PTR SS:[ESP+14] ; ||
0040135A |. 890424 MOV DWORD PTR SS:[ESP],EAX ; ||
0040135D |. E8 DA060000 CALL <JMP.&msvcrt.strlen> ; |\strlen
00401362 |. 83F8 02 CMP EAX,2 ; |
00401365 |. 77 11 JA SHORT CrackKey.00401378 ; |
00401367 |. C70424 3B30400>MOV DWORD PTR SS:[ESP],CrackKey.0040303B ; |ASCII "Le nom est trop court."
0040136E |. E8 E1060000 CALL <JMP.&msvcrt.puts> ; \puts
00401373 |. E9 8D000000 JMP CrackKey.00401405
00401378 |> 8D4424 14 LEA EAX,DWORD PTR SS:[ESP+14] ; ||
0040137C |. 890424 MOV DWORD PTR SS:[ESP],EAX ; ||
0040137F |. E8 B8060000 CALL <JMP.&msvcrt.strlen> ; |\strlen
00401384 |. 83F8 0F CMP EAX,0F ; |
00401387 |. 76 23 JBE SHORT CrackKey.004013AC ; |
00401389 |. C70424 5230400>MOV DWORD PTR SS:[ESP],CrackKey.00403052 ; |ASCII "Le nom est trop long."
00401390 |. E8 BF060000 CALL <JMP.&msvcrt.puts> ; \puts
00401395 |. EB 6E JMP SHORT CrackKey.00401405
00401397 |> 8B4424 7C /MOV EAX,DWORD PTR SS:[ESP+7C]
0040139B |. 8A4404 14 |MOV AL,BYTE PTR SS:[ESP+EAX+14]
0040139F |. 0FBEC0 |MOVSX EAX,AL
004013A2 |. 014424 78 |ADD DWORD PTR SS:[ESP+78],EAX
004013A6 |. FF4424 7C |INC DWORD PTR SS:[ESP+7C]
004013AA |. EB 01 |JMP SHORT CrackKey.004013AD
004013AC |> 90 NOP
004013AD |> 8B4424 7C |MOV EAX,DWORD PTR SS:[ESP+7C] ; |||
004013B1 |. 8A4404 14 |MOV AL,BYTE PTR SS:[ESP+EAX+14] ; |||
004013B5 |. 84C0 |TEST AL,AL ; |||
004013B7 |.^75 DE \JNZ SHORT CrackKey.00401397 ; |||
004013B9 |. 814424 78 10A4>ADD DWORD PTR SS:[ESP+78],0A410 ; |||
004013C1 |. C70424 6830400>MOV DWORD PTR SS:[ESP],CrackKey.00403068 ; |||ASCII "Entrez le serial correspondant : "
004013C8 |. E8 77060000 CALL <JMP.&msvcrt.printf> ; ||\printf
004013CD |. 8D4424 10 LEA EAX,DWORD PTR SS:[ESP+10] ; ||
004013D1 |. 894424 04 MOV DWORD PTR SS:[ESP+4],EAX ; ||
004013D5 |. C70424 8A30400>MOV DWORD PTR SS:[ESP],CrackKey.0040308A ; ||ASCII "%d"
004013DC |. E8 6B060000 CALL <JMP.&msvcrt.scanf> ; |\scanf
004013E1 |. 8B4424 10 MOV EAX,DWORD PTR SS:[ESP+10] ; |
004013E5 |. 394424 78 CMP DWORD PTR SS:[ESP+78],EAX ; |
004013E9 |. 74 0E JE SHORT CrackKey.004013F9 ; |
004013EB |. C70424 9030400>MOV DWORD PTR SS:[ESP],CrackKey.00403090 ; |ASCII "Non, ton serial n'est pas bon..."
004013F2 |. E8 5D060000 CALL <JMP.&msvcrt.puts> ; \puts
004013F7 |. EB 0C JMP SHORT CrackKey.00401405
004013F9 |> C70424 B430400>MOV DWORD PTR SS:[ESP],CrackKey.004030B4 ; |ASCII "Bravo, ton serial est valide !"
00401400 |. E8 4F060000 CALL <JMP.&msvcrt.puts> ; \puts
00401405 |> B8 00000000 MOV EAX,0
0040140A |. C9 LEAVE
0040140B \. C3 RETN
On nous demande notre nom, il est ensuite enregistré dans DWORD PTR SS:[ESP+14]
Donc, là, si vous voulez mettre un nom de moins de 2 ou plus de (0F)h soit 15 caractères, ben on va se démerder avec nos connaissances de base ! (J'en profite pour attirer votre attention sur le JA et le JBE, qui signifient respectivement "saute si inférieur ou égale" et "saute si supérieur ou égale")
Ici, plusieurs solutions, soit on nop tout (bande de barbares, je vous vois venir !) sinon, pour être un peu plus fin, on remplace le JA et le JBE par des JMP 00401397 (pour se retrouver juste après tout ce beau monde)
Ensuite, on trouve du code...
Puis on nous demande notre sérial, qui se trouve finalement enregistré dans EAX.
Puis arrive ces lignes :
Code ASM :
CMP DWORD PTR SS:[ESP+78],EAX
JE SHORT CrackKey.004013F9
On voit que en 004013F9 on retrouve le message de validation.
C'est donc cette ligne que l'ont va modifié pour bypasser le sérial... Mais, ce n'est pas le but de ce cours ! (Enfin, faites le si ça vous amuse.)
Le CMP nous donne ici une information importante, "DWORD PTR SS:[ESP+78]" -> nous indique où est stocké le véritable sérial.
Remontons un peu plus haut dans le code, nous y avons trouvé ceci :
Code :
00401397 |> 8B4424 7C /MOV EAX,DWORD PTR SS:[ESP+7C]
0040139B |. 8A4404 14 |MOV AL,BYTE PTR SS:[ESP+EAX+14]
0040139F |. 0FBEC0 |MOVSX EAX,AL
004013A2 |. 014424 78 |ADD DWORD PTR SS:[ESP+78],EAX
004013A6 |. FF4424 7C |INC DWORD PTR SS:[ESP+7C]
004013AA |. EB 01 |JMP SHORT CrackKey.004013AD
004013AC |> 90 NOP
004013AD |> 8B4424 7C |MOV EAX,DWORD PTR SS:[ESP+7C]
004013B1 |. 8A4404 14 |MOV AL,BYTE PTR SS:[ESP+EAX+14]
004013B5 |. 84C0 |TEST AL,AL
004013B7 |.^75 DE \JNZ SHORT CrackKey.00401397
Bon, analysons le !
Déjà, on peut voir qu'il est composé d'une boucle :
Code ASM :
TEST AL,AL
JNZ SHORT CrackKey.00401397
En jetant un rapide coup d'œil plus haut dans le code, on peut observer cette ligne :
Code ASM :
MOV DWORD PTR SS:[ESP+7C],0
L'instruction MOV permet de déplacer une source vers une destination. On l'utilise comme ceci : MOV destination, source. (en assembleur, les instructions sont lues a "l'envers" c'est a dire qu'on a la destination avant la source.)
Içi, on va donc mettre la valeur 0 dans DWORD PTR SS:[ESP+7C]
Au tout début de l'algorithme, on peut voir que la valeur de DWORD PTR SS:[ESP+7C] est déplacée dans le registre EAX.
Ensuite, on récupère la première lettre (BYTE récupère un octet) du nom entré dans AL. Puis, l'instruction MOVSX va permettre au programme de changer le type de la chaine récupérer. C'est un peu compliqué, je ne le détaillerai pas ici, mais sachez juste que dans ce cas présent, on se retrouvera avec la valeur décimale du code ASCII de la lettre sélectionnée.
Code ASM :
MOV AL,BYTE PTR SS:[ESP+EAX+14]
MOVSX EAX,AL
Ensuite, cette valeur hexa est récupérée et placée dans DWORD PTR SS:[ESP+78] grâce a l'instruction ADD (bah oui, ça ne fait qu'ajouter, additionner)
Puis, le programme incrémente DWORD PTR SS:[ESP+7C] qui est finalement passé dans EAX.
On place ensuite la lettre suivante du nom (BYTE PTR SS:[ESP+EAX+14]) dans AL.
On a ensuite un TEST. Pour que le JNZ suivant saute, il faudra que AL et la valeur 0. Or, la seule façon pour qu'il atteigne le 0, c'est d'arriver en fin de chaine, en effet, lorsque l'on enregistre une chaine, celle ci ce termine OBLIGATOIREMENT par un caractère NULL ; qui vaut 00 en hexa.
Donc, pour résumer, le programme parcours le nom entré, et additionne la valeur ASCII de chaque lettres.
On peut donc trouvé notre sérial !!
HOP HOP HOP, minute ! Je sais pas si vous avez remarqués, mais n'oublions pas cette ligne : ADD DWORD PTR SS:[ESP+78],0A410
On ajoute la valeur (0A410)h a la valeur précédemment calculée... N'oubliez pas une ligne ! C'est toujours très important ! bon, cette valeur vaut 42000 en décimal.
Le sérial sera donc composé de : Valeur ASCII de chaque lettres additionnés + 42000
Bon, ben maintenant, vous prenez une table ASCII, votre calculatrice Windows pour convertir l'hexa en décimal. Et vous trouvez le sérial pour votre nom !
Ou alors... si vous êtes flemmards, vous codez un keygen...
Allez ! Au boulot !
ça y est ?
bon, je vous passe le code de mon keygen en C... Mais j'espère bien que vous m'avez codé ça, parce que c'est pas bien compliqué ! :p
Code C :
#include <stdio.h>
#include <stdlib.h>
int main()
{
char nom[100];
int serial;
int i;
i = 0;
serial = 42000; /* Tant qu'a faire, autant le mettre depuis le début */
printf("nom : ");
scanf("%s", nom); /* On récupère le nom */
/* calcul du serial */
while (nom[i] != '\0')
{
serial = serial + (int) nom[i];
i++;
}
printf("Le serial correspondant est : %d\n", serial);
return 0;
}
Voilà, c'est la fin de ce tuto, c'était plus une analyse de code qu'une manipulation, mais j'espère que ça vous a plut ! Sachez cependant que vous pouvez placer des breakpoint (en appuyant sur f2) sur les lignes de vos choix afin de pouvoir observer ce qu'il se passe dans les registres. Attention, une opération n'est faite qu'une fois passé a la ligne suivante.
Si vous avez des questions, des remarques, etc, faites m'en part !
Voilà maintenant, je vous conseille grandement de pratiquer, mangez du crackme !!
CyberSee
Admin fondateur de N-PN Messages : 1,721 Sujets : 287 Points: 158 Inscription : Jan 2012 |
Continuer en reverse engeneering
Un autre super de bon tuto :-) Félicitation _Ark_! Rep + 20!
|
ark
Psyckomodo! Messages : 1,033 Sujets : 48 Points: 317 Inscription : Sep 2011 |
Continuer en reverse engeneering
Merci
Au fait, tu peux m'appeler Ark, les underscores je les ai mis parce qu'avant l'inscription on peut pas mettre de pseudo de 3 lettres... :p |
Hask
Newbie Messages : 9 Sujets : 3 Points: 5 Inscription : Nov 2012 |
RE: Continuer en reverse engeneering
Dans la continuité du premier, encore une fois merci pour cet excellent tuto !
J'ai décidé de me prendre au jeu à la suite de ce tuto et de coder un petit KeyGen en C# ! (Que je pratique depuis vraiment pas longtemps, soyez indulgents !). KeyGen disponible ici pour les intéressés ! En espérant te re-croiser un de ces jours Ark |
ark
Psyckomodo! Messages : 1,033 Sujets : 48 Points: 317 Inscription : Sep 2011 |
RE: Continuer en reverse engeneering
Merci Hask :)
Pas de VM windows sous la main pour test ton KeyGen, mais j'ai prévu d'en install une bientôt. Citation :En espérant te re-croiser un de ces jours ArkAh, bah passe sur IRC, il y a que ça :p |