Archives du blog

lundi 29 octobre 2012

IO level3

Je préviens, cet article est un spoiler du level3 de IO







Nous voici donc au level3, nous sommes d'ailleurs encore en présence d'un binaire livré avec ses sources.
Analysons tout ça..







Un pointeur de fonction qui prend comme adresse celle de "bad", une fonction "good" qui nous donne le shell gagnant, une copie d'argument dans un buffer, si la taille de l'argument est inférieure à 4 alors le programme "ret" (pourquoi pas...) et..On nous affiche l'adresse des deux fonctions "bad" et "good".

On remarque que la copie dans le buffer n'est pas du tout vérifiée, on peut donc conclure a une faille type buffer overflow =)

Nous pouvons en effet voir que le nombre de bytes que nous copions dans le buffer ne dépends que de la taille de l'argument. Le programme ne vérifie en aucun cas si la taille de la variable est inférieure à celle de l'espace censé le contenir. Donc, si nous envoyons plus de données qui ne peut en être stockée dans le buffer, memcpy va simplement se contenter de réécrire par dessus le reste de la mémoire et de la pile du programme jusqu'à ce que le paramètre soit entièrement copié... Donc nous pouvons nous servir de ce bug pour contrôler et réécrire la donnée contenant la valeur de "functionpointer" et ainsi lancer la fonction "good".

Tout d'abords, ouvrons GDB et récupérons l'adresse de "good"







N'oublions pas qu'on est sur une architecture linux x86 donc le format des adresses est en little endian
0x8048474 = \x74\x84\x04\x08

Continuons avec notre analyse, voici le main désassemblé : 





Lançons le programme avec un argument et examinons l'état de la pile :
























Nous remarquons donc que nos "a" rentrés en paramètres sont bien présent (0x61616161)
On peut conclure que le buffer commence en 0xbffffdc80 et en analysant le reste des données on aperçoit une valeur familière, celle de "bad" : 0x080484a4 qui commence en 0xbffffdccc ! 

Une simple soustraction nous donne la taille exacte du buffer :







Donc pour écraser totalement l'adresse de la fonction "bad" et la remplacer par "good" il nous faut un paramètre d'une taille de 76 bytes ainsi que l'adresse qu'on a récupéré un peu avant : \x74\x84\x04\x08






Notez que pour me simplifier la vie j'utilise du python ou du perl parfois afin de pas passer une éternité a écrire 76 "a" =) 

Moralité : Toujours vérifier la copie d'argument dans un buffer, cela peut mener a un joli stack-based buffer overflow comme celui-ci... (Evidemment des protections contre ce genre d'attaques existent depuis un moment.. Mais parfois cela ne suffit pas toujours...)









Un peu de lecture sur les protections utilisées de nos jours contre ces attaques :


2 commentaires: