Forum d'Entraide Informatique Index du Forum
Forum d'Entraide Informatique

Venez partager vos connaissances, soumettre vos problèmes informatiques ou lire les articles et astuces...
 AccueilAccueil   Site internet du ForumSite   FAQFAQ  RechercherRechercher   Liste des MembresListe des Membres   Groupes d'utilisateursGroupes d'utilisateurs   S'enregistrerS'enregistrer 
 RechercherStatistiques   Jeux d'arcadeJeux d'arcade    ProfilProfil   Se connecter pour vérifier ses messages privésSe connecter pour vérifier ses messages privés   ConnexionConnexion 
Buffer overflow comment sa marche

 
Poster un nouveau sujet   Répondre au sujet    Forum d'Entraide Informatique Index du Forum -> Infos Sécurité
Voir le sujet précédent :: Voir le sujet suivant  
Auteur Message
Netstat
Niveau de Participation :
Niveau de Participation :


Inscrit le: 25 Avr 2006
Messages: 12

MessagePosté le: Dim Avr 30, 2006 9:40 am    Sujet du message: Buffer overflow comment sa marche Répondre en citant

Généralités

Pour créer des exploits et comprendre leur action, il est nécessaire de connaître
plusieurs concepts des Systèmes d’Exploitation, comme l'organisation de la mémoire,
la structure des fichiers exécutables et les phases de la compilation. Nous détaillerons
ces principes dans ce chapitre pour le système d'exploitation Linux.

1.1 Le format ELF et l’organisation de la mémoire

Grâce au principe de mémoire virtuelle, chaque programme, quand il est exécuté
obtient un espace mémoire entièrement isolé. La mémoire est adressée par mots (4
octets) et couvre l'espace d'adresse de 0x00000000 - 0xffffffff soit 4 Giga octets
adressables. Le système d’exploitation Linux utilise pour les programmes
exécutables, le format ELF1 (Executable Linking Format) qui est composé de
plusieurs sections.
L'espace virtuel est divisé en deux zones: l'espace user (0x00000000 - 0xbfffffff) et
l'espace kernel (0xc0000000 - 0xffffffff). Contrairement au kernel avec l'espace user,
un processus user ne peut pas accéder à l'espace kernel. Nous allons surtout détailler
cet espace user car c'est lui qui nous intéresse.
Un exécutable ELF est transformé en une image processus par le program loader.
Pour créer cette image en mémoire, le program loader va mapper en mémoire tous les
loadable segments de l'exécutable et des librairies requises au moyen de l'appel
système mmap(). Les exécutables sont chargés à l’adresse mémoire fixe 0x080480002
appelée « adresse de base ».
La figure 1 montre les sections principales d'un programme en mémoire. La section
.text de la figure correspond au code du programme, c'est-à-dire aux instructions.
Dans la section .data sont placées les données globales initialisées (dont les valeurs
sont connues à la compilation) et dans la section .bss les données globales noninitialisées.
Ces deux zones sont réservées et connues dès la compilation. Une variable
locale static (la définition de la variable est précédé mot-clé static) initialisée se
retrouve dans la section .data et une variable locale static non initialisée se retrouve
dans la section .bss.

La pile quant à elle contient les variables locales automatiques (par défait une variable
locale est automatique). Elle fonctionne selon le principe LIFO (Last in First Out),
premier entré premier sorti, et croît vers les adresses basses de la mémoire. A
l'exécution d'un programme, ses arguments (argc et argv), ainsi que les variables
d'environnement sont aussi stockés dans la pile.
Les variables allouées dynamiquement par la fonction malloc() sont stockées dans le heap.




Nous allons voir quelques déclarations de variables et leur location en mémoire:
int var1; // bss
char var2[] = "buf1"; // data
main(){
int var3; // stack
static int var4; // bss
static char var5[] = "buf2"; // data
char * var6; // stack
var6 = malloc( 512 ); // heap
}
La commande size permet de connaître les différentes sections d'un programme ELF
et de leur adresse mémoire.
ouah@weed:~/heap2$ size -A -x /bin/ls
/bin/ls :
section size addr
.interp 0x13 0x80480f4
.note.ABI-tag 0x20 0x8048108
.hash 0x258 0x8048128
.dynsym 0x510 0x8048380
.dynstr 0x36b 0x8048890

