Rétro-Ingénierie de Programmes
Rappels de Compilation
1/16
Qu'est-ce qu'un programme compilé ?
Compilation = Code Source → (Binaire) Programme
Observation #1
Codez un programme C "Hello world", compilez le et ouvrez le binaire
avec la commande cat.
1 #include <stdio.h>
2 int main(void)
3{
4 printf(”Hello World !\n”);
5 return 0;
6}
2/16
Qu'est-ce qu'un programme compilé ?
3/16
Qu'est-ce qu'un programme compilé ?
Observation #2
Ouvrez le binaire avec xxd.
4/16
Qu'est-ce qu'un programme compilé ?
Observation #2
Ouvrez le binaire avec xxd.
4/16
Regarder correctement le contenu d'un programme
Observation #3
Ouvrez le programme avec la commande strings.
5/16
Regarder correctement le contenu d'un programme
Observation #3
Ouvrez le programme avec la commande strings.
5/16
Regarder correctement le contenu d'un programme
Observation #4
Ouvrez le programme en utilisant les commandes suivantes :
objdump -d -M intel
objdump -s -M intel.
6/16
Cible de ce cours : les programmes Linux
De nombreux formats de fichiers
Windows : PE macOS : Mach-O Linux : ELF
Java : JAR Android : APK PDF
Documentation ELF
man 5 elf
7/16
Structure globale d'un fichier ELF
En-tête En-tête
ELF ELF
segment en-tête 1 Table des
... en-têtes de
segment en-tête n programme
Fichier
section en-tête 1 Table des
ELF
... en-têtes
section en-tête m de section
code
&
données
8/16
En-tête ELF
Informations importantes
Architecture cible du programme : jeu d'instructions utilisées par le
programme (ARM, x86, …)
Point d'entrée (Entry point) : adresse de la première instruction du
programme
Adresses des tables des en-têtes de programme et de section
9/16
En-tête ELF
Informations importantes
Architecture cible du programme : jeu d'instructions utilisées par le
programme (ARM, x86, …)
Point d'entrée (Entry point) : adresse de la première instruction du
programme
Adresses des tables des en-têtes de programme et de section
Observation #5
Ouvrez le programme précédent en utilisant la commande readelf -h et
récupérez les informations de l'en-tête.
9/16
En-tête ELF
Observation #6
Allez au point d'entrée du programme en utilisant objdump -d.
À quoi correspond _start?
10/16
Tables des en-têtes programme & section
Définition : segment & section
Les en-têtes de programme et de section fournissent des méta-données sur
différentes parties du fichier.
Les segments contiennent les informations nécessaires à l'exécution
du programme.
Les sections contiennent les informations nécessaires pour l'édition de lien et la
relocalisation du programme en mémoire.
Observation #7
Ouvrez le programme précédent en utilisant readelf -l et readelf -S.
11/16
Sections de code et de données
Section de code
Le code est généralement placé dans la section .text.
Sections de données
.rodata: données globales en lecture seule, comme par exemple les chaînes
de caractères.
.data: données globales en lecture/écriture comme par exemple les variables
statiques.
.bss: données globales non-initialisées (lecture/écriture).
12/16
Rappel sur la mémoire d'un processus
0xffffffff
Noyau Linux
0xcfffffff
Pile (stack)
Tas (heap)
Espace mémoire
d'un processus Segment BSS
Segment Data
Segment Text
(code)
0x400000
...
13/16
Section init & fini
Initialization et terminaison du programme
La section .init_array, resp. .fini_array, contient la liste des adresses à appeler
avant, resp. après, l'appel de la fonction main.
Observation #8
Ajoutez dans le programme le code ci-dessous.
Observez le nouveau comportement et le contenu de la section
.init_array.
1 void before(void) __attribute__((constructor));
2 void before(void) {printf(”Before the main!\n”);}
14/16
Section des symboles
Définition : symboles
Un symbole est un nom donné à une adresse du programme (e.g. nom de fonction).
La section .symtab contient les adresses des symboles.
Vous pouvez retrouver son contenu en utilisant readelf -s.
Observation #9
Utilisez la commande strip sur le programme et observez le en utilisant
la commande objdump -d.
Que s'est-il passé ?
15/16
Liens avec les bibliothèques
Définition : liaison dynamique
Les adresses des fonctions se trouvent dans la section .got.
Définition : liaison statique
Le code des fonctions est directement inséré dans le fichier ELF.
16/16
Liens avec les bibliothèques
Définition : liaison dynamique
Les adresses des fonctions se trouvent dans la section .got.
Définition : liaison statique
Le code des fonctions est directement inséré dans le fichier ELF.
Observation #10
Où est la fonction puts ? Comment est-elle appelée ?
Observation #11
Recompilez le programme en utilisant l'option -static et observez le code
généré. 16/16