Plus facile à lire avec un fond crème, une teinte, plus de contraste ou un texte plus grand ? Choisissez vos couleurs et votre texte, une fois pour toutes les pages.

Leçon gratuite

Arrêter un programme avec gdb

Après cette leçon: Je peux arrêter un programme avec gdb et lire les textes qu’il compare.

Leçon de 60 min5 commandesLab de rétro-ingénierie : lire des programmes avec gdb, radare2, strace et ltrace dans une VM

Lire le code attendu pendant la comparaison

Un débogueur est un outil qui lance un programme, l’arrête où vous le demandez et vous montre sa mémoire. Sous Linux, le plus répandu est gdb, le débogueur du projet GNU.

Un programme salle compare le code que l’on tape à celui qu’il attend. Plutôt que de deviner, on l’arrête au moment de la comparaison et on lit les deux textes. Rappel : seuls les programmes de votre labo se lisent ici.

À la fin de cette leçon

Remarque

Je peux arrêter un programme avec gdb et lire les textes qu’il compare.

Mots-clés

MotCe que ça veut direExemple
Débogueurun outil qui lance un programme et le contrôle pas à pasgdb
Point d’arrêtun endroit où le débogueur arrête le programmebreak strcmp
Argumentune valeur donnée à une fonction quand on l’appelle
rdi et rsiles registres du premier et du second argument d’une fonction sur x86-64
Adressela place d’une donnée dans la mémoire0x402008

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

Un programme qui compare un texte

Les deux Runs suivants écrivent salle.c et le compilent avec les réglages du labo. Le programme prend un code sur la ligne de commande, le compare avec strcmp et répond « Salle ouverte. » ou « Salle fermee. ».

strcmp est une fonction de la bibliothèque : elle compare deux textes et rend 0 s’ils sont égaux.

Écrire le programme salle.c

Commande
printf '%s\n' '#include <stdio.h>' '#include <string.h>' 'int main(int argc, char **argv) {' '    if (argc != 2) { puts("usage: salle CODE"); return 2; }' '    if (strcmp(argv[1], "B12-nord") == 0) { puts("Salle ouverte."); return 0; }' '    puts("Salle fermee.");' '    return 1;' '}' > salle.c

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Le compiler avec les réglages du labo

Commande
gcc -O0 -no-pie -fno-stack-protector -o salle salle.c

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Essayer un code au hasard

Commande
./salle essai

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Un point d’arrêt stoppe le programme

Dans gdb, break strcmp pose un point d’arrêt sur strcmp, run lance le programme et continue le relance après un arrêt. Quand l’arrêt a lieu, le programme est suspendu juste à l’entrée de la fonction : ses arguments sont déjà prêts.

Le chargeur de bibliothèques peut aussi appeler strcmp avant main. On arrête donc le programme sur main d’abord, puis on pose le point d’arrêt sur strcmp.

x/s lit un texte à une adresse

Sur x86-64, le premier argument d’une fonction arrive dans le registre rdi et le second dans rsi. Ici, ce sont les adresses des deux textes comparés.

x/s $rdi veut dire : examine (x) comme un texte (s) l’adresse qui est dans rdi. Le Run lance tout cela d’un coup avec -batch, puis garde avec grep seulement les deux lignes lues en mémoire.

Lire les deux textes que strcmp compare

Commande
gdb -batch -ex 'set debuginfod enabled off' -ex 'set environment LD_BIND_NOW=1' -ex 'break main' -ex 'run' -ex 'break strcmp' -ex 'continue' -ex 'x/s $rdi' -ex 'x/s $rsi' --args ./salle essai 2>&1 | grep -E '^0x[0-9a-f]+:'

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Exemple travaillé : ce que fait chaque option -ex

OptionCe qu’elle faitPourquoi à cet endroit
set debuginfod enabled offRefuse le téléchargement d’informationsPas de question posée pendant le Run
set environment LD_BIND_NOW=1Résout tous les appels dès le départstrcmp existe quand on pose l’arrêt
break main puis runLance et s’arrête à mainAprès le chargeur, avant la comparaison
break strcmp puis continueS’arrête à l’entrée de strcmpLes deux textes sont prêts
x/s $rdi puis x/s $rsiLit le premier puis le second texteLe texte tapé et le texte attendu

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

bt montre qui a appelé strcmp

Quand le programme est arrêté, bt 2 affiche les deux dernières fonctions en cours : la fonction où l’on est, puis celle qui l’a appelée. C’est une pile d’appels.

Le Run garde la ligne qui commence par #1. Elle doit finir par in main () : c’est main qui a appelé strcmp.

Voir qui a appelé strcmp

Commande
gdb -batch -ex 'set debuginfod enabled off' -ex 'set environment LD_BIND_NOW=1' -ex 'break main' -ex 'run' -ex 'break strcmp' -ex 'continue' -ex 'bt 2' --args ./salle essai 2>&1 | grep '^#1'

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Erreur fréquente

Attention

Beaucoup de gens pensent qu’un point d’arrêt sur strcmp s’arrête toujours dans leur programme. Il s’arrête à chaque appel de strcmp, même celui d’une autre partie du système. Posez-le après main, puis vérifiez avec bt que l’appelant est bien votre programme.

Pour aller plus loin

Relancez le Run avec ./salle B12-nord à la place de ./salle essai. Les deux textes lus sont-ils les mêmes ? Que répond le programme ?

Dites ensuite pourquoi l’arrêt sur strcmp donne la réponse quel que soit le texte tapé, alors que deviner à la main prend un temps énorme.

À propos de ce labo et de sa source: Lab de rétro-ingénierie : lire des programmes avec gdb, radare2, strace et ltrace dans une VM

Vous enseignez à une classe ? Proposez ce module à vos étudiants avec un guide de l'enseignant, des devoirs corrigés et un laboratoire pour chaque étudiant.