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

Analyser un programme sans l’exécuter

Après cette leçon: Je peux apprendre ce que contient un programme sans le lancer.

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

Un outil dont personne ne connaît l’auteur

La rétro-ingénierie, en anglais reverse engineering, consiste à comprendre comment un programme fonctionne à partir du programme lui-même, sans son code source. Elle sert à trouver une faille, à vérifier ce que fait un outil inconnu ou à comprendre ce que le compilateur a produit.

Une bibliothèque universitaire trouve un petit outil sur l’un de ses serveurs. Plus personne ne sait qui l’a écrit. Avant de le lancer, il faut le lire.

La règle de ce module

Important

Vous lisez uniquement les programmes de votre labo, sur votre propre copie. Vous n’ouvrez jamais le logiciel de quelqu’un d’autre, ni une licence, ni un jeu, ni une protection. Le but est de défendre : trouver et corriger les failles. Rien ici ne vise un vrai système. Entrer sans droit dans un système est un délit.

À la fin de cette leçon

Remarque

Je peux apprendre ce que contient un programme sans le lancer.

Mots-clés

MotCe que ça veut direExemple
Rétro-ingénieriecomprendre un programme à partir du programme seul
Binaireun programme tel que la machine l’exécute, un fichier d’instructionsbibli
ELFle format des programmes sous Linux
Chaîne de caractèresun texte lisible rangé dans un fichierPret : 3 semaines
Désassembleurun outil qui retraduit les instructions en assembleur lisibleobjdump
Assembleurles instructions du processeur écrites en mots courtscall

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

La commande file décrit un binaire

Un programme compilé est un binaire. Sous Linux, son format s’appelle ELF. La commande file lit le début du fichier et dit ce que c’est, sans rien exécuter.

Les trois Runs suivants écrivent un petit programme à nous, bibli.c, le compilent, puis le décrivent. Les réglages de gcc sont ceux du labo : pas d’optimisation, des adresses fixes et pas de protection de pile, pour que la lecture reste simple.

Écrire le programme bibli.c

Commande
printf '%s\n' '#include <stdio.h>' 'int main(void) {' '    puts("Bienvenue a la bibliotheque");' '    puts("Pret : 3 semaines");' '    return 0;' '}' > bibli.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 bibli bibli.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.

Demander ce que contient le fichier

Commande
file bibli

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.

strings sort le texte d’un binaire

Un programme porte son texte avec lui, lisible, que son auteur l’ait voulu ou non. strings affiche chaque suite de caractères lisibles du fichier.

La liste est longue, car un binaire contient aussi des noms de fonctions. Le Run garde donc seulement la ligne qui contient Pret, avec grep. Vous trouvez ce que le programme dit sans l’avoir lancé.

Chercher une phrase dans le fichier

Commande
strings bibli | grep Pret

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 que compiler un programme cache ce qu’il dit. Compiler change la forme du programme, pas son contenu : les textes, les noms d’appels et l’ordre des étapes y sont toujours. Tout ce qu’un programme doit savoir pour fonctionner, un lecteur peut le trouver. Ne cachez donc jamais un secret dans un programme.

La commande objdump montre les instructions

Un désassembleur retraduit les instructions en assembleur : une instruction par ligne, en mots courts. objdump -d est celui de binutils. L’option --disassemble=main ne garde que la fonction main, le point de départ du programme.

Le Run choisit la syntaxe Intel avec -M intel et garde les lignes qui contiennent puts. Il y en a deux, car le programme affiche deux phrases. Chacune est un call, un appel de la fonction puts de la bibliothèque, qui affiche du texte.

Trouver les appels à puts dans main

Commande
objdump -d -M intel bibli --disassemble=main | grep puts

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é : trois outils, trois questions

OutilQuestion poséeRéponse pour bibli
fileQuelle sorte de fichier ?Un exécutable ELF 64 bits, noms conservés
stringsQuel texte contient-il ?Bienvenue a la bibliotheque, Pret : 3 semaines
objdump -dQuelles instructions ?Deux appels à puts dans main

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

Pour aller plus loin

Changez la phrase de puts dans bibli.c, recompilez avec la même commande gcc, puis relancez strings bibli | grep avec un mot de votre nouvelle phrase.

Ensuite, dites en une phrase pourquoi un mot de passe écrit en toutes lettres dans un programme est lisible par n’importe qui. Votre labo contient un dossier revlab : ne le lisez pas encore, la leçon suivante prépare l’outil dont vous aurez besoin.

À 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.