Ce nouvel article traitera d'un sujet trés intéréssant : les bases en matiere de Reversing.
Nous verrons ici seulement le strict minimum , ce qui permettra tout de meme d'acquérir quelque notions en la matiere ,et qui pourrait ( on sais jamais ) susciter des vocations..?
Pour les besoins de cet article nous utiliseront un codes et un programmes de déboggage incontournable : GDB ( sous Linux) puis un crack-me appellé "cm"codé en C trouvé sur un célèbre site .
Le principe ne changeant pas , je n'ai pas trouvé d'intéret a en coder d'autre ( ba ouai quoi) .
Trève de bavardages place a l'article now :
Le Crack-me
1)Ici nous cherchons donc le password , bien , pour cela nous devons d'abord désassembler le "main" ( fonction pricipale du programme) afin d'y placer un "break point" ( point d'arret destiné a stopper le programme a l'endroit que l'on veut examiner , soit l'endroit ou le programme teste l'entrée utilisateur ou a la fin de celle ci selon la façon choisie) .
Commençons par lancer GDB avec "cm" puis désassemblons le "main" avec l'instruction " disas main" de Gdb.
Vous devriez avoir quelque chose comme ça :
[user@localhost asm]$ gdb cm
GNU gdb 6.6-3mdv2008.0 ( Linux release 2008.0)
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i586-mandriva-linux-gnu"...
Using host libthread_db library "/lib/i686/libthread_db.so.1".
(gdb) disas main
Dump of assembler code for function main:
0x080483a4
0x080483a8
0x080483ab
0x080483ae
0x080483af
0x080483b1
0x080483b2
0x080483b5
0x080483b8
0x080483bb
0x080483be
0x080483c0
0x080483c3
0x080483c6
0x080483c9
0x080483cb
0x080483cf
0x080483d6
0x080483db
0x080483e0
0x080483e6
0x080483e9
0x080483ec
0x080483ef
0x080483f2
0x080483f5
0x080483f7
0x080483fa
0x080483fe
0x08048401
0x08048406
0x08048408
0x0804840a
0x08048411
0x08048416
0x08048418
0x0804841f
0x08048424
0x08048426
0x0804842d
0x08048432
0x08048437
0x0804843a
0x0804843b
0x0804843c
0x0804843f
End of assembler dump.
Ok , maintenant cherchons un peu ou se trouve l'endroit qui nous intéresse ....
Ici , j'ai personnellement choisi de placé mon Break Point a la fin de la condition c'est a dire juste avante le " Mauvais mot de passe " . ( façon certe inabituelle mais efficace tout de meme ,comme vous pourrez le constatez par la suite.
Pour le break point nous choisirons donc l'adresses 0x8048419 puisque :
0x08048408
Nous en déduisons donc que Main+116 se trouve entre l'instruction "else" et "printf("Mauvais mot de passe !\n");" car on y est renvoyé si il y a une inégalité.
Choisissons donc la l'adresse 0x8048419 soit main+117 de cette maniere :
(gdb) b *main+117
Breakpoint 1 at 0x8048419: file ./cm.c, line 15 ; message indiquant la création du break point
Ok , lançons donc le crack-me ("cm") en passant 40*a en argument puis observons ce qui se passe :
(gdb) r aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Starting program: /home/kmkz/Bureau/asm/cm aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Vous avez ecrit aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Program received signal SIGILL, Illegal instruction.
main (ac=2, av=0xbf90e174) at ./cm.c:15
15 printf("Mauvais mot de passe !\n");
Bon , nous avions vu juste , l'adresse pointait bel et bien sur la fin de la condition .Afin de le vérifié , utilisons la commande "list" de Gdb pour voir exatement ou le break point stoppe le programme :
(gdb) list
10 {
11 printf("Bon mot de passe !\n");
12 }
13 else
14 {
15 printf("Mauvais mot de passe !\n");
16 }
17 }
18 else
19 {
Tout va bien , on est sur la bonne voie \o/ .
C'est bien beau , mais le pass dans tout ça ? il est ou ?
Bah pour le trouver maintenant il nous faut l'adresse du pointeur ESP afin de voir ce qui s'y trouve , pour cela commençons par trouver l'adresse de nos 40*a passé en argument puis tentons de remonter a la pile :
(gdb) print av[1] ; nos "a" étant l'argument [1]
$1 = 0xbf910255 'a'
Poursuivons par l'affichage de tout les argument passés au programme stockés dans "av" :
(gdb) print av
$2 = (char **) 0xbf90e174
Maintenant nous possédons l'adresse du tableau d'argument du programme "cm" , alons donc voir ce qu'il contient a partir de cette adresse mémoire....Bienvenu dans :"la Pile "!
Nous utilisons ici l'instruction x/16x afin d'afficher les 16*4 octets contenu dans la pile :
(gdb) x/16x 0xbf90e174
0xbf90e174: 0xbf91023c 0xbf910255 0x00000000 0xbf91027e
0xbf90e184: 0xbf910291 0xbf9102a6 0xbf9102b9 0xbf9102d0
0xbf90e194: 0xbf9102e3 0xbf9102fb 0xbf91030f 0xbf91031a
0xbf90e1a4: 0xbf91032a 0xbf910337 0xbf910388 0xbf910396
ceci dit de petites vérifications s'imposent :
(gdb) printf "%s", 0xbf91023c
/home/kmkz/Bureau/asm/cm(gdb) printf "%s", 0xbf910255 ; on obtient le chemin du programme cm
et :
(gdb) print "%s",0xbf910255
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$3 = 3213951573 ; ici c'est bien av[1] avec nos 40*a , no soucy
Il est temp pour nous de voir vers quelle adresse pointe ESP ( ESP pointe vers le sommet de la pile).
(gdb) print $esp
$4 = (void *) 0xbf90e0b0
Ici se trouve donc l'adresse du sommet de la pile allos dons y jeter un oeil ...
(gdb) x/16x $esp ; meme explications que tout a l'heure
0xbf90e0b0: 0xbf910255 0xbf90e0cc 0xbf90e0c8 0x080482bc
0xbf90e0c0: 0xbf90e0f0 0x08049640 0xbf90e0e8 0x666b646d
0xbf90e0d0: 0x0079766a 0xbf90e0f0 0xbf90e148 0xb7e93f90
0xbf90e0e0: 0xb7fe9cc0 0x08048450 0xbf90e148 0xb7e93f90
bon la on peu constater que l'on a :
l'adresse de la pile : 0xbf90e0c0
l'adresse de nos "a" (av[1]) :0xbf910255
Mais aussi une adresse que l'on avait pas encore vu jusqu'ici : 0xbf90e0cc
Testons donc 0xbf90e0cc afin de voir ce que cette adresse contient .
(gdb) printf "%s", 0xbf90e0cc
mdkfjvy(gdb)
Hey !! Mais qu'est-ce donc ..? Notre pass seait donc la ? ??
Et oui , en effet le pass est bel et bien mdkfjvy !
Voila , vous venez de voir les principes de base du Reversing , mais la route est encore longue alors courage et a bientot!