Post

Partie 24 - Annexe n°2 - gérer plusieurs versions de gdb et principales commandes pour déboguer le tas

Annexe n°2 : Gérer plusieurs versions de gdb et principales commandes pour déboguer le tas

Ce tutoriel se déroule en deux étapes :

  1. dans un premier temps, nous allons apprendre à faire cohabiter plusieurs versions de gdb ensemble ;
  2. dans un second temps, nous allons nous intéresser aux principales commandes à connaître lorsque l’on débogue un programme utilisant le tas.

Installation de plusieurs versions de gdb

Versions installées

Pour différentes raisons, il se peut que vous ayez envie d’installer différentes versions de gdb. Par “version” on entend ici “variante” et non pas le numéro de version.

Installer différentes versions permet de passer de l’une vers l’autre afin de profiter des avantages de chacune d’elles. Le principal souci réside dans leur cohabitation pour qu’elles ne s’emmêlent pas les pinceaux.

Voici les différentes versions que nous allons installer :

Par souci de clarté, gdb-gef désignera la version “classique” de gef tandis que gdb-gef++ désignera la version forkée contenant davantage de fonctionnalités.

Comment les installer

J’ai teeellement la flemme de les installer une par une 😩.

Ça tombe bien, nous allons utiliser un script qui fera (presque) tout le sale boulot pour nous !

Pour installer ces différentes versions ensemble, nous allons nous servir du projet gdb-peda-pwndbg-gef.

Comme indiqué dans le tutoriel, lançons les commandes suivantes :

1
2
3
cd ~ && git clone https://github.com/apogiatzis/gdb-peda-pwndbg-gef.git
cd ~/gdb-peda-pwndbg-gef
./install.sh

Voilà ! Les versions suivantes sont désormais installées :

  • gdb-pwndbg ;
  • gdb-peda ;
  • gdb-gef (version classique) ;

Malheureusement, gdb-gef++ n’est pas installé par ce script, il va donc falloir le faire nous-mêmes, vous verrez, ça vaut le coup !

Installation de gdb-gef++

gdb-gef++ est un fork de gdb-gef avec e nombreuses fonctionnalités supplémentaires notamment :

  • débogage du noyau sans symboles : commandes heuristiques pour déboguer le noyau Linux sans vmlinux ;
  • support multi-architectures : compatibilité étendue avec qemu-user pour plusieurs plateformes ;
  • analyse avancée du tas : commandes spécifiques pour examiner le tas ;
  • optimisations diverses : ajouts et améliorations pour une meilleure expérience utilisateur.

Évidemment, il n’est pas forcément meilleur que toutes les autres versions, les goûts et les couleurs, toussa toussa. Néanmoins, pour ce qui est de l’exploitation dans le tas, il reste très intéressant.

Pour l’installation de gdb-gef++, vous pouvez simplement suivre ce qui est indiqué dans la rubrique d’installation en fonction de la version de votre système.

La commande d’installation est lancée avec sudo. Cela facilite peut-être l’installation des paquets nécessaires pour éviter de demander le mot de passe root.

Étant donné que les fichiers d’installation sont placés dans /root, nous allons devoir faire quelques changements et déplacer le fichier d’initialisation :

1
2
3
4
5
mkdir ~/gdb-gef++
sudo cp /root/.gdbinit ~/gdb-gef++
sudo cp -R /root/.gef ~/gdb-gef++
# Donner les droits de l'utilisateur courant
sudo chown -R $(whoami):$(id -gn) ~/gdb-gef++

Une fois ces étapes terminées, ouvrez le fichier ~/.gdbinit et ajoutez le bloc suivant :

1
2
3
4
5
6
define init-gef-bata24
source ~/gdb-gef++/.gef/gef.py
end
document init-gef-bata24
Initializes bata24-GEF (GDB Enhanced Features)
end

Enfin, créez le fichier /usr/bin/gdb-gef++ avec le contenu suivant :

