Vous pouvez recuperer le programme crackme a ette adresse : http://www.lse.epita.fr/secu/tools/crackme
Afin que vous ayez tous les memes bases, nous allons detailler la premiere partie de cet exercice qui consistait a afficher avec gdb le serial qui correspond au nom entre.
En desassemblant le main on peut apercevoir :
0x0804862f <main+152>: call 0x80484b7 <compute_serial>
0x08048634 <main+157>: lea 0xffffffc8(%ebp),%eax
0x08048637 <main+160>: mov %eax,0x4(%esp)
0x0804863b <main+164>: mov 0xc(%ebp),%eax
0x0804863e <main+167>: add $0x8,%eax
0x08048641 <main+170>: mov (%eax),%eax
0x08048643 <main+172>: mov %eax,(%esp)
0x08048646 <main+175>: call 0x8048414 <my_streq>
0x0804864b <main+180>: test %eax,%eax
0x0804864d <main+182>: je 0x804869b <main+260>
La fonction "compute_serial" est appelle, puis my_streq. Si my_streq retourme 0, on saute a main+260. Dans la suite on affiche les messages.
Pour voir le serial qui correspond au nom que l'on a entre, la fonction my_streq est un bon depart (si c'etait celle de la libc vous auriez surement ld_preloade cette fonction...). Posons donc un break sur celle-ci. Une fois le breakpoint atteint, en affichant eip on se rend compte que l'on est a <my_streq+6>. Un petit disass de my_streq nous donne :
0x08048414 <my_streq+0>: push %ebp
0x08048415 <my_streq+1>: mov %esp,%ebp
0x08048417 <my_streq+3>: sub $0x8,%esp
0x0804841a <my_streq+6>: nop
0x0804841b <my_streq+7>: cmpl $0x0,0x8(%ebp)
0x0804841f <my_streq+11>: je 0x804845b <my_streq+71>
0x08048421 <my_streq+13>: cmpl $0x0,0xc(%ebp)
0x08048425 <my_streq+17>: je 0x804845b <my_streq+71>
0x08048427 <my_streq+19>: mov 0x8(%ebp),%eax
0x0804842a <my_streq+22>: cmpb $0x0,(%eax)
0x0804842d <my_streq+25>: je 0x804845b <my_streq+71>
0x0804842f <my_streq+27>: mov 0xc(%ebp),%eax
0x08048432 <my_streq+30>: cmpb $0x0,(%eax)
0x08048435 <my_streq+33>: jne 0x8048439 <my_streq+37>
Les deux premiers 'je' testent la nullitude des pointeurs, ce qui vous donne quelques indications sur la localisation des parametres :
(gdb) p $ebp+8
$2 = (void *) 0xbffba210
(gdb) p (char *) *0xbffba210
$3 = 0xbffba487 "lol"
(gdb) p $ebp+0xc
$4 = (void *) 0xbffba214
(gdb) p (char *) *0xbffba214
$5 = 0xbffba260 "96tc2TavASj68SkMXIaU.9"
Puis en testant :
$ ./crackme steck 96tc2TavASj68SkMXIaU.9
Serial correct :)
Cet exercice est note sur 2 points. Vous devrez tout d'abord reflechir a la facon dont vous pouvez modifier pour qu'il accepte n'importe quel serial. Il existe beaucoup de facons (rappel : x1/x main+182 pour voir le code hexa, set *0x804864d 0x42424242 pour tester une modification dans la memoire, x/10x main+182 pour localiser cette instruction dans le binaire), dont une tres facile (http://www.itis.mn.it/linux/quarta/x86/mov.htm), une differente (0x74 = je, 0x75 = jne), une assez bourin (0x90 = nop, http://www.itis.mn.it/linux/quarta/x86/jmp.htm)... Vous devrez ecrire un petit programme C de quelques lignes qui patchera ce programme. Enfin vous devrez modifier le crackme afin qu'il affiche (a la fin d'autres messages si vous voulez) le serial qui correspond au nom rentre en premier parametre.
Vous devrez rendre dans votre tarball de rendu le fichier crack.c qui contient la source de votre programme qui patche le crackme, avec quelques mots en commentaire pour expliquer ce que vous changez, et un fichier keygen.txt expliquant brievement la methode pour transformer le crackme en keygen (ce qu'il faut changer, a quelle adresse et en quoi, et l'effet produit).