Annonce

Réduire
Aucune annonce.

Buffer Overflow - Mémoire & exploitation.

Réduire
X
 
  • Filtre
  • Heure
  • Afficher
Tout nettoyer
nouveaux messages

  • Tutoriel Buffer Overflow - Mémoire & exploitation.

    Bonjour à tous.

    Dans ce tutoriel nous allons voir ce qu'est un Buffer Overflow et comment l'exploiter succintement. Nous verrons aussi comment fonctionne la mémoire au sein d'un programme.
    Les dépassements mémoires sont très largement utilisés à notre époque en ce qui concerne le domaine des failles applicatives. En effet, l'accès à la mémoire d'un programme permet de le modifier, de détourner ses flux de données, d'obtenir des droits (bit SUID) etc etc.



    I) La mémoire

    A) Définition et rappels

    Tout d'abord, qu'est-ce que la mémoire ?
    Lorsqu'un programme s'exécute cela correspond à une série d'opération réalisées par l'ordinateur. Les valeurs des variables utilisées, les résultats et les valeurs temporaires des opérations sont stockés afin d'être réutilisés plus tard. Chacune valeur de ces valeurs correspond à un octet (codé sur 8 bits), et à chacun de ces octets correspond une adresse mémoire unique. Ainsi, il est possible d'accéder à ces valeurs en utilisant leur adresse en mémoire. Une adresse est toujours unique pour une valeur unique afin d'éviter les collisions.
    Ces adresses peuvent être de format différent dépendant de l'architecture du processeur utilisé. Ainsi, pour un processeur 32 bits, l'adresse sera une séquence numérique composée de 32 chiffres. Pour un processeur 64 bits, l'adresse sera une séquence numérique composée de 64 chiffres.
    Rappel: 1 octet = 8 bits, donc 32 bits = 4 octets


    Chaque composant physique possède un bloc mémoire spécifique, généralement de petite taille.
    Le processeur possède un bloc mémoire spécifique primordial puisqu'il permet d'enregistrer les évènements générés lors de l'exécution d'une routine, d'un service ou d'un programme. Ces évènements enregistrés sont ensuite stockés puisqu'ils sont utilisés dans le cas des diagnostics systèmes réalisés dans le cas d'un crash du programme par exemple.
    Ce bloc mémoire est divisé en secteurs que l'on appelle les registres. Il existe plusieurs registres, mais seuls trois sont vraiment important pour le processeur.
    Le premier, et le plus important, est l'EIP pour Extended Instruction Pointer ; il permet d'enregistrer les différentes adresses mémoire des instructions générées par le programme. Ensuite vient l'ESP pour Extended Stack Pointer et l'EBP pour Extended Base Pointer.

    Nous parlons donc maintenant de pointeur. Mais qu'est-ce qu'un pointeur ?
    Même pour les programmeurs chevronnés, il est toujours bon de rappeler ce qu'ils sont et leur utilité.
    Un pointeur permet de stocker une adresse mémoire afin qu'elle soit utilisée par une fonction dans un programme. Pour réutiliser un bloc mémoire il est nécessaire de le recopier ; en effet, la mémoire est statique, elle ne peut être déplacée manuellement. Le pointeur permet donc de passer l'adresse mémoire rapidement quand une fonction en a besoin. On gagne ainsi de la vitesse et du temps.



    B ) Répartition de la mémoire

    Il existe différentes zones composant le bloc mémoire ; on dit que la mémoire est segmentée.
    Ces zones sont au nombre de cinq. Le schéma suivant illustre la répartition de ces cinq zones:





    Ces cinq zones sont donc (dans l'ordre) le text, le data, le bss, le heap et le stack.

    La zone "text" permet de stocker les instructions que le programme exécutera au lancement. Quand le programme est lancé, le registre EIP commence à lire le début de ce segment puis évolue au long de l'exécution. Cette zone n'est pas accessible en écriture car les instructions du programmes ne peuvent pas être modifiées !

    La zone "data" permet de stocker la valeur d'initialisation des variables globales utilisées par le programme. Cette zone est accessible en écriture mais non modifiable en espace de stockage.

    La zone "bss" permet de stocker la valeur d'initialisation des variables statiques utilisées par le programme. Cette zone est accessible en écriture mais non modifiable en espace de stockage.

    La zone "heap" permet de stocker la valeur des variables dynamiques utilisées par le programme. Cette zone est accessible en écriture et modifiable en espace de stockage.

    La zone "stack" (pile) permet de stocker des valeurs temporaires, des résultats de transition. Quand une fonction utilise une variable, sa valeur est stockée dans le stack puis libérée ensuite. La pile permet donc de stocker des valeurs. Cependant, l'ordinateur a besoin de connaitre différentes choses au sein de la pile: son point d'entrée, la position des valeurs dans la pile etc etc. C'est à ça que vont servir les trois registres du processeur cités plus haut.
    Le registre ESP permet de connaitre le point d'entrée de la pile, donc le "haut" de la pile. Tandis que le registre EBP permet de localiser une valeur dans la pile afin de la lire, l'extraire ou autre.




    II) Buffer Overflow

    Le Buffer Overflow est le dépassement de la mémoire allouée initialement lors de l'exécution d'un programme. En effet, quand l'on surcharge un programme en lui passant un argument trop grand pour la mémoire allouée, cela va entraîner une corruption du bloc et des différentes variables qui s'y trouvent. Généralement cela permet de crasher le programme ou d'accéder à des zones mémoires non-autorisées.

    Voilà un exemple très simple de Buffer Overflow écrit en C:

    Code:
    #include <stdio.h>
    
    int main() {
    char bufferMDP[10];
    printf("Choisissez un mot de passe pour votre compte: ");
    scanf("%s",&bufferMDP);
    printf("\nMot de passe choisi: %s",bufferMDP);
    return 0;
    }

    On définit un tableau (bufferMDP) pouvant contenir 10 caractères.

    Exécutons le programme:

    Code:
    -> "Choisissez un mot de passe: "
    -> azerty1234
    -> "Mot de passe choisi: azerty1234"
    -> Programme fermé correctement.
    
    -> "Choisissez un mot de passe: "
    -> azerty123456789
    -> "Mot de passe choisi: azerty123456789"
    -> Erreur de segmentation 0x80000 le programme ne s'est pas fermé correctement.

    Dans le deuxième cas, on rentre un mot de passe supérieur à la taille du tableau, la mémoire est donc corrompue et le programme crash avec une erreur (généralement l'erreur comporte l'adresse de la corruption).

    Cette exemple a créé un Buffer Overflow dans la pile, ce que l'on appelle un stack-based overflow, qui consiste a réécrire la mémoire allouée afin de déborder sur des instructions privées et donc de réécrire leurs valeurs. Il existe des Buffer Overflow pour chaque zone mémoire: heap-based overflow, bss based-overflow...

    Comment s'accorder les privilèges root par un stack-based overflow ?
    Tout simplement en passant un shell (il en existe des milliers sur Internet) argumentaire supérieur à la taille du tableau alloué. Ce shell sera réécrit sur les emplacements mémoire privés et sera donc exécuté par le programme. On peut de cette façon s'accorder le bit SUID afin d'avoir les privilèges maximaux sur le programme. Par exemple, un buffer overflow sur le terminal de commande linux nous permettrait de l'exécuter en privilège root (sudo).


    Dernière modification par MadHatter, 27 décembre 2011, 17h44.
    Ex-membre Hackademiciens.

  • #2
    Un peu trop succinct pour être compris par un débutant. L'exploitation pratique n'est pas vu du tout. Ce qui est dommage.

    Petite erreur d'inattention :
    "Le registre ESP permet de connaitre le point d'entrée de la pile, donc le "haut" de la pile. Tandis que le registre EBP permet de localiser une valeur dans la pile afin de la lire, l'extraire ou autre."


    Mais même comme ça j'ai pas tellement compris ta phrase. EBP sert normalement à délimiter la stack pour la fonction en cours, il contient son adresse de début.
    Ou tu ne t'es pas trompé. Mais le "Tandis que" est de trop dans ce cas.
    Dernière modification par kallimero, 22 décembre 2011, 17h51.

    Commentaire


    • #3
      @Kallimero, je ne crois pas que son tuto ait la prétention d'être exhaustif. Je le vois plus comme une bonne introduction, d'autant qu'il est posté dans "basic knowledge"

      Pour les an­glo­philes qui voudrait pousser le sujet, je vous propose de lire les tutos de "Lupin" et "sickness" sur le sujet :

      Lupin/Windows:
      http://grey-corner.blogspot.com/2010/01/beginning-stack-based-buffer-overflow.html
      http://grey-corner.blogspot.com/2010...-overflow.html
      http://grey-corner.blogspot.com/2010...-tutorial.html
      http://grey-corner.blogspot.com/2010...-internet.html
      http://grey-corner.blogspot.com/2010...-tutorial.html

      Sickness/Linux:
      http://www.exploit-db.com/download_pdf/17008
      http://www.exploit-db.com/download_pdf/17049
      http://www.exploit-db.com/download_pdf/17131

      Plus de détails : http://www.backtrack-linux.org/forums/experts-forum/39462-writing-buffer-overflow-exploits-linux.html#post193531
      Dernière modification par comaX, 22 décembre 2011, 19h54.

      Commentaire


      • #4
        Envoyé par kallimero Voir le message
        Un peu trop succinct pour être compris par un débutant. L'exploitation pratique n'est pas vu du tout. Ce qui est dommage.

        Petite erreur d'inattention :
        "Le registre ESP permet de connaitre le point d'entrée de la pile, donc le "haut" de la pile. Tandis que le registre EBP permet de localiser une valeur dans la pile afin de la lire, l'extraire ou autre."


        Mais même comme ça j'ai pas tellement compris ta phrase. EBP sert normalement à délimiter la stack pour la fonction en cours, il contient son adresse de début.
        Ou tu ne t'es pas trompé. Mais le "Tandis que" est de trop dans ce cas.

        Un peu trop succinct pour être compris par un débutant ? C'est antithétique. C'est notamment parce qu'il est succinct, mais regroupe la base de ce qu'il faut savoir, qu'il peut être compris par un débutant en applicatif. Pour éviter d'entendre un "ton tutoriel il fait 30m de long, je ne vais sûrement pas lire ça, je n'y connais rien" ; qui est de bonne guerre quand on y pense.
        Pour ce qui est de l'exploitation, si tu relis le début "comment l'exploiter succinctement" tu devrais donc t'apercevoir que j'avertis le lecteur que ce sera une exploitation théorique de dépassement de tampon succincte ; ce qui est fait.

        En ce qui concerne ma phrase sur les registres, je ne vois pas ce qui te chagrines. La fonction première de l'EBP est bien de localiser ou pointer sur une position x dans la pile, ensuite il sert également à définir la stack de la fonction active.
        "Celui là sert à ça, tandis que celui-ci à ça", délimitation sémantique de deux objets du discours possédant deux sens différents , ne fait pas figure d'opposition ici.

        Et donc, pour finir, il est normal que ce tutoriel n'aborde pas la segmentation et la distribution de la mémoire de façon poussée et/ou détaillée (appels, bloc, leaks, croisements, récursivité, fractionnement), ni l'application poussée (réécriture, corruption, shell injection, détournement, altération) ; je l'ai écrit pour un support théorique de vrai débutant. Il faut commencer par là avant d'aborder un tutoriel long et détaillé, sinon c'est rebutant et fortement anti-pédagogique. Ce serait comme vouloir résoudre Schrodinguër sans apprendre les additions avant .
        D'où sa présence dans le level I, où il ne faut donc pas s'attendre à de l'hardcore.

        Mais ne t'en fais pas, j'en ai un autre bien plus costaud, long, et pour le coup très détaillé pour le Level II .
        Ex-membre Hackademiciens.

        Commentaire


        • #5
          Oui, "Lorie" () a raison. C'est vraiment une introduction pour débutants, très bien faite de surcroit. Le BO en exemple est vraiment simple à comprendre. Et la partie 1 est bien détaillée (et sa syntaxe est correcte ).

          Il a bien sa place en L1 (Level I), et dans Basic Knowledge. La gestion (l'allocation) mémoire est une des bases fondamentales à connaître tu en conviendras
          sigpic

          Cyprium Download Link

          Plus j'étudie plus j'me rends compte que je n'sais rien.

          †|

          Commentaire


          • #6
            Si EBP est en gras dans ma citation c'est parce que j'ai corrigé ce que tu as dis.
            " Le registre ESP permet de connaitre le point d'entrée de la pile, donc le "haut" de la pile. Tandis que le registre ESP permet de localiser une valeur dans la pile afin de la lire, l'extraire ou autre."

            Je sais ce que signifie tandis que, merci.

            Succinct n'était peut être pas tout à fait adapté. Ce que je voulais dire, c'est surtout qu'il est bien trop "touffu".(désolé, manque d'inspiration), et trop abstrait, pour être assimilé facilement. Si on balance ça a un débutant je ne pense pas qu'il pourra suivre. Mais sinon, l'info est là. C'est peut être le pincipal.

            Commentaire


            • #7
              Autant pour moi, j'avais lu en diagonale ; j'ai corrigé l'erreur d'inattention (ESP -> EBP), merci pour la remarque.
              Ex-membre Hackademiciens.

              Commentaire


              • #8
                Envoyé par kallimero Voir le message
                Un peu trop succinct pour être compris par un débutant
                Envoyé par kallimero Voir le message
                il est bien trop "touffu"
                Un peu contradictoire sur ce coup !

                Moi je le trouve pas mal, plutôt débutant, bien détaillé. Après il y a certaines choses qui mériteraient d'être un peu plus développées (je pense que c'est ce que tu voulais dire kallimero) pour les "débutants débutants". Mais bon en même temps, ici, c'est pas le siteduzero^^ Après par contre, le BO et bien trop peu expliqué, mais je pense que Madhatter en à sous le pied à ce sujet. Cela devra être placé en Level II pour le coup.

                En tous cas merci pour le soulignement de la petite bévue kallimero.
                sigpic

                Cyprium Download Link

                Plus j'étudie plus j'me rends compte que je n'sais rien.

                †|

                Commentaire


                • #9
                  Il a surtout réussi le tour de force de parler de BOF sans évoquer une seule fois l'adresse de retour empilée, qui est pourtant le concept central d'un BOF. Parce qu'avec ce qui est décrit, impossible d'exécuter un shell.. Si on pense qu'un shellcode sera (je cite) "réécrit sur les emplacements mémoire privés et sera donc exécuté par le programme", on va avoir beaucoup de mal à faire quoi que ce soit de tangible.

                  Commentaire


                  • #10
                    C'est bien de critiquer, à condition d'être constructif. Je te ferais la même remarque qu'à quelqu'un d'autre dans cette même discussion :"@Kallimero, je ne crois pas que son tuto ait la prétention d'être exhaustif. Je le vois plus comme une bonne introduction, d'autant qu'il est posté dans "basic knowledge" "

                    Commentaire


                    • #11
                      Ce que je lui reproche ce n'est pas de n'être pas exhaustif, c'est de n'avoir pas introduit le BOF. Tout ce qu'on a introduit là, c'est la SegFault, c'est tout.

                      Commentaire


                      • #12
                        Libre à toi de créer une discussion pour le faire alors

                        Commentaire


                        • #13
                          Je prends en considération ta remarque Beru, mais je n'en changerai pas pour autant cette introduction très liminaire, et c'est d'ailleurs ici sa prérogative.
                          Et ce n'est pas "un tour de force", c'est un choix ; je n'ai pas voulu traiter le calling-code ni le called-code à dessein. L'absence de ces deux notions ne représente absolument pas un facteur limitant pour ma démonstration initiale.
                          C'est vu sous un autre angle pédagogique ; ce n'est pas parce qu'il diverge du tien qu'il est bancale.

                          Comme le dit ComaX, je t'invite à écrire un tutoriel plus complet et détaillé qui viendra se superposer à celui-ci, afin que le sujet soit traité au complet.
                          Ex-membre Hackademiciens.

                          Commentaire


                          • #14
                            C'est ton choix. Mais que reste-t-il du BOF si on ne traite pas du "calling-code"? En définitive, de quoi ton tutoriel est-il l'introduction, si ce n'est du SegFault et quelles en sont les possibilités à part faire planter une routine?

                            Commentaire


                            • #15
                              J'ai quand même eu du mal à comprendre mais bon tutoriel tout de même merci !

                              Commentaire

                              Chargement...
                              X