1
2
#!/bin/sh
exec gdb -q -ex init-gef-bata24 "$@"

N’oubliez pas de lui accorder les droits d’exécution : sudo chmod +x /usr/bin/gdb-gef++.

Et voilà, vous pouvez lancer gdb-gef++ !

Principales commandes pour déboguer le tas

Cette section est divisée en deux parties :

  • un résumé des principales commandes ;
  • les détails des commandes, souvent accompagnés d’une image d’illustration.

Vous pouvez rechercher avec Ctrl+F le nom d’une commande sur la page pour trouver les détails de celle-ci un peu plus bas.

Liste des commandes :

  • chunks : affiche les différents blocs alloués et libres présents sur le tas en se focalisant sur leurs métadonnées ;
  • heap chunk 0xaddr : affiche les détails d’un bloc en particulier ;
  • visual-heap : affiche une liste des différents blocs alloués et libres présents sur le tas. Très pratique pour avoir une vue d’ensemble ;
  • arenas : affiche la liste des arènes ;
  • arena : affiche les détails d’une arène en particulier ;
  • top : affiche les détails du bloc du sommet ;
  • bins : affiche le contenu des différentes corbeilles du tas ;
    • tcachebins ;
    • fastbins ;
    • unsortedbin ;
    • smallbins ;
    • largebins.
  • heap bins-simple : affiche une vue d’ensemble des différentes corbeilles ;
  • try-free : simule la libération d’un bloc ;
  • try-malloc : simule l’allocation d’un bloc ;
  • heap find-fake-fast : recherche un bloc de taille n qui pourrait être utilisé pour exploiter la fastbin de même taille.

chunks

💡 Résumé

Affiche les différents blocs alloués et libres présents sur le tas en se focalisant sur leurs métadonnées

📃 Détails

Les différents chunks (blocs) sont affichés avec différents détails :

  • les blocs libres apparaissent en 🟡 ;
  • les informations liées aux différentes métadonnées sont affichées avec différentes couleurs ;
  • le bloc du sommet est visible avec la mention top ;
  • l’adresse base indique l’adresse du début du bloc, contenant les métadonnées, tandis que l’adresse addr indique l’adresse à partir de laquelle commencent les données du bloc (adresse retournée par malloc).

heap chunk 0xaddr

💡 Résumé

Affiche les détails d’un bloc en particulier.

📃 Détails

Cette commande permet d’avoir plus d’informations à propos d’un bloc en particulier.

L’adresse à saisir n’est pas l’adresse base mais addr, celle qui pointe vers les données du bloc.

N’oubliez pas le mot clé heap dans la commande heap chunk 0xaddr pour que celle-ci puisse s’exécuter correctement.

visual-heap

💡 Résumé

Affiche une vue d’ensemble des différents blocs alloués et libres présents sur le tas en se focalisant sur leur contenu.

  • Raccourcis : vis

📃 Détails

Cette commande permet de visualiser rapidement le contenu des différents blocs présents sur le tas qu’ils soient libres ou alloués. Si un bloc appartient à une corbeille en particulier, cette dernière sera affichée.

Cette commande est très utile pour avoir en tête la structure des différents blocs en mémoire.

Astuce gdb : l’option -d permet d’utiliser des couleurs sombres (-dark) afin d’éviter d’avoir mal à la tête 😵‍💫. L’option -n permet d’afficher directement le tas sans utiliser une visualisation “à la less”.

arenas

💡 Résumé

Afficher la liste des arènes.

📃 Détails

Cette commande permet d’afficher la liste des arènes utilisées par le programme.

Pour rappel, un processus peut utiliser plusieurs arènes mémoire, notamment dans les programmes multithreadés.

arena

💡 Résumé

Afficher les détails d’une arène en particulier.

📃 Détails

