Annonce

Réduire
Aucune annonce.

Porter un Buffer Overflow Python vers du Ruby pour l'automatiser sous MSF

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

  • Porter un Buffer Overflow Python vers du Ruby pour l'automatiser sous MSF

    Salut ! Je suis en train d'apprendre à porter un exploit statique en python vers du Ruby pour le rendre utilisable par Metasploit de façon dynamique. (Choix de l'adresse IP, du payload etc...)

    Je me base sur ce tutoriel qui m'a permis d'apprendre pour poser ma question. Le buffer overflow de l'exploit à la forme suivante : [Offset][EIP][Padding][Shellcode]. Mon problème se situe à la partie Shellcode.

    Dans l'exemple du tutoriel, l'exploit en python à 338 Bytes de taille pour son shellcode. Tandis que pour l'exploit en Ruby la taille du shellcode est de 444bytes. Je ne comprends pas cette différence de taille. Dans ma logique la taille devrai être la même.

    Un ami m'a suggéré que à cause de la taille réservé pour l'encodage des variables. Cette taille ne serait pas la même pour Python et Ruby.

    Est-ce exact ce que m'a suggéré mon ami ?
    Si oui, pouvez vous m'expliquer de manière à ce que je soit capable de retomber sur 444bytes avec le calcul adéquat ?

    J'ai retourné Google et là je sèche vraiment....

    Pour vous aider voici les différentes tailles des buffers :

    ------ Python Exploit ---- Size Shellcode / payload : 338 Bytes Offset : 230 bytes EIP -> JMP ESP : 4 bytes Padding ESP : 15 bytes Total Buffer Size : 587
    ------ MSF Exploit ---- Size Shellcode / Payload : 444 bytes offset : 230 bytes EIP -> JMP ESP : 4 bytes Padding ESP : 15 Bytes Total Buffer Size : 693 Bytes

    En vous remerciant par avance

  • #2
    Salut et bienvenue,

    Je vais être clair : je n'y connais pas grand-chose à python (cela dit, le code est facile à lire) et moins encore à Ruby (mais ce ne semble pas très compliqué). Quant à Metasploit, heu... Presque rien.

    Là, tu dois te dire que tu es tombé sur le seul ignare de cette communauté, pas de bol. Mais il y a une chose que je connais, c'est le langage machine, du moins l'assembleur. Et, dans ce domaine, si la taille d'un code A n'est pas égale à celle d'un code B, c'est que ce ne sont pas les mêmes codes. Autrement dit, je pense que Metasploit utilise ses propres shellcodes ainsi que certaines variables le font penser.
    Code:
    'Payload'        =>            
    
            {
    
              'Space'    => 444,                                      
    
              'BadChars' => "x00x0ax0bx27x36xcexc1x04x14x3ax44xe0x42xa9x0d",        
    
            },
    Il semble que tu doives donner des contraintes et Metasploit te sert un shellcode. D'ailleurs où est-il dans le code Ruby ? Nulle part on trouve celui de l'exploit en python.

    L'auteur de l'article l'indique au début :
    3) Our payload will be chosen via the console or GUI but within the code, we will only have to enter it as payload.encoded.
    Et ici, il fait son choix :
    Selecting a payload

    After this, the next step is to choose a payload. Try entering show payloads and hit enter to display the possible payloads for use with this exploit.

    exp5_11

    After some inspection, I decided that the meterpreter payload would be a great choice given our buffer size and the fact that the payload would be encoded to avoid the bad characters we listed.

    Commentaire


    • #3
      Salut Icarus, et merci de t'intéresser à mon problème ! Toute aide est la bienvenue !

      En effet tu as vu juste. le "payload" / "shellcode" (code qui va permettre et choisir la méthode de connexion de la victime sur le pirate) va être codé en dur dans l'exploit en python.
      Tandis qu'en ruby, l'intérêt va être de le "sélectionner". Par exemple le shell_bind_tcp permettra l'ouverture d'un port choisi sur la victime pour que le pirate puisse se connecter dessus.

      Avec Metasploit l'intérêt est de générer dynamiquement ce Payload en fonction de ce l'utilisateur à définis. La variable "Space" que tu as présenté dans ton sreenshot va donc servir à identifier la taille maximum autorisée.

      La taille sera variable entre les payloads, le boulot de Metasploit sera donc de combler l'espace en trop avec des slides NOP ou des caractères aléatoires par exemple. Tout en prenant d'autre contraintes si elles sont spécifiées comme éviter certains caractères avec les "Badchars" ou encore un encoding spécifique...C'est donc pour ça que tu ne vois pas de code apparaître dans l'exploit en ruby !

      Ce que tu dis me parait logique. Ce qui me chiffonne c'est que dans le principe du buffer overflow. En vulgarisant énormément, on va trouver la taille à laquelle le logiciel va planter, on va localiser EIP, faire pointer EIP vers notre buffer pour permettre l'exécution du shellcode.

      Donc, dans la totalité du buffer une partie sera délimitée pour le shellcode. Cette partie aura pour pré-requis, un espace assez grand pour y placer notre shellcode, puis la possibilité de le joindre via un JMP. Cependant cette partie à une taille bien précise, lors de l'écriture du shellcode il ne faudra pas dépasser ou laisser vide l'espace alloué, sous peine d'écraser ou de décaler le reste de la pile.

      C'est pour cette raison que je ne vois pas la logique entre un taille réservé différente d'un langage à un autre !

      Si jamais mon raisonnement est mauvais n'hésite pas à me corriger

      Commentaire


      • #4
        C'est effectivement un écrasement de pile. Ce qui compte, c'est le nombre d'octets pour atteindre le début de la pile et l'écraser avec une adresse calculée (ces paramètres dépendent de la faille exacte et parfois de la version de l'OS). Un ret transférera tôt ou tard cette adresse à EIP (tout en faisant remonter ESP de 4 octets).

        De ce que je comprends, on met une adresse connue de shell32.dll (chargée dans chaque application) qui contient l'instruction jmp ESP. Cela va provoquer un saut vers la pile justement. Il faut donc que le shellcode s'y trouve (ce qui est le cas en regardant comment la charge est constituée). Le shellcode écrase donc la pile. Il y a forcément une limite de taille, ne serait ce que de par l'adresse limite haute allouée au programme cible mais la pile sera de toute façon irrécupérable.

        Une fois le "boulot" terminé, au mieux, on finit plus ou moins proprement par un call ExitThread si applicable et si ça marche (l'application reste active mais éventuellement dans un état anormal), sinon call ExitProcess, ce qui termine l'application. On peut aussi la laisser planter...

        Je ne sais pas si je suis clair. Je pense qu'il faut quand même quelques notions d'assembleur pour se faire une idée de la chose.

        Commentaire


        • #5
          Yes tu est très clair, tout ce que tu as pu dire me parle complètement. Sans en être un expert, le fonctionnement de assembleur et l'agencement des registre pour créer un Buffer Overflow fonctionnel me parle. J'ai pu réaliser des challenges pour me familiariser avec ces notions.

          En soit ici, c'est pas la création du buffer overflow qui pose problème, mais plutôt la conversion en ruby. Cette augmentation de la taille du shellcode pour moi sort de nulle part, rien est expliqué à ce sujet dans le cours ou sur google. Pourtant le développeur n'a pas fait ça par hasard...

          Commentaire


          • #6
            Honnêtement, je ne vois pas ce qui te pose problème. Le shellcode est indépendant de python ou Ruby. C'est une suite d'octets qui constitue un programme en langage machine. Tout ce qu'on lui demande, outre de ne pas contenir certaines valeurs (en raison de la faille elle-même), c'est d'ouvrir une ligne de commande et diriger les entrées / sorties vers le réseau. Il en existe une multitude. Je suis certain qu'on peut mettre le même dans la version python et vice-versa pour Ruby, cela fonctionnera très bien.

            Le truc ici, c'est que l'auteur utilise ceux disponibles dans msf plutôt que de recopier celui de l'exploit initial (car sinon je pense que ce doit être compliqué d'obtenir la ligne de commande via msf). Quant à la taille de 444 octets qui est un maximum, j'ignore d'où ça vient mais on peut penser que l'auteur de l'article a estimé ou mesuré le nombre d'octets disponibles avant d'arriver à une zone mémoire interdite en écriture (ce qui planterait le serveur ftp sans avoir le temps d'exécuter le shellcode). Si cela te tracasse tant, demande directement à cette personne.

            Une précision que je vois à présent, c'est qu'il utilise un shellcode codé de sorte que les valeurs interdites n'y apparaissent pas. Une première partie de ce programme doit donc d'abord décoder la suite avant d'exécuter sa fonctionnalité première. Une fois décodé, les valeurs interdites peuvent apparaître sans problème puisque le transport de la charge a été effectuée par le programme victime.

            Dernier point : cet exploit risque fort de ne fonctionner que sur Windows XP SP3 anglais à cause de la référence absolue de l'adresse mémoire de shell32.dll. Il fera probablement planter le serveur ftp pour toute autre version.
            Dernière modification par Icarus, 17 mai 2018, 18h46.

            Commentaire


            • #7
              Merci, icarus, j'ai trouvé la réponse à mon interrogation plus tôt dans la journée et ce que tu dis le confirme.

              444 n'est autre que la partie du buffer se trouvant juste après EIP. Elle comprend l'espace adressable pour les Nops + Shellcode. Le rédacteur à tout simplement dû constater qu'en pratique au maximum il y avait un buffer adressable de 444 octets au lieu de 353. Mais ne l'ayant pas mentionné clairement dans le tuto je n'ai pas vu de corrélation entre les deux et je me suis fait des noeuds au cerveaux haha !

              Dans tous les cas je te remercie pour ton intérêt, tes précisions et ta patience !
              Dernière modification par 3r4inZ, 17 mai 2018, 22h34.

              Commentaire


              • #8
                Une toute petite précision, non pour toi car tu es au fait de la chose, mais pour les personnes qui liraient ce sujet : EIP est le registre du processeur qui contient l'adresse de l'instruction qui va être exécutée ou qui est en cours d'exécution pour le mode protégé 32 bits (il signifie Extended Instruction Pointer). Ici, on écrase le début de la pile pour modifier ce registre dès lors qu'un ret est exécuté.

                Commentaire

                Chargement...
                X