.gnu.version 0xa2 0x8048bfc
.gnu.version_r 0x80 0x8048ca0
.rel.got 0x10 0x8048d20
.rel.bss 0x28 0x8048d30
.rel.plt 0x230 0x8048d58
.init 0x25 0x8048f88
.plt 0x470 0x8048fb0
.text 0x603c 0x8049420
.fini 0x1c 0x804f45c
.rodata 0x2f3c 0x804f480
.data 0xbc 0x80533bc
.eh_frame 0x4 0x8053478
.ctors 0x8 0x805347c
.dtors 0x8 0x8053484
.got 0x12c 0x805348c
.dynamic 0xa8 0x80535b8
.sbss 0x0 0x8053660
.bss 0x2a8 0x8053660
.comment 0x3dc 0x0
.note 0x208 0x0
Total 0xade9
(Des informations similaires mais plus détaillées peuvent être obtenues avec les
commandes readelf –e ou objdump -h). Nous voyons apparaître l’adresse en mémoire
et la taille (en bytes) des sections qui nous intéressent : .text, .data et .bss. D’autres
sections, comme .plt, .got ou .dtors seront décrites dans les chapitres suivants.

1.2 L’appel de fonction avec le compilateur gcc

Nous allons voir comment est fait l’appel d’une fonction en assembleur dans un
programme compilé avec gcc au moyen d’un programme qui nous servira d’exemple.
void foo(int i, int j){
int a = 1;
int b = 2;
return;
}
main(){
foo(5,6);
}
Le programme appelle une fonction foo() avec plusieurs arguments. Désassemblons
ce programme au moyen du débugger gdb, pour voir comment se passe l’appel,
l’entrée et la sortie d’une fonction et comment sont gérés les arguments et les
variables locales d’une fonction.
ouah@weed:~/chap2$ gdb tst -q
(gdb) disassemble main
Dump of assembler code for function main:
0x80483d8 <main>: push %ebp
0x80483d9 <main+1>: mov %esp,%ebp
0x80483db <main+3>: sub $0x8,%esp
0x80483de <main+6>: add $0xfffffff8,%esp
0x80483e1 <main+9>: push $0x6
0x80483e3 <main+11>: push $0x5

0x80483e5 <main+13>: call 0x80483c0 <foo>
0x80483ea <main+18>: add $0x10,%esp
0x80483ed <main+21>: leave
0x80483ee <main+22>: ret
0x80483ef <main+23>: nop
End of assembler dump.
(gdb) disassemble foo
Dump of assembler code for function foo:
0x80483c0 <foo>: push %ebp
0x80483c1 <foo+1>: mov %esp,%ebp
0x80483c3 <foo+3>: sub $0x18,%esp
0x80483c6 <foo+6>: movl $0x1,0xfffffffc(%ebp)
0x80483cd <foo+13>: movl $0x2,0xfffffff8(%ebp)
0x80483d4 <foo+20>: jmp 0x80483d6 <foo+22>
0x80483d6 <foo+22>: leave
0x80483d7 <foo+23>: ret
End of assembler dump.
Nous voyons donc ci-dessus les fonctions main() et foo() désassemblées.

Appel d’une fonction
Dans notre programme, la fonction foo() est appelée avec les paramètres 5 et 6. En
assembleur, cela est accompli ainsi :
0x80483e1 <main+9>: push $0x6
0x80483e3 <main+11>: push $0x5
0x80483e5 <main+13>: call 0x80483c0 <foo>
En <main+9>, l’appel de la fonction commence. On empile d’abord avec l’instruction
push les arguments de la fonction en commençant par le dernier. On saute ensuite au
moyen de l’instruction call dans le code de la fonction foo(). L ‘instruction call ne fait
pas que sauter à l’adresse désirée, avant elle sauve le registre %eip dans la pile. Ainsi,
quand on sortira de la fonction foo(), le programme saura où revenir pour continuer
l’exécution dans main().

Prologue d’une fonction
Le prologue d’une fonction correspond aux premières instructions exécutées dans la
fonction soit depuis <foo>. Soit :
0x80483c0 <foo>: push %ebp
0x80483c1 <foo+1>: mov %esp,%ebp
0x80483c3 <foo+3>: sub $0x18,%esp
En <foo> nous sauvons d’abord le registre frame pointer (%ebp) sur la pile. Il s’agit
du frame pointer de la fonction d’avant. Ainsi, quand nous sortirons de la fonction
foo() le frame pointer pourra être remis à sa valeur sauvée. En <foo+1>, nous mettons
à jour le registre frame pointer, au début de la frame qui va commencer et qui est la
frame pour la fonction. En <foo+3>, nous réservons ensuite la place pour les variables
locales. La valeur 0x18 indique que 24 bytes ont été réservés pour nos 2 int (2*4
bytes), cela est plus que suffisant mais gcc (2.95.3) réserve au minimum 24 bytes. Si nous avions plus que 24 bytes de variables locales, il aurait donc fallu soustraire (la
pile croît vers le bas) plus de bytes. Le compilateur gcc réserve pour chaque frame un
espace dans la pile de taille multiple de 4.

