hacktricks/binary-exploitation/common-binary-protections-and-bypasses/libc-protections.md

11 KiB

Protections Libc

{% hint style="success" %} Apprenez et pratiquez le piratage AWS :Formation HackTricks AWS Red Team Expert (ARTE)
Apprenez et pratiquez le piratage GCP : Formation HackTricks GCP Red Team Expert (GRTE)

Soutenez HackTricks
{% endhint %}

Application de l'alignement des chunks

Malloc alloue de la mémoire par groupes de 8 octets (32 bits) ou 16 octets (64 bits). Cela signifie que la fin des chunks dans les systèmes 32 bits doit s'aligner sur 0x8, et dans les systèmes 64 bits sur 0x0. La fonctionnalité de sécurité vérifie que chaque chunk s'aligne correctement à ces emplacements spécifiques avant d'utiliser un pointeur d'un bin.

Avantages en termes de sécurité

L'application de l'alignement des chunks dans les systèmes 64 bits améliore considérablement la sécurité de Malloc en limitant le placement des faux chunks à seulement 1 adresse sur 16. Cela complique les efforts d'exploitation, surtout dans les scénarios où l'utilisateur a un contrôle limité sur les valeurs d'entrée, rendant les attaques plus complexes et plus difficiles à exécuter avec succès.

  • Attaque Fastbin sur __malloc_hook

Les nouvelles règles d'alignement dans Malloc contrecarrent également une attaque classique impliquant le __malloc_hook. Auparavant, les attaquants pouvaient manipuler les tailles des chunks pour écraser ce pointeur de fonction et obtenir une exécution de code. Désormais, l'exigence stricte d'alignement garantit que de telles manipulations ne sont plus viables, fermant ainsi une voie d'exploitation courante et renforçant la sécurité globale.

Mélange de pointeurs sur fastbins et tcache

Le mélange de pointeurs est une amélioration de sécurité utilisée pour protéger les pointeurs Fd fastbin et tcache dans les opérations de gestion de mémoire. Cette technique aide à prévenir certains types de tactiques d'exploitation de mémoire, en particulier celles qui ne nécessitent pas d'informations de mémoire divulguées ou qui manipulent directement les emplacements mémoire par rapport à des positions connues (écrasements relatifs).

Le cœur de cette technique est une formule d'obscurcissement :

Nouveau_Ptr = (L >> 12) XOR P

  • L est l'emplacement de stockage du pointeur.
  • P est le véritable pointeur Fd fastbin/tcache.

La raison du décalage des bits de l'emplacement de stockage (L) de 12 bits vers la droite avant l'opération XOR est cruciale. Cette manipulation adresse une vulnérabilité inhérente à la nature déterministe des 12 bits de poids faible des adresses mémoire, qui sont généralement prévisibles en raison des contraintes de l'architecture du système. En décalant les bits, la partie prévisible est éliminée de l'équation, améliorant le caractère aléatoire du nouveau pointeur mélangé et protégeant ainsi contre les exploits qui reposent sur la prévisibilité de ces bits.

Ce pointeur mélangé exploite le caractère aléatoire existant fourni par la Randomisation de l'Agencement de l'Espace d'Adresses (ASLR), qui randomise les adresses utilisées par les programmes pour rendre difficile aux attaquants de prédire la disposition mémoire d'un processus.

Démêler le pointeur pour retrouver l'adresse d'origine implique d'utiliser la même opération XOR. Ici, le pointeur mélangé est traité comme P dans la formule, et lorsqu'il est XORé avec l'emplacement de stockage inchangé (L), il révèle le pointeur d'origine. Cette symétrie dans le mélange et le démélange garantit que le système peut encoder et décoder efficacement les pointeurs sans surcharge significative, tout en augmentant considérablement la sécurité contre les attaques qui manipulent les pointeurs mémoire.

Avantages en termes de sécurité

Le mélange de pointeurs vise à empêcher les écrasements partiels et complets de pointeurs dans la gestion du tas, une amélioration significative en termes de sécurité. Cette fonctionnalité impacte les techniques d'exploitation de plusieurs manières :

  1. Prévention des écrasements relatifs de Bye Byte : Auparavant, les attaquants pouvaient modifier une partie d'un pointeur pour rediriger des chunks du tas vers des emplacements différents sans connaître les adresses exactes, une technique évidente dans l'exploit House of Roman sans fuite. Avec le mélange de pointeurs, de tels écrasements relatifs sans fuite de tas nécessitent désormais une force brute, réduisant considérablement leur probabilité de succès.
  2. Difficulté accrue des attaques sur les bins Tcache/Fastbin : Les attaques courantes qui écrasent les pointeurs de fonction (comme __malloc_hook) en manipulant les entrées fastbin ou tcache sont entravées. Par exemple, une attaque pourrait impliquer la fuite d'une adresse LibC, la libération d'un chunk dans le bin tcache, puis l'écrasement du pointeur Fd pour le rediriger vers __malloc_hook pour une exécution de code arbitraire. Avec le mélange de pointeurs, ces pointeurs doivent être correctement mélangés, nécessitant une fuite de tas pour une manipulation précise, élevant ainsi la barrière d'exploitation.
  3. Nécessité de fuites de tas dans des emplacements non-tas : Créer un faux chunk dans des zones non-tas (comme la pile, la section .bss ou PLT/GOT) nécessite désormais également une fuite de tas en raison du besoin de mélange de pointeurs. Cela étend la complexité de l'exploitation de ces zones, similaire à l'exigence de manipulation des adresses LibC.
  4. La fuite d'adresses de tas devient plus difficile : Le mélange de pointeurs restreint l'utilité des pointeurs Fd dans les bins fastbin et tcache en tant que sources de fuites d'adresses de tas. Cependant, les pointeurs dans les bins non triés, petits et grands restent non mélangés, donc toujours utilisables pour la fuite d'adresses. Ce changement pousse les attaquants à explorer ces bins pour des informations exploitables, bien que certaines techniques permettent toujours de démêler les pointeurs avant une fuite, mais avec des contraintes.

