Cours n°10 : Cracker un crackme et trouver le serial

 

    Objectif : 

        1°)  Faire un peu tout et n'importe quoi du moment qu'on arrive à avoir le bon message et le bon serial. ;-)

    Niveau :

        - J'en sais rien ! Ca dépend de vous. ;-) Mais plus compliqué que les précédents.

    Ce qu'il vous faut :

        - WinDasm (Voir page "Outils")

        - Un éditeur hexadécimal comme HexDecCharEditor (Idem)

        - Le crack-me (8 Ko)

 

    Aller on y va !

        Je sais pas trop par quoi commencer mais enfin bon, on y va quand même ! Alors déjà après l'avoir télécharger, curieux comme vous êtes, vous avez dû lancer ce petit crackme. Et vous avez dû voir qu'il n'y a pas de case pour le nom !! Donc soit le serial est unique, soit il est calculé avec par exemple le numéro du disque dur ou soit avec l'âge de votre belle-mère. A première vue ça m'a l'air d'être un serial unique.

        Ni une, ni deux, on ouvre WinDasm et on désassemble ce crackme. On recherche dans les Data Strings Reference le vilain message d'erreur : "Bzzz, Essaye encore!!". Et on arrive sur ce message :

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00401429(C), :00401436(C), :0040143F(C), :00401448(C)
--> pour ceux qui n'auraient par encore compris  le (C) veut dire saut Conditionnel et le (U) saut inconditionnel
|
:00401465 FC cld

* Possible StringData Ref from Data Obj ->"Bzzz, Essaye encore!!"
|
:00401466 6838314000 push 00403138
:0040146B FF3599314000 push dword ptr [00403199]
 

        Ce message est donc appelé par 4 sauts conditionnels. Ce qui est bien c'est qui sont tous rassemblés un peu plus haut.

:00401418 E88B000000 Call 004014A8
:0040141D A37D314000 mov dword ptr [0040317D], eax
:00401422 833D7D31400003 cmp dword ptr [0040317D], 00000003
:00401429 753A jne 00401465
:0040142B BBF0314000 mov ebx, 004031F0
:00401430 0FBE03 movsx eax, byte ptr [ebx]
:00401433 83F84D cmp eax, 0000004D
:00401436 752D jne 00401465
:00401438 43 inc ebx
:00401439 0FBE03 movsx eax, byte ptr [ebx]
:0040143C 83F84F cmp eax, 0000004F
:0040143F 7524 jne 00401465
:00401441 43 inc ebx
:00401442 0FBE03 movsx eax, byte ptr [ebx]
:00401445 83F849 cmp eax, 00000049
:00401448 751B jne 00401465
:0040144A EB00 jmp 0040144C

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040144A(U)
|
:0040144C FC cld

* Possible StringData Ref from Data Obj ->"Arf C'est le bon Code!!"
|
        Donc ces 4 sauts nous amenant sur le message d'erreur il faut les remplacer. Des NOP partout doivent très bien marcher (bonjour l'élégance du crack me direz-vous) ! Mais au moins ça a le mérite de marcher ! ;-)

 

    Analyse du code à l'aide du débuggeur

        Afin de trouver le bon code on va donc utiliser le débuggeur de WinDasm. Donc CTRL+L ou Debug --> Load Process et là le débuggeur s'ouvre. Il faudrait poser un BP (Break Point) avant ces 4 sauts. Donc on mets un BP avant l'arrivée du premier saut qui nous amène sur le message d'erreur. Comme le CALL n'est pas intéressant on va poser le BP sur la ligne d'après.

:00401418 E88B000000 Call 004014A8
:0040141D A37D314000 mov dword ptr [0040317D], eax
--> Break Point sur cette ligne
:00401422 833D7D31400003 cmp dword ptr [0040317D], 00000003
:00401429 753A jne 00401465

        Inutile de cocher les 5 cases de la fenêtre de droite, car là on en aura pas besoin. On fait Run (F9) et on tape un code bidon : 123456. On valide et là il break. Là il va falloir s'occuper de la fenêtre de gauche. Mais tout d'abord on analyse un peu le code.

        Je ferais, dans un prochain cours, un cours sur l'assembleur pour que vous ayez quelques bases car cela vous servira plus d'une fois.

