Buffer overflow [Résolu]

tomk_41 2 Messages postés jeudi 16 novembre 2000Date d'inscription 31 octobre 2005 Dernière intervention - 31 oct. 2005 à 19:53 - Dernière réponse : cs_neria 320 Messages postés vendredi 21 février 2003Date d'inscription 16 février 2009 Dernière intervention
- 1 nov. 2005 à 16:17
Voila maintenant plusieurs jour que je flanche sur un problème.
Dans le cadre d'un cours de sécurité informatique, je dois réussir à faire afficher "Bienvenu sur ce systeme..." sans entrer un des nom et mots de passe du tableau users.
Quelqu'un aurait il une idée sur la chaine de caractères à rentrer pour faire un buffer overflow et choisir notre propre nom et mot de passe ?

#include <stdio.h>

char users[][2][20] =
{ { "root", "98765" },
{ "moi", "allo" },
{ "abc", "motdepasse" },
{ "", "" }
};

int check_name()
{
char user_name[20];
char password[20];
int i;

printf("Nom: "); gets(user_name);
printf("Mot de passe: "); gets(password);

for(i=0; users[i][0][0] != 0; i++)
{
if(strcmp(user_name, users[i][0]) == 0 &&
strcmp(password, users[i][1]) == 0)
return 1;
}
return 0;
}

void logon()
{
printf("Bienvenu sur ce systeme...\n");
exit(1);
}

void reject()
{
printf("Connection fermee!\n");
exit(0);
}

main()
{
unsigned int i;
for(i=(unsigned)-3; i && !check_name(); i++);
if(i>=(unsigned)-3)
logon();
else
reject();
}
Afficher la suite 

Votre réponse

5 réponses

cs_neria 320 Messages postés vendredi 21 février 2003Date d'inscription 16 février 2009 Dernière intervention - 1 nov. 2005 à 00:44
+3
Utile
Salut tom_k !


Tout d'abord je tiens à préciser que je n'ai jamais réaliser de buffer overflow donc ma méthode sera peut être mauvaise, mais j'ai quand même réussi à sauter le test et aller directement dans logon(). Il faut aussi préciser que j'ai compilé le programme avec Visual C++ 6 en le modifiant légérement (pour la fonction exit par exemple) et que les adresses ne seront pas forcement les bonnes. De plus j'ai utilisé le débogueur intégré de VC++ ce qui m'a beaucoup aidé.
Voici le code que j'ai compilé :

#include <stdio.h>
#include <string.h>


char users[][2][20] =
{ { "root", "98765" },
{ "moi", "allo" },
{ "abc", "motdepasse" },
{ "", "" }
};


int check_name()
{
char user_name[20];
char password[20];
int i;


printf("Nom: "); gets(user_name);
printf("Mot de passe: "); gets(password);

for(i=0; users[i][0][0] != 0; i++)
{
if(strcmp(user_name, users[i][0]) == 0 &&
strcmp(password, users[i][1]) == 0)
return 1;
}
return 0;
}


void logon()
{
printf("Bienvenu sur ce systeme...\n");
//exit(1);
}


void reject()
{
printf("Connection fermee!\n");
//exit(0);
}


void main()
{
unsigned int i;
for(i=(unsigned)-3; i && !check_name(); i++);


if(i>=(unsigned)-3)
logon();
else
reject();
}


