Cours n°10

Cracker un crackme et trouver le serial



Objectif :

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


Niveau :

Je n'en sais rien ! Ça dépend de vous. ;-) Mais plus compliqué que les précédents.


Ce qu'il vous faut :

- WinDasm

- Un éditeur hexadécimal

- Le crack-me (8 Ko)





Aller on y va !

     Je ne sais pas trop par quoi commencer mais enfin bon, on y va quand même ! Alors déjà après l'avoir téléchargé, 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 ou fait attention le (C) veut dire saut Conditionnel et le (U) saut inconditionnel (Unconditional)
|
: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 ce qui évite contrairement à certains programmes de retrouver les sauts éparpillés au quatre coins du code.


: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à, tel Sésame, le débuggeur s'ouvre. Il faudrait poser un BP (Break Point) avant ces 4 sauts. Donc on met 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 n'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 ferai, 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 est copié à l'adresse 0040317D et la température extérieur est de 23.6°C ! (oups pardon !) 
:00401422 833D7D31400003     cmp dword ptr [0040317D], 00000003
--> la valeur en 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 en passant par dessus (enfin le programme rentre bien sur dedans mais vous ne le voyez pas). Là prenez celui que vous voulez car on n'a pas de CALL à traverser.

    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é à 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 copier 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 (en anglais bit=bit et byte=octet ! Ne pas confondre ! un octet correspond là à un caractère) de ebx (de notre serial) à eax. En effet on voit ensuite que eax = 31. Et 31 (en hexa bien sur) représente le caractère '1' (en ascii). L'ascii c'est le format qui regroupe les caractères que nous voyons à l'écran (lettres, chiffres, caracteres spéciaux...) mais aussi d'autres tels que le retour à ligne par exemple. Pour connaître les correspondances, allez dans HexDecCharEditor et cliquez sur "characters table" qui est représenté par un rectangle jaune. Regardez à la valeur 31 hexa et vous verrez qu'il correspond au chiffre 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, 000000
4D --> 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, 000000
4F --> 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, 000000
49 --> 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

 

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



Passer au cours suivant >>>
[ Le Crackme qui se cracke tout seul ]