:0040141D A37D314000 mov dword ptr [0040317D], eax --> Vous êtes ici ! :-) La valeur de eax va dans dword ptr [0040317D]
:00401422 833D7D31400003 cmp dword ptr [0040317D], 00000003
--> la valeur de dword ptr [0040317D] (donc eax) est comparé à 3 (3 en hexa = 3 en decimal) 

        On va donc regarder ce qu'il y a dans EAX pour voir ce qu'il compare à 3, car si EAX n'est pas égal à 3 (JNE) il saute vers le mauvais message. Pour cela il faut regarder dans le cadre "regs" en haut à gauche de la fenêtre de gauche. On voit EAX = 00000006. Notre code était 123456 donc la valeur de EAX doit être le nombre de lettres. On peut essayer avec d'autres serials bidons pour vérifier. Donc le vrai serial fait 3 caractères. Il faut donc recommencer le débuggage pour rentrer cette fois un serial de 3 caractères. Le BP toujours sur la ligne du "mov", on rentre cette fois 123, on valide. Et là il break. Là on va y aller en Pas à Pas (Step) dans les boutons à coté de Run. Le Step Into (F7) est le pas à pas en rentrant dans les CALL et Step Over (F8) sans rentrer dedans. Là prenez celui que vous voulez car on a pas de CALL.

        Les modifications des registres s'effectuent une fois la ligne passée. Si par exemple vous êtes sur une ligne avec 'mov eax, 6', eax sera égale à 6 seulement quand vous serez passés à la ligne suivante.

        Donc on avance pas à pas jusqu'à la ligne du premier JNE. Ayant rentré un serial de 3 chiffres, il ne devrait pas sauter. On appuie sur F7 ou F8 pour passer cette ligne : Ouf ! il ne saute pas ! Là on est sur une ligne où il y a : mov ebx, 004031F0 . Il va donc déplacer une valeur dans ebx. On passe cette ligne pour regarder ce que contient ebx. Voici un exemple avec la valeur de eax et le contenu de ecx.

        Donc il faut cliquer sur "ebx" pour voir ce qu'il y a mis. Et là on voit le code '123' que nous avons tapé. Le serial bidon est donc stocké dans ebx.

        Ensuite il y a cette ligne : movsx eax, byte ptr [ebx] qui va donc donner la valeur d' un byte (caractères) de ebx (de notre serial) à eax. En effet on voit après que eax = 31. et 31 (en hexa) représente 1 (en ascii). L'ascii c'est les caractères que nous voyons à l'écran. Pour connaître les correspondances, allez dans HexDecCharEditor et cliquer sur "characters table" qui est représenté par un rectangle jaune. Regardez à la valeur 31 hexa et vous verrez qu'il correspond à 1 en Window Char (Ascii).

        Après avoir mis le premier caractère dans eax, il le compare à 4D (hexa) : cmp eax, 0000004D. On cherche donc dans la liste des valeurs hexa 4D et on voit qu'il correspond à M. Ensuite il incrémente (augmenter de 1) ebx (inc ebx) pour passer à la lettre suivante et compare les deux lettres suivantes par 4F et 49 (O et I). Après chaque test il y a un JNE qui saute si la lettre n'est pas la même.

    Donc petit récapitulatif :


:0040141D A37D314000 mov dword ptr [0040317D], eax
--> nombre de caractères du serial bidon
:00401422 833D7D31400003 cmp dword ptr [0040317D], 00000003
--> compare ce nombre à 3
:00401429 753A jne 00401465
--> si pas égal saute vers mauvais message
:0040142B BBF0314000 mov ebx, 004031F0
--> mets notre serial bidon dans ebx
:00401430 0FBE03 movsx eax, byte ptr [ebx]
--> la valeur de eax est le premier caractère du serial bidon en hexa
:00401433 83F84D cmp eax, 0000004D
--> compare la 1ere lettre à 4D (M)
:00401436 752D jne 00401465
--> saute si pas égal
:00401438 43 inc ebx
--> ebx + 1 : caractère suivant
:00401439 0FBE03 movsx eax, byte ptr [ebx]
--> la valeur de eax est le deuxième caractère du serial bidon en hexa
:0040143C 83F84F cmp eax, 0000004F
--> compare le 2eme caractère à 4F (O)
:0040143F 7524 jne 00401465
--> saute si pas égal
:00401441 43 inc ebx
--> ebx + 1 : caractère suivant
:00401442 0FBE03 movsx eax, byte ptr [ebx]
--> la valeur de eax est le troisième caractère du serial bidon en hexa
:00401445 83F849 cmp eax, 00000049
--> compare le 3ème caractère à 49 (I)
:00401448 751B jne 00401465
--> saute si pas égal
:0040144A EB00 jmp 0040144C
--> saute vers bon message

        Le bon serial est donc MOI.

 

        Pour obtenir le bon message avec un serial faux vous pouvez aussi inverser les PUSH :

* Possible StringData Ref from Data Obj ->"Arf C'est le bon Code!!"
|
:0040144D 6820314000 push 00403120
:00401452 FF3599314000 push dword ptr [00403199]
 

* Possible StringData Ref from Data Obj ->"Bzzz, Essaye encore!!"
|
:00401466 6838314000 push 00403138
--> A remplacer par push 00403120
:0040146B FF3599314000 push dword ptr [00403199]
 

        Le push après le mauvais message devra être remplacé par celui du bon message. Donc il faut mettre push 00403120 (6820314000) à la place de push 00403138 (6838314000). Pour info : PUSH = 68, et ensuite il faut lire à l'envers 2 par 2 : 6820314000 =  push 00403120.

 

        Voilà encore un crack-me de cracké et avec la manière ! ;-)

<<< Cours précédent    Cours suivant >>>