Démêler les pointeurs avec une fuite de tas

{% hint style="danger" %} Pour une meilleure explication du processus consultez le post original ici. {% endhint %}

Aperçu de l'algorithme

La formule utilisée pour mélanger et démêler les pointeurs est :

Nouveau_Ptr = (L >> 12) XOR P

L est l'emplacement de stockage et P est le pointeur Fd. Lorsque L est décalé vers la droite de 12 bits, il expose les bits les plus significatifs de P, en raison de la nature de XOR, qui produit 0 lorsque les bits sont XORés avec eux-mêmes.

Étapes clés de l'algorithme :

  1. Fuite initiale des bits les plus significatifs : En XORant le décalage de L avec P, vous obtenez efficacement les 12 bits supérieurs de P car la partie décalée de L sera nulle, laissant les bits correspondants de P inchangés.
  2. Récupération des bits du pointeur : Comme XOR est réversible, connaître le résultat et l'un des opérandes vous permet de calculer l'autre opérande. Cette propriété est utilisée pour déduire l'ensemble complet de bits pour P en XORant successivement des ensembles de bits connus avec des parties du pointeur mélangé.
  3. Démêlage itératif : Le processus est répété, chaque fois en utilisant les bits de P nouvellement découverts de l'étape précédente pour décoder le segment suivant du pointeur mélangé, jusqu'à ce que tous les bits soient récupérés.
  4. Gestion des bits déterministes : Les 12 derniers bits de L sont perdus en raison du décalage, mais ils sont déterministes et peuvent être reconstruits après le processus.

Vous pouvez trouver une implémentation de cet algorithme ici : https://github.com/mdulin2/mangle

Garde de pointeur

La garde de pointeur est une technique de mitigation des exploits utilisée dans glibc pour protéger les pointeurs de fonction stockés, en particulier ceux enregistrés par des appels de bibliothèque tels que atexit(). Cette protection implique de brouiller les pointeurs en les XORant avec un secret stocké dans les données du thread (fs:0x30) et en appliquant une rotation bit à bit. Ce mécanisme vise à empêcher les attaquants de détourner le flux de contrôle en écrivant sur les pointeurs de fonction.

Contourner la Garde de Pointeur avec une fuite

  1. Compréhension des Opérations de Garde de Pointeur : Le brouillage des pointeurs est effectué en utilisant la macro PTR_MANGLE qui XOR le pointeur avec un secret de 64 bits puis effectue une rotation gauche de 0x11 bits. L'opération inverse pour récupérer le pointeur d'origine est gérée par PTR_DEMANGLE.
  2. Stratégie d'Attaque : L'attaque est basée sur une approche de texte clair connu, où l'attaquant doit connaître à la fois la version originale et la version brouillée d'un pointeur pour déduire le secret utilisé pour le brouillage.
  3. Exploitation des Textes Clairs Connus :
  • Identification des Pointeurs de Fonction Fixes : En examinant le code source de glibc ou les tables de pointeurs de fonction initialisées (comme __libc_pthread_functions), un attaquant peut trouver des pointeurs de fonction prévisibles.
  • Calcul du Secret : En utilisant un pointeur de fonction connu tel que __pthread_attr_destroy et sa version brouillée à partir de la table de pointeurs de fonction, le secret peut être calculé en effectuant une rotation inverse (rotation droite) du pointeur brouillé puis en le XORant avec l'adresse de la fonction.
  1. Textes Clairs Alternatifs : L'attaquant peut également expérimenter en brouillant des pointeurs avec des valeurs connues comme 0 ou -1 pour voir si cela produit des motifs identifiables en mémoire, révélant potentiellement le secret lorsque ces motifs sont trouvés dans les vidages mémoire.
  2. Application Pratique : Après avoir calculé le secret, un attaquant peut manipuler les pointeurs de manière contrôlée, contournant essentiellement la protection de la Garde de Pointeur dans une application multi-thread avec la connaissance de l'adresse de base de la libc et la capacité de lire des emplacements mémoire arbitraires.

Références