
Voici un article sur la résolution des « crackme », destiné à guider les débutants en reverse engineering (cet article est proposé sur le site Begin.re).
Yow,
Tout dâabord, les outils utilisĂ©s. Contrairement au site Begin.re, je ne vais pas utiliser IDA pro qui est payant, mais bien radar2 avec Cutter qui est lui, gratuit et https://www.begin.re/tĂ©lĂ©chargeable ici. Je ne vais pas non plus utiliser ollydbg pour lâanalyse dynamique , mais bien www.immunityinc.com. Ces deux outils installĂ©s, nous avons tout ce quâil faut. En effet, les crackme ici ne sont pas dâun niveau expert et ne sont pas non plus des malwares en puissance, donc pas besoin de VM, PE Bear, âŠ
Enfin, ici je ne vais pas traiter en dĂ©tail les mĂ©thodes ASM ou autres conventions. Cette solution est destinĂ©e aux personnes ayant commencĂ© lâapprentissage de lâASM x86 et du reverse engineering qui sont bloquĂ©es Ă la rĂ©solution des exercices de Begin.re .
Commençons :
Exer0_Password :
Une fois tĂ©lĂ©chargĂ© via le site, exĂ©cutons le programme via une invite de commande. Le programme nous demande un mot de passe. Quel est-il ? et bien câest le but de lâarticle, donc câest partis !
Ouvrons lâexĂ©cutable avec Cutter (choisissez lâanalyse automatique : aaa). Le programme Ă©tant maintenant dĂ©sassemblĂ©, cherchons la mĂ©thode « main » dans la fenĂȘtre de gauche :
Dans la fenĂȘtre du milieu se trouve le code relatif Ă cette mĂ©thode. Analysons le :
Il ne faudra pas longtemps avant de voir que le mot de passe attendu est « cr4ckm3« .
Comment le sait-on ? Regardons ce quâil ce passe dans cette mĂ©thode. A lâadresse 0x004010b6 on a un push dâune chaine de caractĂšres formant « Enter password: », rappelez-vous, lorsque lâon exĂ©cute le programme, câest cette phrase qui sâaffiche. Ensuite Ă 0x004010bb on fait un call vers une mĂ©thode de la crt windows traitant les entrĂ©s/sorties (stdio), on en dĂ©duit donc que câest a ce moment la que la chaine de caractĂšre est affichĂ©e Ă lâĂ©cran.
0x004010c7 on push un paramĂštre, encore une chaine de caractĂšres « %s » qui en langage C est utilisĂ© pour dire au programme que lâon attend un paramĂštre de type string (chaine de caractĂšre) et Ă la ligne juste aprĂšs, un autre appel de mĂ©thode Ă la lib stdio. En clair, ici on attend que lâutilisateur entre une chaine de caractĂšres (notre mot de passe).
Si lâutilisateur entre un mot, que fait-on ensuite ? Directement on passe en argument dâune autre mĂ©thode le rĂ©sultat de lâappel de la mĂ©thode prĂ©cĂ©dente, donc notre mot de passe et encore une chaine de caractĂšres « cr4ckm3 ». Et ici, ces deux argument sont envoyĂ© Ă une mĂ©thode qui porte le nom de « strcmp » (string compare). Cette mĂ©thode est une mĂ©thode utilisĂ©e en C pour comparer deux chaines de caractĂšres ensembles. Si câest deux chaines sont identiques, le rĂ©sultat est 0 (plus dâinformations ici).
Maintenant je prĂ©sume que vous commencez Ă connaĂźtre la chanson, on regarde la suite et Ă lâadresse 0x004010e8 on teste le rĂ©sultat renvoyĂ© par strcmp. Pour rappel « test » effectue un et (AND) logique. Donc ici, si, le rĂ©sultat est diffĂ©rent de zĂ©ro on passe Ă lâadresse 0x00401109 sinon on continue. Et si lâon continue, on voit que lâon affiche (push + call) une chaine de caractĂšres qui est : « Correct!\n ». On en conclu donc que notre mot de passe doit ĂȘtre Ă©gal à « cr4ckm3 ».
VoilĂ , le 1er exercice est fini. La suite ?
Exer1_GoodLuck :
Comme pour le programme précédent, téléchargeons le et exécutons le :
Il ne se passe rien, essayons avec un paramĂštre :
Toujours rien. Bien, voyons le code. Chargeons le programme avec Cutter. Voici la fonction « main » :
Que peut-on y trouver ? Et bien tout dâabord, Ă lâadresse 0x00401043 on trouve que lâon compare [arg_ch] Ă deux. Pour information [arg_ch] est lâargument de la
fonction main qui contient le nombre de paramĂštres (argc) passĂ©s au programme. Ici, on sort du main si le nombre dâarguments nâest pas deux. Le programme attend bien un argument.
Alors pourquoi lors de la seconde tentative celui-ci ne faisait rien non plus ? Voyons la suite.
De lâadresse 0x001049 Ă 0x0040104f, on appelle une mĂ©thode de nom « atoi » en lui donnant le paramĂštre de la ligne de commande. Atoi est une fonction qui permet de convertir une chaine de caractĂšres en entier (int). Et Ă lâadresse suivante, si le rĂ©sultat de la fonction nâest pas correct, on sort du programme. Dans notre cas, convertir « test » en entier renvoie dâoffice une erreur, dâoĂč le pourquoi nous sortions du programme directement. Si lâon test avec un nombre :
Tout se passe bien, sauf que ce nâest pas le nombre attendu. pour trouver le nombre attendu, il faut aller un peu plus loin dans le code, juste aprĂšs la conversion (adresses 0x0040105c Ă 0x0040105f). On met dans le registre eax le rĂ©sultat de lâexpression eax + eax x 4. Ensuite on compare la valeur de eax Ă la valeur hexadĂ©cimale 0x181a (6170 en dĂ©cimale). Ici la solution rĂ©side dans la diffĂ©rence entre lâinstruction mov et lea. Mov dĂ©place une valeur situĂ©e Ă une adresse, lea dĂ©place simplement une valeur. Ici la valeur rĂ©sultant de eax + eax x 4, soit 5 fois eax. Et si lâon regarde attentivement eax est le rĂ©sultat de la conversion en entier.
Donc pour rĂ©sumer, le nombre recherchĂ© est quelque chose x 5 qui est Ă©gale Ă 6170. Si lâon fait 6170/5 = 1234. Testons :
Exer2_Juila :
Ce crackme est un peut plus complexe, mais rien de trĂšs mĂ©chant vous allez voir. Commençons comme dâhabitude et exĂ©cutons ce programme :
Ok, encore une fois câest une application qui attend un mot de passe en paramĂštre. Regardons dans Cutter le code :
On voit quâil y a dĂ©jĂ un peu plus Ă manger que dans les programmes prĂ©cĂ©dents. Encore une fois le programme teste si lâon a bien deux arguments en paramĂštre, si oui, on va Ă lâadresse 0x00401063 sinon on affiche « please provide the password » et lâon sort.
Que ce passe-t-il Ă lâadresse 0x00401063 ? Et bien en gros il y a un appel Ă une mĂ©thode « strlen » qui prend en paramĂštre notre argument (arg_ch).
Strlen renvoie la taille dâune chaine de caractĂšres et en voyant le malloc en dessous on comprend que lâon va allouer de la mĂ©moire dâune taille Ă©quivalente Ă notre argument + 1 (add eax, 1 Ă lâadresse 0x00401080). On ajoute un car en C/C++ ce qui dĂ©finit la fin dâune chaine de caractĂšres est la valeur 0 que lâon place Ă la fin et strlen nâen tient pas compte.
On voit que le pointeur vers la mémoire allouée est placé dans une variable locale (local_4h) que pour plus de visibilité nous pouvons renommer (Shift + N). Ici je la renomme en « p_malloc » .
La suite, Ă lâadresse 0x004010b2 on appel une mĂ©thode nommĂ©e strcpy et si lâon regarde les paramĂštres, on trouve arg_ch (arg_ch + 4) qui est notre chaine de caractĂšres passĂ©e lors du lancement du programme et le pointeur p_malloc.
Strcpy copie une chaine de caractĂšres dans une autre, ici le programme copie notre chaine de caractĂšres dans lâespace mĂ©moire allouĂ© prĂ©cĂ©demment. Si cela ce passe mal, on affiche « input copying to array failed » et on appelle « free » pour libĂ©rer lâespace.
Si tout se passe correctement, on se retrouve Ă lâadresse 0x004010e9. A cet endroit sans rentrer dans les dĂ©tails on constate que lâon rentre dans une boucle qui itĂšre sur p_malloc. Boucle dans laquelle un appel Ă une fonction mystĂ©rieuse (fcn.00401160) est fait. Cette fonction prend en paramĂštre un caractĂšre de la chaine Ă lâadresse p_malloc Ă chaque tour.
AprĂšs avoir bouclĂ© sur toute la chaine, on compare celle-ci Ă la valeur « VIMwXliFiwx« . Si câest la mĂȘme chose, on affiche « brava!!! » et câest gagnĂ©, sinon on affiche « Incorrect Password ».
Ok, donc cela veut dire que la fonction fcn.00401160 applique un traitement à notre chaine de départ. Voyons le code de cette fonction :
Alors, cela donne que notre caractĂšre est testĂ© pour voir sâil est contenu entre 0x61 et 0x7a ou entre 0x41 et 0x5a. Comme nous lâindique ici Cutter, 0x61 = 97 = le code la lettre âaâ, 0x7a = 122 = âzâ, 0x41 = 65 = âAâ et 0x5a = 90 = âZâ. En rĂ©sumĂ©, on regarde si notre caractĂšre est bien une lettre. Si câest le cas on ajoute Ă la valeur numĂ©rique de notre lettre la valeur situĂ©e Ă [0x403008]. Câest ici que lâanalyse dynamique avec immunity debugger entre en jeu.
Ouvrons notre programme dans le debugger et retrouvons lâexpression de lâadresse 0x00401179.
Ajoutons maintenant un « watcher » dans la fenĂȘtre « watch expressions ». Nous allons ajouter « DS:[1103008] » pour voir la valeur qui se cache Ă cette adresse.
000000004 ! Donc cela veut dire que cette fonction ajoute 4 Ă la valeur numĂ©rique de notre caractĂšre. En cryptographie cela sâappelle un code de cĂ©sar. Donc pour trouver notre mot de passe, nous devons faire lâinverse avec VIMwXliFiwx.
Le rĂ©sultat est : « REIsTheBest » đ
Retrouvez aussi mes articles sur mon blog DCK's blog.