Cette commande permet d’afficher pas mal d’informations sur une arène :

  • les adresses des différentes corbeilles (toutes les corbeilles sauf le tcache) ;
  • l’adresse du bloc du sommet ;
  • plusieurs variables intervenant dans le fonctionnement interne de free, malloc et autres fonctions de gestion de mémoire.

Astuce gdb : par défaut, c’est l’arène principale qui est affichée. Vous pouvez spécifier une autre arène avec l’option -a. Par exemple : arena -a 0x7ffff0000030.

top

💡 Résumé

Afficher les détails du bloc du sommet.

📃 Détails

Cette commande affiche plusieurs informations concernant le bloc du sommet.

Astuce gdb : par défaut, le bloc du sommet affiché est celui de l’arène principale. Vous pouvez spécifier une autre arène avec l’option -a. Par exemple : top -a 0x7ffff7e1ac80.

bins

💡 Résumé

Afficher le contenu des différentes corbeilles du tas.

📃 Détails

Si vous cherchez une commande permettant d’avoir une vue panoramique sur les différentes corbeilles du tas, c’est la commande qu’il vous faut !

Les différents blocs libres sont listés avec les informations concernant leurs métadonnées. De plus, dans le cas où une corruption de liste chaînée, par exemple, a eu lieu, cette commande indiquera la présence d’une corruption.

Astuce gdb : pour avoir la liste de toutes les corbeilles, même celles qui sont vides, vous pouvez utiliser l’option -v.

Vous pouvez restreindre les informations affichées à une corbeille en particulier avec les commandes suivantes :

  • tcachebins ;
  • fastbins ;
  • unsortedbin ;
  • smallbins ;
  • largebins.

heap bins-simple

💡 Résumé

Afficher une vue d’ensemble des différentes corbeilles.

📃 Détails

Il s’agit d’une version plus concise de la commande bins.

N’oubliez pas le mot clé heap dans la commande heap bins-simple pour que celle-ci puisse s’exécuter correctement.

try-free

💡 Résumé

Simuler la libération d’un bloc.

📃 Détails

Cette commande est très utile en pwn car elle permet de simuler la libération d’un bloc. Cela permet de savoir à l’avance si appeler free sur ce bloc va générer une erreur ou non. De cette manière, vous pouvez savoir si une libération de bloc va passer toutes les vérifications.

Un point essentiel de cette commande est que la libération est simulée, donc ne vous inquiétez pas, free ne sera pas réellement appelée.

L’adresse à donner en paramètre de cette commande est l’adresse qui pointe vers les données du bloc et non ses métadonnées.

try-malloc

💡 Résumé

Simuler l’allocation d’un bloc.

📃 Détails

De la même manière que try-free simule la libération d’un bloc, try-malloc simule l’allocation d’un bloc pour une taille donnée. La fonction retourne l’adresse qui aurait été retournée si malloc avait réellement été appelé avec cette taille en paramètre.

Cela est pratique pour voir si votre exploit est propre et fonctionnel. Par exemple, dans le cas d’une tcache attack ou fastbin attack, si vous ne gérez pas correctement la liste chaînée, il se peut que la prochaine allocation échoue, chose que vous devriez observer si vous lancez try-malloc.

heap find-fake-fast

💡 Résumé

Rechercher un bloc de taille n qui pourrait être utilisé pour exploiter la fastbin de même taille.

📃 Détails

Étant donné que depuis la version 2.3.4 de la glibc, la taille des blocs utilisés est vérifiée lorsqu’un bloc de taille n est alloué en utilisant la fastbin de même taille, nous ne pouvons plus utiliser n’importe quel bloc pour réaliser une fastbin attack, par exemple.

Cette commande permet ainsi de pouvoir trouver en mémoire de potentiels blocs de taille n que l’on pourrait utiliser pour exploiter la liste chaînée de la fastbin.

N’oubliez pas le mot clé heap dans la commande heap find-fake-fast pour que celle-ci puisse s’exécuter correctement.

This post is licensed under CC BY 4.0 by the author.