Linux reversing ?
Source originale : http://repository.hwc-crew.com//Docs/Sec...y_fr0g.txt
(J'ai retiré les accents pour éviter les problèmes d'encodage sur le repo)
[COLOR="Orange"]################################
# Author : fr0g (hwc-crew.com)
# Mail : fr0g@hwc-crew.com OR fr0g.security@gmail.com
# Website : http://hwc-crew.com
#
# Special Thank'x :
#
# - int_0x80 (big-daddy.fr)
# - eko
################################[/COLOR]
Introduction au réversing sous GNU/Linux x86
Avant toute chose, je tiens à préciser qu'il est préférable
d'avoir quelques connaissances en langage assembleur afin de comprendre ce paper, (et de connaitre
correctement le fonctionnement de Linux)
[SIZE="3"]# 1/ Les outils Nécessaires[/SIZE]
Pour vous expliquer le but de cet article, je le rédige dans le but
de familiariser un peu les débutants en R-E sur Linux, avec les outils
gratuits les plus courants sur notre cher système open source
(ayant moi-même eut des difficultés quand je me suis retrouve avec
les outils de Linux entre les mains, alors que j'avais l'habitude de OllyDbg sous Windows.)
Les outils que nous allons utiliser ici sont :
- GDB (désassembleur/débugger pour Linux)
- KhexEdit (éditeur hexadécimal pour interface KDE, il en existe évidemment d'autres
comme Ghexedit (sous Gnome))
[size="3"]2# / Le désassemblage[/size]
Bon commençons, pour la démonstration j'ai utilise un crack-me du site
root-me.org (le code obtenu ne sera pas celui qui valide la vrai épreuve,
afin de ne pas spolier leur travail)
Afin de désassembler notre programme (appelé ch1.bin), on lance le terminal, accédez au dossier contenant ch1.bin via la commande "cd" :
Ensuite, lancez GDB avec en paramètre le nom du fichier a désassembler:
A partir de la, ch1.bin est ouvert par GDB, il vous suffit maintenant de
désassembler le programme à partir de son point d'entrée (appelé "main" par défaut):
A partir de la ligne 0x08048700, on voit que le code teste si EAX = 0 (test %eax,%eax), et fais un
saut inconditionnel (JNE (JUMP if NOT EQUAL)) après.
Plaçons un BreakPoint sur l'instruction call 0x80484d8, grâce à la commande :
on lance ensuite notre programme en tapant "run" :
On entre un passe bidon (dans mon cas "AAAAAA"), le programme va évidemment nous dire que le password est invalide ^^ (sinon c'est pas drôle) mais avant cela, il va faire une pause sur le BreakPoint :
Maintenant, jetons un oeil au registre $eax (qui a été manipule dans les précédentes instructions) :
Bof, un résultat qui à première vue ne nous dit pas grand chose, cependant, si on affiche le contenu de eax sous forme de chaine de caractères, on obtiens cela :
Le code que nous avons entré, c'est bien, mais cela ne nous avance pas beaucoup ^^. penchons nous donc sur l'instruction suivante dans le code qui était :
Plaçons un BreakPoint dessus, comme tout à l'heure :
Puis, on va dire au programme de continuer jusqu'au prochain breakpoint :
Bon revenons à l'instruction JNE, comme je l'ai explique plus haut (et si vous connaissez un peu l'ASM, vous devez le savoir) il s'agit d'un saut "si les valeurs comparées ne sont pas égales), on voit donc que le programme va sauter à la ligne 0x804871e si les valeurs comparées sont inégales.
Nous allons donc modifier cette instruction, on va demander à GDB de nous renvoyer la valeur hexadécimale de l'instruction JNE en question, puis, appuyez plusieurs fois sur Entrée pour obtenir les valeurs hexadécimales suivantes:
le 0x75 (75 hexa) correspond a l'instruction JNE "brute", les valeurs suivantes (soit : 0x15, 0x8b, 0x45) correspondent aux valeurs suivantes du code.
NOTE : Il est important de savoir que si on demande à gdb de nous renvoyer la valeur hexa de la ligne de code ou est le JNE en question, celui ci nous renverra :
L'ordre des valeurs est inversé ?
Explication de la part de teach
Notez donc la valeur "75158b75" dans par exemple un fichier texte (ou dans votre tête :p ), nous allons maintenant modifier notre programme via KhexEdit, pour cela, lancez KhexEdit dans un second terminal avec en paramètre le nom du programme (ch1.bin)
[size="3"]# 3/ L'édition en hexadécimal[/size]
KhexEdit s'ouvre et nous affiche le code du programme (en hexadécimal), de tête ce n'est pas vraiment compréhensible, mais nous savons déjà ce que nous cherchons la séquence hexadécimale : 75158b45
Il suffit alors de chercher cette séquence en la tapant dans la barre de recherche de KhexEdit (ou en faisant CTRL+F)
Boom, le programme la trouve (et il n'y en a qu'une, on a de la chance )
NOTE : Pourquoi n'ai je pas simplement tape 75 (pour JNE) ?
Car le 75 peut apparaitre plusieurs fois dans un programme (c'est d'ailleurs souvent le cas) mais une séquence contenant 75****** apparait plus difficilement plusieurs fois dans le même fichier)
On va donc remplacer le 75 par un 74 (74 = JE (Jump if Equal)), soit remplacer la chaine recherchée : 75158b45 par 74158b45 .
On enregistre le code (fermez GDB sinon vous n'aurez pas la permission de modifier le programme)
On relance notre programme dans la console :
(en réalité une fois cracké, le programme nous donne le code qui valide l'épreuve, je ne l'ai pas affiche ici)
NOTE : Étant donne que l'on a remplacé JNE par un JE via l'éditeur hexadécimal, si l'on entre le vrai password dans le programme, celui ci nous renverra le message d'erreur, pour éviter cela, on peut remplacer le 75 (JNE) par un 90 (NOP) qui n'exécute aucune instruction)
Voila, j'espère que ce tuto vous aura un peu aide à comprendre les fonctionnements et commandes les plus pratiques de GDB sous Linux.
Pour finir, je partage ce petit lien de l'ami Xylitol sur le même sujet > http://xylitol.free.fr/Home/craxoring/In...ylitol.rar
cordialement, fr0g.
(J'ai retiré les accents pour éviter les problèmes d'encodage sur le repo)
[COLOR="Orange"]################################
# Author : fr0g (hwc-crew.com)
# Mail : fr0g@hwc-crew.com OR fr0g.security@gmail.com
# Website : http://hwc-crew.com
#
# Special Thank'x :
#
# - int_0x80 (big-daddy.fr)
# - eko
################################[/COLOR]
Introduction au réversing sous GNU/Linux x86
Avant toute chose, je tiens à préciser qu'il est préférable
d'avoir quelques connaissances en langage assembleur afin de comprendre ce paper, (et de connaitre
correctement le fonctionnement de Linux)
[SIZE="3"]# 1/ Les outils Nécessaires[/SIZE]
Pour vous expliquer le but de cet article, je le rédige dans le but
de familiariser un peu les débutants en R-E sur Linux, avec les outils
gratuits les plus courants sur notre cher système open source
(ayant moi-même eut des difficultés quand je me suis retrouve avec
les outils de Linux entre les mains, alors que j'avais l'habitude de OllyDbg sous Windows.)
Les outils que nous allons utiliser ici sont :
- GDB (désassembleur/débugger pour Linux)
- KhexEdit (éditeur hexadécimal pour interface KDE, il en existe évidemment d'autres
comme Ghexedit (sous Gnome))
[size="3"]2# / Le désassemblage[/size]
Bon commençons, pour la démonstration j'ai utilise un crack-me du site
root-me.org (le code obtenu ne sera pas celui qui valide la vrai épreuve,
afin de ne pas spolier leur travail)
Afin de désassembler notre programme (appelé ch1.bin), on lance le terminal, accédez au dossier contenant ch1.bin via la commande "cd" :
Code :
fr0g@XUB:~$ cd Desktop
fr0g@XUB:~/Desktop$
Ensuite, lancez GDB avec en paramètre le nom du fichier a désassembler:
Code :
fr0g@XUB:~/Desktop$ gdb ch1.bin
GNU gdb 6.6-debian
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 "i486-linux-gnu"...
(no debugging symbols found)
Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
(gdb)
A partir de la, ch1.bin est ouvert par GDB, il vous suffit maintenant de
désassembler le programme à partir de son point d'entrée (appelé "main" par défaut):
Code :
(gdb) disass main
Dump of assembler code for function main:
0x0804869d <main+0>: lea 0x4(%esp),%ecx
0x080486a1 <main+4>: and $0xfffffff0,%esp
0x080486a4 <main+7>: pushl 0xfffffffc(%ecx)
0x080486a7 <main+10>: push %ebp
0x080486a8 <main+11>: mov %esp,%ebp
0x080486aa <main+13>: push %ecx
0x080486ab <main+14>: sub $0x24,%esp
0x080486ae <main+17>: movl $0x8048841,0xfffffff8(%ebp)
0x080486b5 <main+24>: movl $0x804884c,(%esp)
0x080486bc <main+31>: call 0x80484c8 <puts@plt>
0x080486c1 <main+36>: movl $0x804888c,(%esp)
0x080486c8 <main+43>: call 0x80484c8 <puts@plt>
0x080486cd <main+48>: movl $0x80488cc,(%esp)
0x080486d4 <main+55>: call 0x80484c8 <puts@plt>
0x080486d9 <main+60>: movl $0x804890c,(%esp)
0x080486e0 <main+67>: call 0x8048498 <printf@plt>
0x080486e5 <main+72>: mov 0xfffffff4(%ebp),%eax
0x080486e8 <main+75>: mov %eax,(%esp)
0x080486eb <main+78>: call 0x80485fe <getString>
0x080486f0 <main+83>: mov %eax,0xfffffff4(%ebp)
0x080486f3 <main+86>: mov 0xfffffff8(%ebp),%eax
0x080486f6 <main+89>: mov %eax,0x4(%esp)
0x080486fa <main+93>: mov 0xfffffff4(%ebp),%eax
0x080486fd <main+96>: mov %eax,(%esp)
0x08048700 <main+99>: call 0x80484d8 <strcmp@plt>
0x08048705 <main+104>: test %eax,%eax
0x08048707 <main+106>: jne 0x804871e <main+129>
0x08048709 <main+108>: mov 0xfffffff8(%ebp),%eax
0x0804870c <main+111>: mov %eax,0x4(%esp)
0x08048710 <main+115>: movl $0x8048930,(%esp)
0x08048717 <main+122>: call 0x8048498 <printf@plt>
0x0804871c <main+127>: jmp 0x804872a <main+141>
0x0804871e <main+129>: movl $0x8048970,(%esp)
0x08048725 <main+136>: call 0x80484c8 <puts@plt>
0x0804872a <main+141>: mov $0x0,%eax
0x0804872f <main+146>: add $0x24,%esp
0x08048732 <main+149>: pop %ecx
0x08048733 <main+150>: pop %ebp
0x08048734 <main+151>: lea 0xfffffffc(%ecx),%esp
0x08048737 <main+154>: ret
End of assembler dump.
(gdb)
A partir de la ligne 0x08048700, on voit que le code teste si EAX = 0 (test %eax,%eax), et fais un
saut inconditionnel (JNE (JUMP if NOT EQUAL)) après.
Code :
0x08048700 <main+99>: call 0x80484d8 <strcmp@plt>
0x08048705 <main+104>: test %eax,%eax
0x08048707 <main+106>: jne 0x804871e <main+129>
Plaçons un BreakPoint sur l'instruction call 0x80484d8, grâce à la commande :
Code :
(gdb) b *main+99
Breakpoint 1 at 0x8048700
on lance ensuite notre programme en tapant "run" :
Code :
(gdb) run
Starting program: /home/fr0g/Desktop/ch1.bin
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
############################################################
## Bienvenue dans ce challenge de cracking ##
############################################################
Veuillez entrer le mot de passe :
On entre un passe bidon (dans mon cas "AAAAAA"), le programme va évidemment nous dire que le password est invalide ^^ (sinon c'est pas drôle) mais avant cela, il va faire une pause sur le BreakPoint :
Code :
Veuillez entrer le mot de passe : AAAAAA
Breakpoint 1, 0x08048700 in main ()
(gdb)
Maintenant, jetons un oeil au registre $eax (qui a été manipule dans les précédentes instructions) :
Code :
(gdb) print
$1 = 134524936
(gdb)
Bof, un résultat qui à première vue ne nous dit pas grand chose, cependant, si on affiche le contenu de eax sous forme de chaine de caractères, on obtiens cela :
Code :
(gdb) x/s
0x804b008: "AAAAAA"
(gdb)
Le code que nous avons entré, c'est bien, mais cela ne nous avance pas beaucoup ^^. penchons nous donc sur l'instruction suivante dans le code qui était :
Citation :0x08048707 <main+106>: jne 0x804871e <main+129>
Plaçons un BreakPoint dessus, comme tout à l'heure :
Code :
(gdb) b *main+106
Breakpoint 2 at 0x8048707
(gdb)
Puis, on va dire au programme de continuer jusqu'au prochain breakpoint :
Code :
(gdb) c
Continuing.
Breakpoint 2, 0x08048707 in main ()
(gdb)
Bon revenons à l'instruction JNE, comme je l'ai explique plus haut (et si vous connaissez un peu l'ASM, vous devez le savoir) il s'agit d'un saut "si les valeurs comparées ne sont pas égales), on voit donc que le programme va sauter à la ligne 0x804871e si les valeurs comparées sont inégales.
Nous allons donc modifier cette instruction, on va demander à GDB de nous renvoyer la valeur hexadécimale de l'instruction JNE en question, puis, appuyez plusieurs fois sur Entrée pour obtenir les valeurs hexadécimales suivantes:
Code :
(gdb) x/b 0x08048707
0x8048707 <main+106>: 0x75
(gdb)
0x8048708 <main+107>: 0x15
(gdb)
0x8048709 <main+108>: 0x8b
(gdb)
0x804870a <main+109>: 0x45
le 0x75 (75 hexa) correspond a l'instruction JNE "brute", les valeurs suivantes (soit : 0x15, 0x8b, 0x45) correspondent aux valeurs suivantes du code.
NOTE : Il est important de savoir que si on demande à gdb de nous renvoyer la valeur hexa de la ligne de code ou est le JNE en question, celui ci nous renverra :
Code :
(gdb) x/x 0x08048707
0x8048707 <main+106>: 0x458b1575
L'ordre des valeurs est inversé ?
Explication de la part de teach
Citation :L'ordre n'est pas inversé à cause de la pile mais plutôt à cause de l'endianness des processeur intel x86 (little endian): lorsqu'un entier sur 32 bits est enregistré en mémoire, les extra-terrestres qui nous ont fait cadeau à nous humbles terriens du processeur intel ont arbitrairement choisi cette convention d'enregistrer les octets "à l'envers" (mais on me souffle discrètement que ce n'était pas si arbitraire que ça en avait l'air car la lecture du même entier se trouve optimisée si le processeur dispose de registres de tailles différentes). Dans leur ultime sagesse, les E.T ne tolèrent cependant pas que ce choix soit remis en question
Notez donc la valeur "75158b75" dans par exemple un fichier texte (ou dans votre tête :p ), nous allons maintenant modifier notre programme via KhexEdit, pour cela, lancez KhexEdit dans un second terminal avec en paramètre le nom du programme (ch1.bin)
[size="3"]# 3/ L'édition en hexadécimal[/size]
KhexEdit s'ouvre et nous affiche le code du programme (en hexadécimal), de tête ce n'est pas vraiment compréhensible, mais nous savons déjà ce que nous cherchons la séquence hexadécimale : 75158b45
Il suffit alors de chercher cette séquence en la tapant dans la barre de recherche de KhexEdit (ou en faisant CTRL+F)
Boom, le programme la trouve (et il n'y en a qu'une, on a de la chance )
NOTE : Pourquoi n'ai je pas simplement tape 75 (pour JNE) ?
Car le 75 peut apparaitre plusieurs fois dans un programme (c'est d'ailleurs souvent le cas) mais une séquence contenant 75****** apparait plus difficilement plusieurs fois dans le même fichier)
On va donc remplacer le 75 par un 74 (74 = JE (Jump if Equal)), soit remplacer la chaine recherchée : 75158b45 par 74158b45 .
On enregistre le code (fermez GDB sinon vous n'aurez pas la permission de modifier le programme)
On relance notre programme dans la console :
Code :
fr0g@XUB:~/Desktop$ ./ch1.bin
############################################################
## Bienvenue dans ce challenge de cracking ##
############################################################
Veuillez entrer le mot de passe : AAAAAA
Bien joué, vous pouvez valider l'épreuve.
(en réalité une fois cracké, le programme nous donne le code qui valide l'épreuve, je ne l'ai pas affiche ici)
NOTE : Étant donne que l'on a remplacé JNE par un JE via l'éditeur hexadécimal, si l'on entre le vrai password dans le programme, celui ci nous renverra le message d'erreur, pour éviter cela, on peut remplacer le 75 (JNE) par un 90 (NOP) qui n'exécute aucune instruction)
Voila, j'espère que ce tuto vous aura un peu aide à comprendre les fonctionnements et commandes les plus pratiques de GDB sous Linux.
Pour finir, je partage ce petit lien de l'ami Xylitol sur le même sujet > http://xylitol.free.fr/Home/craxoring/In...ylitol.rar
cordialement, fr0g.
CyberSee
Admin fondateur de N-PN Messages : 1,721 Sujets : 287 Points: 157 Inscription : Jan 2012 |
Linux reversing ?
J'ai arrangé ton BBCode ;-)
Bravo très bon tuto complet sur la question :-) +20 de REP ;-) |
teach
Newbie Messages : 8 Sujets : 1 Points: 0 Inscription : Jun 2011 |
Linux reversing ?
Citation :Afin de comprendre pourquoi l'ordre des valeurs est inversé (75 apparait en dernier), documentez vous sur les fonctionnement du processeur, et de la "PILE" (la première valeur à y entrer est la dernière a en sortir) , je n'argumenterai pas sur ce sujet ici .L'ordre n'est pas inversé à cause de la pile mais plutôt à cause de l'endianness des processeur intel x86 (little endian): lorsqu'un entier sur 32 bits est enregistré en mémoire, les extra-terrestres qui nous fait cadeau à nous humbles terriens du processeur intel ont arbitrairement choisi cette convention d'enregistrer les octets "à l'envers" (mais on me souffle discretement que ce n'était pas si arbitraire que ça en avait l'air car la lecture du meme entier se trouve optimisée si le processeur dispose de registres de tailles differentes). Dans leur ultime sagesse, les E.T ne tolèrent cependant pas que ce choix soit remis en question |
fr0g
NTEuNDI2MzcsLTEuNzc4NDg4 Messages : 348 Sujets : 22 Points: 56 Inscription : Aug 2011 |
Linux reversing ?
Merci de la précision teach
|
fr0g
NTEuNDI2MzcsLTEuNzc4NDg4 Messages : 348 Sujets : 22 Points: 56 Inscription : Aug 2011 |
Linux reversing ?
Merci teach, j'ai édité le tuto pour ajouter ton explication
|