Epilogue d’une fonction
L’épilogue correspond à la sortie de la fonction foo(). Elle doit alors retourner au bon
endroit et restituer le frame pointer sauvegardé par le prologue de la fonction. Le
prologue est effectué par ces deux instructions :
0x80483d6 <foo+22>: leave
0x80483d7 <foo+23>: ret
L’instruction leave est équivalente aux deux instructions suivantes :
mov %ebp,%esp
pop %ebp
Il s’agit de l’opération inverse de celle effectuée dans le prologue. On ramène le
sommet de la pile au niveau du frame pointer puis on restitue le frame pointeur
sauvegardé dans %ebp.
La dernière instruction, ret, retourne à l’endroit juste après l’appel de la fonction foo()
grâce à la valeur de retour stockée en pile durant l’appel. Enfin, au retour de la
fonction, en <main+18> :
0x80483ea <main+18>: add $0x10,%esp
On remet la pile en place pour revenir à la situation d’avant l’empilement des
arguments de foo() pour l’appel.

_________________
Se connaître soi-même, c'est s'oublier. S'oublier soi-même, c'est s'ouvrir à toutes choses
Revenir en haut de page
Voir le profil de l'utilisateur Envoyer un message privé
hargnes
Niveau de Participation :
Niveau de Participation :


Inscrit le: 10 Juin 2004
Messages: 334
Localisation: Hérault

MessagePosté le: Dim Avr 30, 2006 11:27 am    Sujet du message: Répondre en citant

Salut Netstat

En général sur les forums
--> pour eviter des ennuis aux responsables du forum.
--> par respect de l'auteur, du droit d'auteur et du travail qu'il a fourni..
Il est plutôt recommandé de citer ses sources, quand on est pas l'auteur de l'original.

En l'occurence l'article est
Advanced Exploitation of Buffer Overflows
de Olivier Gay
http://lasecwww.epfl.ch/php_code/publications/search.php?ref=Gay02
le document intégral est disponible ici.
http://lasecwww.epfl.ch/pub/lasec/doc/Gay02.pdf

Merci a toi d'y faire attention.
Clin d'oeil

_________________
XP.Net - A.I.L - MWC
Revenir en haut de page
Voir le profil de l'utilisateur Envoyer un message privé Visiter le site web de l'utilisateur
Netstat
Niveau de Participation :
Niveau de Participation :


Inscrit le: 25 Avr 2006
Messages: 12

MessagePosté le: Dim Avr 30, 2006 11:45 am    Sujet du message: Répondre en citant

oui dsl j ai oublier car en fait j ai pas fini l explication il reste sur la meme source d autre chose a mettre merci est ma source n est pas c est liens la mais tu a tous ta fait raison Sourire

Edit : a si dsl ^^ autant pour moi

_________________
Se connaître soi-même, c'est s'oublier. S'oublier soi-même, c'est s'ouvrir à toutes choses
Revenir en haut de page
Voir le profil de l'utilisateur Envoyer un message privé
Montrer les messages depuis:   
Poster un nouveau sujet   Répondre au sujet    Forum d'Entraide Informatique Index du Forum -> Infos Sécurité Toutes les heures sont au format GMT
Page 1 sur 1

 
Sauter vers:  
Vous ne pouvez pas poster de nouveaux sujets dans ce forum
Vous ne pouvez pas répondre aux sujets dans ce forum
Vous ne pouvez pas éditer vos messages dans ce forum
Vous ne pouvez pas supprimer vos messages dans ce forum
Vous ne pouvez pas voter dans les sondages de ce forum
Vous ne pouvez pas joindre des fichiers
Vous pouvez télécharger des fichiers


Copyright
Powered by phpBB © 2001, 2005 phpBB Group | RéférenceMod 1.0.2
Traduction par : phpBB-fr.com
Template by ©Dragons


Page générée en : 0.1658s (PHP: 83% - SQL: 17%) - Requêtes SQL effectuées : 16 - Compression GZIP désactivée - Debugage activé