En tout ça m'a prit 1h30 pour comprendre (j'ai pénétré le système à minuit pile :) ). Le principe est que lors du retour du check_name() (dans le for) il ne faut non pas aller à l'instruction suivante (pour tester si le code de retour est bon), mais aller directement à l'adresse du call logon juste après le test if. Chez moi cette adresse est 0x00401211.
Nous le savons tous, lors d'un ret, la machine dépile le contenu de l'adresse d'ESP (*ESP) dans EIP (qui pointe vers l'instruction suivante à éxécuter). Hors les variables statiques (pas static !!!) sont elles même contenue dans la pile. De plus on utilise un gets ce qui aura effet d'écrire chaque caractère tapé au clavier sur cette même pile, donc si on déborde de la taille prévue au départ on pourra écraser des valeurs de la pile dont la fameuse adresse de retour !!
Pour faire simple on va utiliser la variable user_name car c'est la plus proche du début de la pile. On lance le programme en mode pas à pas avec vue désassemblée et on tape dans Nom:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 afin de voir ce qu'on écrase et où. Pour mot de passe on tape ce qu'on veux. On remarque que avant d'éxecuter le ret, ESP pointe sur 0x0012FF2C. Un petit coup d'oeil dans la mémoire pour voir ce qui s'y trouve, et qu'est ce qu'on découvre ??? "YZab". Ce sont donc ces caractères qu'il faudra changer pour modifier l'adresse de retour. On Recommence l'opération,
Nom:ABCDE...X il faut alors taper l'adresse 0x00401211 à la place de YZab. Attention, il faut les taper à l'envers car on est en litle endian --> 11 12 40 00 et en décimal 17 18 64 00 (alt + 17 sur le pavé numérique [ne fonctionne pas sur les portables] pour écrire le caractère 17). Puis entrer et entrer (mot de passe) et ... miracle on arrive directement au logon() après le if en squizzant le test !!!!
Il faudra sûrement changer les valeurs des adresses suivants les compilos et ce ne sera peut être pas aussi évident si tu as juste le binaire et un débogueur mais bon perso je me suis bien amusé à faire mon premier buffer overflow :p

@+ Neria
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de cs_neria
Taron31 199 Messages postés vendredi 16 avril 2004Date d'inscription 28 février 2008 Dernière intervention - 1 nov. 2005 à 13:10
+3
Utile
Ouais c'est exactement ça, tu peux preciser que la valeur pointée par
ESP est EIP Saved précédement pushée lors de l'appel de check_name() :)



Ps : puis-je savoir dans quel cursus te situes-tu et en quelle année ? (ca m'interesse)

Bye.
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de Taron31
cosmobob 706 Messages postés mardi 30 décembre 2003Date d'inscription 27 janvier 2009 Dernière intervention - 31 oct. 2005 à 23:56
+1
Utile
salut,

tu dois recuperer l'adresse de ta fonction logon (rajout un printf("addresse : %u\n", logon);)

et le but est de donner un nom trop long, pour ecraser l'adresse a
laquelle la fonction check_name retourne (cette adresse est placée sur
la pile lors du call check_name) et y mettre celle de la fonction logon.

ya des chances qu'elle se situe aux alentours de password[22] ou 23, c la que le debugger de ton compilo doit t'aider.

Donne le nom AAAAAAAAAAAAAAAAAAAAAAAA jusqu'a depasser de 20
caracteres, et regarde qd ton programme va planter. il va planter qd
justement t'auras ecrasé l'adresse de la pile qui est utilisée qd
check_name retourne.



bref si ca a pu un peu t'éclairer ...
Commenter la réponse de cosmobob
tomk_41 2 Messages postés jeudi 16 novembre 2000Date d'inscription 31 octobre 2005 Dernière intervention - 31 oct. 2005 à 23:44
0
Utile
J'ai cru comprendre qu'il fallait debuguer par exemple sous Dev C++ pour voir ou sont stockée les variables. Si quelqu'un pense pouvoir m'aider, je peux lui envoyer l'executable qui est fourni.
Mon adresse : tomk_41@yahoo.fr
Merci d'avance à tous.
Commenter la réponse de tomk_41
cs_neria 320 Messages postés vendredi 21 février 2003Date d'inscription 16 février 2009 Dernière intervention - 1 nov. 2005 à 16:17
0
Utile
On peux continuer cette discussion en MP si tu le souhaites.

@+
Commenter la réponse de cs_neria

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.