lundi 7 avril 2008

Off-by-one overflow - Exemple de strncat

Comme nous l'avons vu dans un précédent article, il y a pas mal de confusions possibles avec les jeux de fonctions str*cat/str*cpy ceci provoque des buffer overflow.
Bon alors lançons nous maintenant dans un buffer overflow causer la plus part de temps par une mauvaise utilisation de strncat.

Commençons par le code d'exemple qui servira de POC ( proof of concept )
#include <stdio.h>
#include <string.h>

void disbonjour(char *str)
{
char buffer[16] = "Bonjour ";

strncat(buffer, str, sizeof(buffer)-strlen(buffer));

printf("%s", buffer);
}

int main(int argc, char *argv[])
{
disbonjour(argv[1]);

return 0;
}


Ici strncat n'est pas bien utilisé ce qui va entrainer un buffer overflow un peu spécial voyons ça d'un peu mieux.

Attention gcc rajoute des données dans la pile, je ne sais pas trop ce que c'est il y a un truc pour la gestion des exeptions enfin bref ... donc ce que je voulais dire c'est que ceci ne marche que pour les anciennes versions de gcc.

bonjour.exe azertyuiop


Et nous avons une belle exeption Access Violation à l'adresse 41414141.

En fait, ce qui ce passe ici c'est que nous avons un buffer overflow un peu particulier, le off-by-one overflow, nous ne pouvons écraser qu'un seul octet et dans le cas de strncat il ne peut s'agir que d'un '\0'.

Nous allons donc écraser le premier octet du ebp sauvegarder par un '\0' cependant comme nous sommes en litte endian nous allons en fait écraser l'octet de poids faible du ebp sauvé.

La redirection ne vient pas ici du eip sauvé ni même directement du ebp sauvé, en fait une fois de retour dans la fonction main ebp sera différent et donc toutes les données aussi y compris le eip sauvé pour retourné à la fonction qui a appelé main or ici nous aurons un eip différent et donc le prog sera rediriger.

Ici ce pose un problème car on ne peut pas vraiment savoir à l'avance sur quoi pointera le nouveau ebp, si nous avons de la chance notre nouveau ebp pointera sur un buffer et nous pourons ainsi contrôler la redirection.

Cependant si nous n'avons pas de chance, l'écart entre l'ancien et le nouveau ebp sera si petit que nous ne pourrons rien faire.

Je voulais juste vous présentez très simplement les off-by-one car c'est très sympa mais la plupart du temps nous n'arriverons pas à faire que le nouveau ebp pointe vers un buffer.