• STATISTIQUES
  • Il y a eu un total de 4 membres et 4921 visiteurs sur le site dans les dernières 24h pour un total de 4 925 personnes!


    2 membres se sont inscrits dans les dernières 24h!


    Membres: 2 608
    Discussions: 3 580
    Messages: 32 820
    Tutoriels: 78
    Téléchargements: 38
    Sites dans l'annuaire: 58



  • DONATION
  • Si vous avez trouvé ce site internet utile, nous vous invitons à nous faire un don du montant de votre choix via Paypal. Ce don servira à financer notre hébergement.

    MERCI!




Note de ce sujet :
  • Moyenne : 0 (0 vote(s))
  • 1
  • 2
  • 3
  • 4
  • 5
Continuer en reverse engeneering
12-09-2011, 23h53 (Modification du message : 16-09-2013, 09h01 par ark.)
Message : #1
ark Hors ligne
Psyckomodo!
*****



Messages : 1,033
Sujets : 48
Points: 317
Inscription : Sep 2011
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 ! Wink) 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 Wink

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
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 :

Code ASM :
TEST AL,AL                                
JNZ SHORT CrackKey.00401397
(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 :

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 !!
+1 (3) -1 (0) Répondre
13-09-2011, 11h56
Message : #2
CyberSee Hors ligne
Admin fondateur de N-PN
*******



Messages : 1,721
Sujets : 287
Points: 157
Inscription : Jan 2012
Continuer en reverse engeneering
Un autre super de bon tuto :-) Félicitation _Ark_! Rep + 20!
+1 (0) -1 (0) Répondre
13-09-2011, 13h13 (Modification du message : 22-10-2011, 16h41 par Di0Sasm.)
Message : #3
ark Hors ligne
Psyckomodo!
*****



Messages : 1,033
Sujets : 48
Points: 317
Inscription : Sep 2011
Continuer en reverse engeneering
Merci Smile
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
+1 (2) -1 (0) Répondre
15-09-2013, 20h16
Message : #4
Hask Hors ligne
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 Wink
+1 (0) -1 (0) Répondre
16-09-2013, 09h05
Message : #5
ark Hors ligne
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 Ark
Ah, bah passe sur IRC, il y a que ça :p
+1 (0) -1 (0) Répondre


Sujets apparemment similaires…
Sujet Auteur Réponses Affichages Dernier message
  Débuter en reverse engeneering. ark 15 1,297 22-03-2018, 03h50
Dernier message: ThomasBr
  Débuter en reverse engineering avec 0$ 0x41 9 619 14-09-2012, 19h55
Dernier message: LR-6
  Introduction au reverse engineering sous Win32 fr0g 7 1,282 11-10-2011, 11h50
Dernier message: naab

Atteindre :


Utilisateur(s) parcourant ce sujet : 1 visiteur(s)
N-PN
Accueil | Challenges | Tutoriels | Téléchargements | Forum | Retourner en haut