Solutions des exercices de begin.re

Solutions des exercices de begin.re

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.

 par Julien | ON3DEX

Auteur / autrice

  • Jeune programmateur, intĂ©ressĂ© par la «Libre Space Fondation» qui a comme mission, rendre l’espace accessible Ă  tous. Il a aussi un blog Ă  ce lien : https://deckbsd.wordpress.com/