ΙΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝ» Ί Initiation aux buffers overflows avec execution de code arbitraire Ί ΘΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΝΌ Introduction ~~~~~~~~~~~~ Je tiens a vous signaler que si vous n'avez pas quelques connaisances en assembleur et en cracking, vous aurez un peu de mal a suivre ce cours. Vous avez sans doute deja entendu parler d'une faille de securite dans un systeme informatique par "buffer overflow". Mais c'est quoi au juste un "buffer overflow" ? Tout d'abord, un buffer est un espace memoire de quelques octets. Le mot "overflow" signifie debordement de capacite. Donc un buffer overflow est un debordement de capacite de cette espace memoire. Voila pour la definition. Le programme "Buffer Overflow 1.0" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Ce programme va me servir a vous montrer l'execution d'un code arbitraire par buffer overflow. Executez le une premiere fois, vous apercevez en bas, le mot "User". User (Utilisateur), dans les systemes de type Unix, ce mode defini un utilisateur 'normal'. Au contraire le mot "Root" indique le statut de super-utilisateur (cf Manuel Unix). Notre but sera donc de devenir Root dans ce petit programme fonctionnement sous windows. Oui c'est paradoxal, mais nous on s'interesse plus aux buffers overflows qu'aux statuts des systemes Unix... Maintenant, rentrez un nom dans la case prevu a cette effet, puis validez le tout : une boite de message vous indique alors le nom tape... Ceci n'est pas d'une grande utilite mais ce n'est pas grave ;) Maintenant nous allons desassembler ce programme, pour etudier l'endroit oω le programme se defini en mode User ou Root. Apres quelques minutes on s'apercoit que c'est ici : :004011AF 803D4230400001 cmp byte ptr [00403042], 01 ;compare l'octet situe a ;l'offset 00403042 a 01 :004011B6 7518 jne 004011D0 ;si c'est egal tu es un utilisateur 'normal' ;sinon tu es 'root' :p On en conclut que si l'on met a l'offset 00403042, la valeur 00, alors on sera 'root'. Donc avec un editeur hexadecimal, ca serait facile d'etre 'root', mais ce n'est pas notre interet : nous on veux etre root en provoquant un buffer overflow :) Mais comment allons nous faire ? Simple, on va commencer par etudier la routine qui gere le stockage du nom et qui l'affiche dans une belle boite de message... :0040122A E869000000 Call 00401298 ;Stock le nom dans le buffer en 00401231 :0040122F EB0A jmp 0040123B :00401231 00000000000000000000 BYTE 10 DUP(0) ;Buffer qui stock le nom (10 octets) :0040123B 6A40 push 00000040 :0040123D 6835304000 push 00403035 :00401242 6831124000 push 00401231 :00401247 6A00 push 00000000 :00401249 E868000000 Call 004012B6 ;Affichage du nom Essayez de rentrer le nom "ABCDEFGHIJK", soit 11 octets : Boum ! Le programme plante ! Mais pourquoi ? Simple le buffer est de 10 octets, le 11eme octet viendra donc ecraser l'octet qui suit. Or cette octet va etre executer par le programme, c'est celui situe en 0040123B, qui est la "traduction" en hexadecimal de l'instruction "push". Vous pensez a ce que je pense ? Oui, nous allons utiliser cette faille, pour executer un code en assembleur, afin de devenir root :o) Nous avons dit tout a l'heure qu'il suffisait de mettre la valeur 00 a l'offset 00403042, pour devenir root. Ce qui en assembleur peut se traduire par ceci : mov eax,00403042h mov byte ptr [eax],00 Compilez ceci avec un compilateur ou en memoire avec SoftIce, et vous obtenez ceci en hexadecimal : B8 42 30 40 00 C6 00 00 Interessant, mais on va faire quoi avec ca ? On sait qu'a partir du 11eme octet du buffer, le code deviendra executable, nous allons donc rajouter ce code en hexadecimal, a partir du 11eme octet de notre nom. Si vous avez bien compris, ca donnera ca en memoire si on rentre 10 octets + B8 42 30 40 00 C6 00 00 dans la case de saisie : Call 00401298 ;Stock le nom dans le buffer en 00401231 jmp 0040123B BYTE 10 DUP(0) ;Buffer qui stock les 10 premiers octets du nom mov eax,00403042h ;Partie du buffer, transformee en instruction executable mov byte ptr [eax],00 ;Partie du buffer, transformee en instruction executable Mais un probleme se pose : comme vous le savez notre buffer va ecraser des instructions necessaire a la bonne execution du programme. Ce qui va provoquer une invaliditer des quelques instructions situe apres notre buffer. Pour remedier a ce probleme, nous allons "reequiliber" le programme en sautant les instructions qui cause une exeption, avec un jmp :) Notre ancien code etait : B8 42 30 40 00 C6 00 00 Nous le changeons en : B8 42 30 40 00 C6 00 00 EB 09 Un autre probleme se pose, comment voulez vous rentrez un code en hexadecimal au clavier, dans cette case de saisie ? Au debut de ce tutorial, je voulais cree un exploit (cf hacking) pour mieux illustrer ce cours et pour pouvoir rentrer ces octets en hexadecimal. Mais malheureusement, je me suis rendu compte que les octets a saisir dans la case de saisie, sont de valeur nulle pour certains. On ne peut donc pas, je pense, coder cette exploit... Mais si vous avez une idee, n'hesitez pas a me la dire ;-) Conclusion: ~~~~~~~~~~~ Voila cette initiation est terminee, j'espere qu'elle vous a aider a comprendre le principe des buffers overflows, qui sont principalement utilises pour etre root sur un systeme local ou distant :p Si vous avez des questions, des suggestions ou des critiques vous pouvez m'envoyer CoOlViPeR - coolviper@multimania.com