Introduction au cracking sous Linux
Ici nous allons étudier les bases du cracking sous Linux, en essayant de casser la sécurité d'un petit logiciel que j'ai moi même codé en C pour l'occasion. Avant de commencer, je rappelle que cracker un logiciel tiers est illégal.
Maintenant, je vous invite à télécharger ce programe, intitulé crackme et dont le code source est disponible en cliquant ici. Vous pourrez compiler ce dernier avec la commande suivante :
wget www.tux-planet.fr/public/dev/c/crackme.c
gcc -Wall -o crackme crackme.c
Si on analyse le code source de crackme.c, on s'aperçoit que si on veut pouvoir rentrer dans le programme, il faut respecter la condition émise par un if, qui compare le premier argument passé en paramètre, avec le password connu du programme :
/* Si password ok, alors on passe a la suite */ if (strcmp(PASSWORD, argv[1]) == 0) {
Si on voulait faire simple, il suffirait d'inverser cette condition au niveau du code source, et de recompiler le programme pour le faire marcher avec un code erroné :
if ( !strcmp(PASSWORD, argv[1]) == 0 ) {
Mais dans un cas réel, on ne possède pas le code source du programme protégé, et le seul moyen d'y parvenir est de désassembler ce dernier afin de le cracker.
Pour cela on peut utiliser la ligne de commande suivante :
objdump -d crackme
On s'intéressera alors à la partie main, qui contient le code principal de crackme :
08048464 <main>:
Les lignes qui suivent sont divisées en plusieurs colonnes :
- La première sert à déterminer l'adresse correspondant à l'instruction.
- La seconde colonne est le code en hexadécimal.
- Et la troisième est le code traduit en assembleur.
Après une bonne analyse, on arrive à retrouver la fonction de comparaison qui vérifie le mot de passe et le saut conditionnel qui suit :
80484ea: 85 c0 test %eax,%eax /* Comparaison */ 80484ec: 75 53 jne 8048541 <main+0xdd> /* Saut */
En assembleur, il faut savoir que :
- je = branchement en cas d'égalité
- jne = branchement en cas de non égalité
Or nous avons un "jne" ici, pour cracker notre programme, il va simplement falloir transformer le "jne" en "je", afin d'inverser la condition du if qui vérifie le bon mot de passe. Les correspondances en hexadécimal sont les suivantes :
- je = 74
- jne = 75
Concrètement, il va falloir que l'on modifie notre programme, à l'aide d'un éditeur hexadécimal, afin de remplacer cette ligne :
75 53 jne 8048541 <main+0xdd>
Par celle-ci :
74 53 je 8048541 <main+0xdd>
Installation de l'éditeur hexadécimal ghex :
yum install ghex
Ouverture du programme avec l'éditeur :
ghex2 crackme
On va dans le menu "Edit" puis "Go Byte" et on rentre la valeur 0x004ec. Comme par hasard on se retrouve pile sur le chiffre 75 suivie de 53. Il ne nous reste donc plus qu'à changer 75 par 74 et sauvegarder le tout.
Utilisez les chiffres que l'on obtient en verrouillant la touche majuscule, plutôt que le pavé numérique pour réaliser cette action.
Pour ceux qui veulent savoir d'où sort le 0x004ec, il s'agit du virtual offset du "jne". Le virtual offset du début du segment contenant le code : 0x080484ec - 0x08048000 = 0x004ec
Il nous reste plus qu'a vérifier que cela fonctionne :
./crackme toto
Starting Root Shell ...
22 Commentaires pour "Introduction au cracking sous Linux"
Flux des commentaires de cet article Ajouter un commentaireExcellent !
Très intéressant et didactique
Merci. Je me demandais justement si ce billet était compréhensible.
Pour ma part, je le trouve compréhensible. C'est très interessent ton truc
réellement très interessant cet article.
La question qui me titille c'est de savoir s'il existe des moyens de reperer les zones de programme correspondantes à la comparaison d'une cle dans un programme plus "complexe"
Interessant ca... !
Juste une question : dans le code en C, on test une égalité, or dans le code assembleur, tu repères un jne, donc une inégalité...
C'est un lapsus ou est-ce lié à la façon dont est compilé le code C ?
Ned > En fait, c'est le test qui est fait :
Si "égal" alors faire quelque chose.
En assembleur c'est compilé de façon :
Si pas égal alors saute plus loin.
Le fait de sauter permet de ne pas faire un bout de code si il n'y a pas l'égalité.
De toute façon, on ne sait jamais ce que l'on cherche quand on cracke un programme. Si on avait le source, y a qu'à recompiler les modifs et changer le test d'égalité.
@Cricri : merci pout ton expliquation.
Trankil ton truc. merci il est très interressant et bien didactique
En réponse à miura, dans un programme plus "complexe", lors de la phase de désassemblage, on cherche les chaînes de charactère qui sont souvent retrouvées à l'identique.
Donc si le soft te demande "Login SVP:" dans le logiciel de désassemblage, on cherche cette même chaîne et ainsi on cible un peu pour rechercher le bon saut conditionnel.
J'avais aussi écrit un article qui vaut ce qu'il vaut sur le reverse engineering. Pas sous linux mais le principe global reste le même.
http://www.supinfo-projects.com/en/2005/reverse_engineering/
Bon pour ce soir apparemment le site est down...
En tout cas c'est très interressant, tres fort.
Mais ce que je veux c'est pouvoir le faire sous windows,
comment pourrais je reconnaitre le fichier qui contient le code source de comparaison.
@gaye : regarde bien le titre de cet article, il est dédié à la plateforme Linux et non Windows. Je t'encourage donc à rechercher d'autres sites qui traitent de ce même sujet, mais pour Windows.
Salutation.
Je trouve que l'article n'est pas assez 'développer', vous faite que 'patché' dans la démonstration, c'est dommage cela été plus enrichissant de parler comment 'phishé' le serial avec objdump.
Pour info il existe aussi GDB c'est un autre debugger en ligne de commande (GNU Debugger) il y a même une version en gui appelez : EDB
Enfin je ne vais pas trop m'avancer la dedans, car je fais que commencé dans le reverse engineering sous Linux et je ne pense pas allez plus loin que les bases qui me suffise largement. Sur ce, bonne continuation pour vos futurs articles.
__
/Xylitol
merci pour ton explication,mais je crois qu'il y a une petite erreur ici
./crackme toto
Starting Root Shell ...
Or le mot de passe dans le fichier crackme.c est " tux"
@TNHax0r : tu as mal compris. Au moment ou on lance ./crackme toto, le progamme a déjà été cracké, donc normal que ça fonctionne.
Petite question concernant le calcul du virtual offset du jne quand tu dis :
0x080484ec - 0×08048000 = 0x004ec
le 0x080484ec je comprend bien comment l'obtenir mais c'est le 0×08048000 d'ou es ce qu'il sort ?
merci pour vos réponses
Bonjour, donc après la lecture de ce tuto, qui me semble le meilleur du net, je tiens a dire que j'ai quand même un problème car quand je l'ouvre avec objdump je ne trouve pas le fameux 80484ec et donc par conséquent je ne peut pas continuer. Merci de m'aider =)
Salut,
Ca aurait été plus judicieux de proposer un NOP (90) plutôt qu'un JE (74). Car si on tappe le bon mot de passe (tux), le programme va nous envoyer bouler. Alors qu'avec un NOP, le programme ne fera aucun test et la condition sera validée quoi qu'il arrive.
J'ai du cherché la ligne manuellement car "0x004ec" m'emener vers une autre ligne mais merci pour ton tuto très compréhensible <3
vous pouvez aussi utiliser Emacs en hexl-mode
Salut, je lis cet article très tard et je commence à peine dans le reverse-engeneering mais il me semble que le mot de passe original peut être trouvé très facilement avec cette commande (il faut modifier tous les 'crackme' pour y mettre le nom du binaire) :
strings crackme | gawk 'system("./crackme " $0) == 0 { print "Found : " $0 }' 2>&1 | grep 'Found : '