• STATISTIQUES
  • Il y a eu un total de 1 membres et 915 visiteurs sur le site dans les dernières 24h pour un total de 916 personnes!


    Membres: 2 097
    Discussions: 3 554
    Messages: 32 736
    Tutoriels: 78
    Téléchargements: 38
    Sites dans l'annuaire: 58


  • ANNUAIRE
  • [FR] Newbie Contest
    Crackme: 35, Cryptographie: 49, Hacking: 27, Javascript/Java: 17, Logique: 31, Programmation: 23, Stéganographie: 53
    Challenges
    [FR] Hackfest
    Le Hackfest est un évènement de sécurité et de piratage informatique au Québec reg...
    Hacking
    [EN] phrack
    Lot's of stuff !
    Hacking
    [EN] Listbrain Version 3
    Site proposant 66 challenges présentés dans une liste mélangée.
    Challenges
    [EN] w3challs
    Ce site propose différents types de défis informatiques: piratage, craquage, cryptographie, stég...
    Hacking
    [EN] Reddit
    Subreddit dédié à la sécurité informatique.
    Hacking
    [EN] This is legal
    Basic: 10, Realistic: 5, Programming: 1, Bonus: 11, SQL: 2, Encryption: 6, Application: 4, User Contributed: 3
    Challenges

  • DONATION
  • Si vous avez trouvé ce site internet utile, nous vous invitons à nous faire un don du montant de votre choix via Paypal. Ce don servira à financer notre hébergement.

    MERCI!




Linux reversing ?

Source originale : Veuillez vous enregistrer pour visualiser l'ensemble du forum en cliquant ici.

(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 : Veuillez vous enregistrer pour visualiser l'ensemble du forum en cliquant ici.
#
# 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 Tongue ), 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 Wink 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 > Veuillez vous enregistrer pour visualiser l'ensemble du forum en cliquant ici.

cordialement, fr0g.
24-08-2011, 19h45
Message : #1
CyberSee Hors ligne
Admin fondateur de N-PN
*******



Messages : 1,717
Points: 156
Inscription : Jan 2012
Linux reversing ?
J'ai arrangé ton BBCode ;-)
Bravo très bon tuto complet sur la question :-)

+20 de REP ;-)
15-10-2011, 16h57 (Ce message a été modifié le : 22-10-2011 15h43 par Di0Sasm.)
Message : #2
teach Hors ligne
Newbie
*



Messages : 8
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
15-10-2011, 18h47
Message : #3
fr0g Hors ligne
NTEuNDI2MzcsLTEuNzc4NDg4
*****



Messages : 348
Points: 56
Inscription : Aug 2011
Linux reversing ?
Merci de la précision teach Big Grin
16-10-2011, 14h02
Message : #4
fr0g Hors ligne
NTEuNDI2MzcsLTEuNzc4NDg4
*****



Messages : 348
Points: 56
Inscription : Aug 2011
Linux reversing ?
Merci teach, j'ai édité le tuto pour ajouter ton explication Wink

New Project News White Hat Hacker V2.3
Accueil | Challenges | Tutoriels | Téléchargements | Forum