Cours n°7

Cracker un crack-me



Objectif :

Cracker un crackme (original non ? Tout comme le titre du cours d'ailleurs... Manque d'inspiration me diront certains...)


Niveau :

Débutant


Ce qu'il vous faut :

Le kit du parfait petit crackeur comme d'habitude qui comprend :

- WinDasm

- Un éditeur hexadécimal

- Le crack-me (10 Ko)

Attention la patience et la réflexion ne sont pas comprises dans ce kit, vous devrez les apporter vous-même. Bien que pour ce qui est de la réflexion je vous aiderai un peu. ;-)





C'est parti !

    Pour ce 7ème cours nous allons nous intéresser à un crack-me avec un schéma de protection un peu différent des autres mais pas trop dur non plus. Nous allons simplement le cracker pour qu'il nous dise toujours "code bon".

    Donc on lance le crack-me, on fait "Help" puis "Register", on tape son nom et un serial bidon et on clique sur Ok. Et là apparaît un vilain message : "No luck" - "No luck there, mate !". On note le message comme d'habitude et on désassemble le crack-me avec notre fameux WinDasm. Ah qu'est-ce qu'on ferait si on ne l'avait pas celui-là ? On prendrait OllyDbg oui je sais mais à l'époque y avait que WinDasm ! ;-)

    On va dans les "Strings Data References" et on trouve facilement notre message d'erreur car il n'y a pas 36 messages fort heureusement. On double-clique dessus pour arriver à l'endroit où il se trouve. On double-clique encore plusieurs fois pour voir s'il n'y en a pas plusieurs et effectivement on en voit deux. Pour savoir lequel il faut prendre on va utiliser le débuggeur de WinDasm. Donc on fait CTRL+L pour le lancer et on va poser un BreakPoint juste avant l'un des deux. On va commencer par le deuxième (pourquoi le 2ème d'abord ? aucune idée ! De toute façon il faut bien en choisir un !). On va au deuxième message d'erreur et on pose un BreakPoint (BP) sur le PUSH juste avant le message (en double-cliquant sur la ligne puis en appuyant sur F2) :
 

:004013AC 5E     pop esi
:004013AD 6A30    
push 00000030 <-- C'est ici que l'on va breaker

* Possible StringData Ref from Data Obj ->"No luck!" <-- 2ème message d'erreur
|
:004013AF 6860214000     push 00402160

* Possible StringData Ref from Data Obj ->"
No luck there, mate!"
|
:004013B4 6869214000     push 00402169
:004013B9 FF7508     push [ebp+08]

 

   Après avoir poser le BreakPoint, on clique sur "Run" ou F9. On entre un nom ("Deamon" pour moi) et un serial bidon (123456) et on fait Ok. Là le message d'erreur apparaît. Donc WinDasm n'a pas breaké, alors ce ne doit pas être le bon message. On va essayer avec le premier message qu'on avait aperçu. On enlève le BreakPoint (en étant sur la ligne du BP et en faisant F2) et on en place un sur le PUSH qui est juste avant le premier message :
 

:00401364 E8AD000000 Call 00401416
:00401369 6A30    
push 00000030 <-- C'est ici que l'on va breaker

* Possible StringData Ref from Data Obj ->"No luck!" <-- 1er message d'erreur
|
:0040136B 6860214000     push 00402160

* Possible StringData Ref from Data Obj ->"
No luck there, mate!"
|
:00401370 6869214000     push 00402169
:00401375 FF7508     push [ebp+08]
 

    Ou plus rapide on pose un BP sur les 2 et on voit où il breake.

    On revient dans le crack-me, on entre un nom et un serial, on clique sur Ok et là il break, donc c'est sur ce message qu'il faut travailler (mais vous verrez par la suite que le deuxième message n'est pas là pour rien). On quitte le débuggeur (en cliquant sur "Terminate"), on revient sur le premier message et on regarde un peu au dessus :


* Referenced by a CALL at Address: <-- Le message d'erreur est appelé par un CALL
|:00401245 <-- Adresse du CALL
|
:00401362 6A00 push 00000000

* Reference To: USER32.MessageBeep, Ord:0000h
|
:00401364 E8AD000000 Call 00401416
:00401369 6A30     push 00000030

* Possible StringData Ref from Data Obj ->"
No luck!" <-- Message d'erreur
|
:0040136B 6860214000     push 00402160

* Possible StringData Ref from Data Obj ->"
No luck there, mate!"
|
:00401370 6869214000     push 00402169
:00401375 FF7508     push [ebp+08]

* Reference To: USER32.MessageBoxA, Ord:0000h
|
:00401378 E8BD000000     Call 0040143A
:0040137D C3     ret

 

    Ici on ne voit pas de saut conditionnel mais on voit que le message d'erreur est appelé par un CALL. Donc on va à l'adresse du CALL (00401245) :

:00401240 58     pop eax
:00401241 3BC3     cmp eax, ebx
:00401243 7407     je 0040124C
:00401245 E818010000   
 call 00401362 <-- Va au message d'erreur
:0040124A EB9A     jmp 004011E6 <-- Saute au-dessus
 

    Donc là on va nopper le CALL et on verra bien si le JMP nous envoie sur le bon message. On ouvre le crack-me avec un éditeur hexadécimal et on remplace E818010000 par 9090909090. On enregistre sous un autre nom par garder l'original et on le lance. Mais là ça ne marche pas. Donc on regarde où on va si on noppe également le JMP. En dessous du JMP il y a :

:0040124A EB9A     jmp 004011E6
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401243(C)
|
:0040124C E8FC000000   
 call 0040134D <-- Va sur le bon message


    Il faut alors nopper également le JMP en remplaçant le EB9A par 9090. Et là ça marche ! Mais cette méthode n'est pas très fine. En effet il y a mieux à faire en changeant un seul octet (un octet est, je le rappelle, composé de deux chiffres hexadécimaux, par exemple 74 ou E8 est un octet). Reprenons la partie où se situe le CALL du mauvais message :

:00401240 58     pop eax
:00401241 3BC3     cmp eax, ebx
<-- Compare eax et ebx (donc sûrement notre serial et le bon)
:00401243 7407     je 0040124C <-- Saute si égal sur le CALL du bon message
:00401245 E818010000     call 00401362 <-- Va au message d'erreur
:0040124A EB9A     jmp 004011E6

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401243(C)
|
:
0040124C E8FC000000     call 0040134D <-- Va sur le bon message


    Il suffit donc de mettre un JMP (EB) à la place du JE (74) pour qu'il saute toujours sur le CALL qui envoie sur le bon message. Donc on remplace 7407 par EB07. On teste et c'est bon.


    Voilà donc ce crack-me est cracké, mais on va s'amuser à faire autre chose. Quand vous lancez le crack-me cracké et que vous mettez un nombre à la place du nom là il affiche le message d'erreur puis le bon message. Vous vous souvenez du deuxième message d'erreur ? Et bien c'est à cause de celui là qu'il s'affiche (vous pouvez utiliser le débuggeur comme on a fait auparavant pour savoir quel message apparaît, mais en mettant bien sûr un numéro au lieu du nom).


* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:
0040138B(C)
|
:004013AC 5E     pop esi
:004013AD 6A30     push 00000030

* Possible StringData Ref from Data Obj ->"
No luck!"
|
:004013AF 6860214000     push 00402160

* Possible StringData Ref from Data Obj ->"
No luck there, mate!"
|
:004013B4 6869214000     push 00402169
:004013B9 FF7508     push [ebp+08]


    Comme vous pouvez le constater, le mauvais message n'est pas appelé au téléphone (oui je sais c'est nul) mais par un saut conditionnel. Allons donc voir en 0040138B :


:00401389 3C41     cmp al, 41
:
0040138B 721F     jb 004013AC <-- Saute juste avant le mauvais message
:0040138D 3C5A     cmp al, 5A


    Donc là c'est pas trop compliqué on remplace juste le 721F par 9090 pour le nopper. Et voilà. Vous pouvez maintenant vous enregistrer si par exemple vous êtes 007 ou K2000.


    Et voilà un autre crack-me qui ne nous a pas trop résisté. J'espère que vous avez tout compris (sinon il faut relire le cours) et à un prochain cours.




Passer au cours suivant >>>
[ Teleport Pro 1.29 ]