SlideShare une entreprise Scribd logo
Mise en place d'un système de
tag sur les objets ELF
Thierry GAYET
Lors de l'inspection d'un objet ELF (binaire, librairie dynamiques,
… ), il peut être intéressant de connaître les éléments qui sont
entrés dans la phase de génération (version du noyau, version du
compilateur, version des binutils, tag SVN ou GIT, … ). Ces éléments
peuvent servir à remonter à l'origine d'un bug et donc aider aux
investigations.
1. Les objets binaire ELF sous Linux
ELF (Executable and Linkable Format, format exécutable et liable ; anciennement Executable and
Linking Format) est un format de fichier binaire utilisé pour l'enregistrement de code compilé
(objets, exécutables, bibliothèques de fonctions).
Il a été développé par l’USL (Unix System Laboratories) pour remplacer les anciens formats a.out
et COFF qui avaient atteint leurs limites. Aujourd'hui, ce format est utilisé dans la plupart des
systèmes d'exploitation de type Unix (GNU/Linux, Solaris, IRIX, System V, BSD), à l'exception de
Mac OS X.
Chaque fichier ELF est constitué d'une en-tête ELF, suivi par les données du fichier. Les données
de fichier peuvent inclure:
• Un tableau d'en-tête de programme, décrivant zéro ou plusieurs segments ;
• Un tableau d'en-tête de section, décrivant zéro ou plusieurs sections ;
• Les données référencées par des entrées dans la table d'en-tête du programme ou le
tableau d'en-tête de la section ;
Les segments contiennent des informations qui sont nécessaires à l'exécution d'exécution du
fichier, tandis que les sections contiennent des données importantes pour la liaison et la
relocalisation. Chaque octet dans le fichier entier est pris par une section à la fois, mais il peut y
avoir octets orphelins qui ne sont pas couverts par une section. Dans le cas normal d'un
exécutable UNIX une ou plusieurs sections sont enfermés dans un segment.
Architecture du format ELF.
2. Quelques commandes pour jouer avec ELF
Qu'il soit ELF32 (x86 32 bits) ou ELF64 (x86 - 64 bits), la commande file donne la carte d'identité
d'un objet sous linux :
$ file ./myBinElf
myBinElf: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs),
for GNU/Linux 2.6.24, BuildID[sha1]=0x8070f79e36c1d0b20889559eaa5a3c91efaabb8c, not stripped
$ file /lib/libcryptsetup.so.4.0.0
libcryptsetup.so.4.0.0: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked,
BuildID[sha1]=0x134928597054b3e93f142dd94c2179ff56e0fc55, stripped
ReadELF est un programme utile pour extraire les éléments de l'entête ELF :
$ readelf -h ./myBinElf
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x8048310
Start of program headers: 52 (bytes into file)
Start of section headers: 4400 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 8
Size of section headers: 40 (bytes)
Number of section headers: 29
Section header string table index: 26
Quelques explications sont les bienvenue :
Nous pouvons remarques quelques données au début :
7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Ces quatre premier octets représentent le nombre magique permettant d'identifier le type du
fichier :
7f 45 4c 46
Les octets suivant représentent des meta-données du fichier comme la version, la taille, le type
d'encodage des données :
Data: 2's complement, little endian
Type: EXEC (Executable file)
Cela spécifie si le ELF est exécutable. Un fichier ELF peur être relogeable, un objet partage, un
core file ou un fichier spécifique à un processeur. Par exemple, un driver dynamique est
relogeable de part son point d'entrée.
Entry point address: 0x8048310
Le point d'entrée de l'exécutable est _start().
Readelf permet également de lister des sections :
$ readelf -S ./myBinElf
There are 30 section headers, starting at offset 0x1148:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 08048154 000154 000013 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 08048168 000168 000020 00 A 0 0 4
[ 3] .note.gnu.build-i NOTE 08048188 000188 000024 00 A 0 0 4
[ 4] .gnu.hash GNU_HASH 080481ac 0001ac 000020 04 A 5 0 4
[ 5] .dynsym DYNSYM 080481cc 0001cc 000080 10 A 6 1 4
[ 6] .dynstr STRTAB 0804824c 00024c 000077 00 A 0 0 1
[ 7] .gnu.version VERSYM 080482c4 0002c4 000010 02 A 5 0 2
[ 8] .gnu.version_r VERNEED 080482d4 0002d4 000030 00 A 6 1 4
[ 9] .rel.dyn REL 08048304 000304 000008 08 A 5 0 4
[10] .rel.plt REL 0804830c 00030c 000030 08 A 5 12 4
[11] .init PROGBITS 0804833c 00033c 00002e 00 AX 0 0 4
[12] .plt PROGBITS 08048370 000370 000070 04 AX 0 0 16
[13] .text PROGBITS 080483e0 0003e0 00020c 00 AX 0 0 16
[14] .fini PROGBITS 080485ec 0005ec 00001a 00 AX 0 0 4
[15] .rodata PROGBITS 08048608 000608 000042 00 A 0 0 4
[16] .eh_frame_hdr PROGBITS 0804864c 00064c 000044 00 A 0 0 4
[17] .eh_frame PROGBITS 08048690 000690 000104 00 A 0 0 4
[18] .ctors PROGBITS 08049f14 000f14 000008 00 WA 0 0 4
[19] .dtors PROGBITS 08049f1c 000f1c 000008 00 WA 0 0 4
[20] .jcr PROGBITS 08049f24 000f24 000004 00 WA 0 0 4
[21] .dynamic DYNAMIC 08049f28 000f28 0000c8 08 WA 6 0 4
[22] .got PROGBITS 08049ff0 000ff0 000004 04 WA 0 0 4
[23] .got.plt PROGBITS 08049ff4 000ff4 000024 04 WA 0 0 4
[24] .data PROGBITS 0804a018 001018 000008 00 WA 0 0 4
[25] .bss NOBITS 0804a020 001020 000008 00 WA 0 0 4
[26] .comment PROGBITS 00000000 001020 00002a 01 MS 0 0 1
[27] .shstrtab STRTAB 00000000 00104a 0000fc 00 0 0 1
[28] .symtab SYMTAB 00000000 0015f8 000460 10 29 45 4
[29] .strtab STRTAB 00000000 001a58 000259 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
Ainsi que les segments :
$ readelf --segments ./myBinElf
Elf file type is EXEC (Executable file)
Entry point 0x80483e0
There are 9 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4
INTERP 0x000154 0x08048154 0x08048154 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD 0x000000 0x08048000 0x08048000 0x00794 0x00794 R E 0x1000
LOAD 0x000f14 0x08049f14 0x08049f14 0x0010c 0x00114 RW 0x1000
DYNAMIC 0x000f28 0x08049f28 0x08049f28 0x000c8 0x000c8 RW 0x4
NOTE 0x000168 0x08048168 0x08048168 0x00044 0x00044 R 0x4
GNU_EH_FRAME 0x00064c 0x0804864c 0x0804864c 0x00044 0x00044 R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4
GNU_RELRO 0x000f14 0x08049f14 0x08049f14 0x000ec 0x000ec R 0x1
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r
.rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .ctors .dtors .jcr .dynamic .got .got.plt .data .bss
04 .dynamic
05 .note.ABI-tag .note.gnu.build-id
06 .eh_frame_hdr
07
08 .ctors .dtors .jcr .dynamic .got
3. Le système de TAG :
En s'appuyant sur ce format dont tous les objets binaires (programmes, librairies dynamiques, …)
utilisent, il est possible de rajouter une section personnalisée à ce format dynamique.
Il est donc possible de rajouter dans cette section un ensemble de données cohérent qui
résumerait la chaîne de génération d'un binaire. En effet, il peut cela peut être utile de façon a
reproduire un bug dans le but de le résoudre.
Le données à inclure sont libre, mais pourrait être :
• version de la toolchain (gcc, ld, … ) ;
• version de la glibc ;
• version des sources du noyau ;
• version des binutils (ar, strip, ranlib, … ) ;
• date et heure du build ;
• tag du système de gestion de versions utilisé (SVN, Mercurial, Git, … ) ;
• ...
Cela pourrait être résumé avec un identifiant du build si sauvegarde de la carte identité des build
en base de données ;
4. Génération et pose d'un TAG avec objcopy
Un tag est simplement un fichier texte dans lequel on écrit des données importantes. Il peut donc
être personnalisé à souhait :
$ touch ./myTag
$ echo "TOOLCHAIN = " $(TOOLCHAIN_VERSION) GCC v$ (GCC_VERSION) >> ./myTag
$ echo "TARGET = " $(TARGET_ID) >> ./myTag
$ echo "BUILT = " $(shell date +"%Y/%m/%d %H:%M: %S") on $(BUILD_HOST) $(BUILD_KIND)
>> ./myTag
Pour faire simple, nous allons utiliser un tag avec juste une salutation :
echo "bonjour Thierry" > ./mytag
Avant d'appliquer un TAG dans les sections du header ELF, il peut être nécessaire par sécurité de
supprimer un ancien TAG similaire :
$ objcopy --remove-section MYTAG ./myBinElf
Ensuite, nous pouvons ajouter notre TAG au binaire :
$ objcopy --add-section MYTAG=./myTag --set-section-flags MYTAG=contents ./myBinElf
On peut vérifier que le tag est bien présent :
$ readelf -all ./myBinElf | grep MYTAG
[27] MYTAG PROGBITS 00000000 00104a 000010 00 W 0 0 1
5. Extraction du TAG avec objcopy
Maintenant nous avons besoin d'extraire ce TAG pour pouvoir connaître sont contenu. Nous allons
utilise l'outil objcopy et dd pour ce faire. De façon, à simplifier l'extraction, je propose un petit script
shell « extractTAG.sh » :
IN_F=$1
OUT_F=$2
SECTION=$3
objdump -h $IN_F |
grep $SECTION |
awk '{print "dd if='$IN_F' of='$OUT_F' bs=1 count=$[0x" $3 "] skip=$[0x" $6 "]"}' |
bash
Une fois le script rendu exécutable avec un chmod +x, son utilisant se fait de la façon suivante :
./extractTAG.sh ./myBinElf MYTAG_dump.txt MYTAG
16+0 enregistrements lus
16+0 enregistrements écrits
16 octets (16 B) copiés, 4,2532e-05 s, 376 kB/s
$ cat ./MYTAG_dump.txt
bonjour Thierry
Nous retrouvons donc bien notre salutation d'origine.
6. Conclusion
Nous avons vu la façon de poser un tag dans dans une nouvelle section ELF d'un binaire. De même,
nous avons également vu comme procédé à son extraction.
Généralisé, à un système de build, cela pourrait permettre de suivre la génération d'un binaire et
aussi de remonté aux contexte de génération en se basant sur les données inclus dans cette section.
7. Liens
• http://manpagesfr.free.fr/man/man5/elf.5.html
• http://pwet.fr/man/linux/formats/elf
• http://elftoolchain.sourceforge.net/for-review/libelf-by-example-20100111.pdf
• http://developers.sun.com/solaris/articles/elf.html
• http://docs.oracle.com/cd/E19082-01/819-0690/chapter6-43405/index.html
• http://www.skyfree.org/linux/references/ELF_Format.pdf
• http://www.linuxjournal.com/article/1059
• http://unixhelp.ed.ac.uk/CGI/man-cgi?objcopy+1
• http://mylinuxbook.com/readelf-command/
• http://www.bottomupcs.com/elf.html
• http://www.ensta-paristech.fr/~diam/dev/online/elf-howto-1996_07_14/ELF-
HOWTO.html#toc
• http://fr.slideshare.net/varunmahajan06/gnu-linux-programstructure
• http://linuxgazette.berlios.de/issue84/hawk.html
• http://asm.sourceforge.net/articles/startup.html
• http://stackoverflow.com/questions/13908276/loading-elf-file-in-c-in-user-space
• http://linux.die.net/man/1/file
• http://linux.die.net/man/1/readelf
• http://linux.die.net/man/1/objdump

Contenu connexe

PPTX
Formation python
Thierry Gayet
 
PPTX
Php1
Kadar Abdillahi
 
PPT
Structure de données en PHP
Jean-Marie Renouard
 
PDF
Bases de php - partie 2
Régis Lutter
 
PDF
Les structures de données PHP5
Jean-Marie Renouard
 
PDF
Python avancé : Lecture et écriture de fichiers
ECAM Brussels Engineering School
 
PPT
.php1 : les fondamentaux du PHP
Abdoulaye Dieng
 
PDF
Chapitre ii architecture interne des processeurs
Sana Aroussi
 
Formation python
Thierry Gayet
 
Structure de données en PHP
Jean-Marie Renouard
 
Bases de php - partie 2
Régis Lutter
 
Les structures de données PHP5
Jean-Marie Renouard
 
Python avancé : Lecture et écriture de fichiers
ECAM Brussels Engineering School
 
.php1 : les fondamentaux du PHP
Abdoulaye Dieng
 
Chapitre ii architecture interne des processeurs
Sana Aroussi
 

En vedette (20)

PPT
Les Metadonnees Exif
carolineparre
 
ODP
Test-Bcdi32009-TMP
afruch
 
PDF
Modelos espiral
alextein
 
PPT
Revitalisation des jeux traditionnels (CIOFF)
heritageorganisations.eu
 
PPT
A VENDRE MAISON ANCIENNE AU COEUR DU VEXIN
Marc Foujols
 
PPTX
Videography "Advertising"
Vilicha Bella
 
DOC
Tice Med09 Projet Sti
Pierre Bénech
 
PPS
Hq historique-de-l'enseignement dd
catavrio
 
PPS
La mouche
catavrio
 
PDF
Communiqué De Presse 20e Festival Du Livre De Mouans Sartoux
brichardcaroline
 
PPS
RéDacteur En Chef Bekal Imane
gawronski
 
PPS
Famille Griffinlsa Cris Morgado
Departamento Francés IES Romero Esteo
 
PPT
Les outils du web 2.0 pour la recherche scientifique - Master 1 SACIM
Magalie Le Gall
 
PPTX
Álbum de fotografía: El teatro
inicial4jfk
 
ODP
Formation ADELHA : initiation à 10 outils Internet pour mieux coopérer
Nicolas Geiger
 
PPS
La peine de_mort_ja1
catavrio
 
PPT
Cv Interactif Et Blog2
Mathieu fabre
 
ODT
Anatomie d'une des particularité de la libc
Thierry Gayet
 
PPTX
Pâques
mingxu
 
Les Metadonnees Exif
carolineparre
 
Test-Bcdi32009-TMP
afruch
 
Modelos espiral
alextein
 
Revitalisation des jeux traditionnels (CIOFF)
heritageorganisations.eu
 
A VENDRE MAISON ANCIENNE AU COEUR DU VEXIN
Marc Foujols
 
Videography "Advertising"
Vilicha Bella
 
Tice Med09 Projet Sti
Pierre Bénech
 
Hq historique-de-l'enseignement dd
catavrio
 
La mouche
catavrio
 
Communiqué De Presse 20e Festival Du Livre De Mouans Sartoux
brichardcaroline
 
RéDacteur En Chef Bekal Imane
gawronski
 
Famille Griffinlsa Cris Morgado
Departamento Francés IES Romero Esteo
 
Les outils du web 2.0 pour la recherche scientifique - Master 1 SACIM
Magalie Le Gall
 
Álbum de fotografía: El teatro
inicial4jfk
 
Formation ADELHA : initiation à 10 outils Internet pour mieux coopérer
Nicolas Geiger
 
La peine de_mort_ja1
catavrio
 
Cv Interactif Et Blog2
Mathieu fabre
 
Anatomie d'une des particularité de la libc
Thierry Gayet
 
Pâques
mingxu
 
Publicité

Similaire à Utilisation d'un système de tag des objets elf (13)

PDF
de l'art binaire: des PEs explosifs fait main
Ange Albertini
 
ODT
A la découverte de redo
Thierry Gayet
 
PDF
cm0hghhjhhu juijjjjj hhhhhggg juu6_x86.pdf
Bergelin
 
PDF
embedded_linux_ENIT_Tunisie_2023_2AGE.pdf
SamirSakrani1
 
PPTX
C2 - Langage C - ISIMA 1 - Deuxieme partie
Loic Yon
 
PPTX
SdE 3 - Systemes de fichiers
Alexandru Radovici
 
PDF
2004-ASR-cours administration -linux.pdf
mohammed merchichi
 
PPTX
Autour du Reverse Engineering des Malwares
Aymen Bentijani
 
PDF
Présentation Unix/Linux (mise à jour 2016)
Emmanuel Florac
 
PDF
Présentation unix linux
Emmanuel Florac
 
PDF
Dans les entrailles du langage C
Stephanie Ouillon
 
PDF
coursjdipmdkpc,EdqkjcÊdpofpofjpoeMJOQDLo.pdf
YdydiaKPLOYA
 
PPT
Virtualiastion des systèmes d'exploitations
SGHIOUAR abdelfettah
 
de l'art binaire: des PEs explosifs fait main
Ange Albertini
 
A la découverte de redo
Thierry Gayet
 
cm0hghhjhhu juijjjjj hhhhhggg juu6_x86.pdf
Bergelin
 
embedded_linux_ENIT_Tunisie_2023_2AGE.pdf
SamirSakrani1
 
C2 - Langage C - ISIMA 1 - Deuxieme partie
Loic Yon
 
SdE 3 - Systemes de fichiers
Alexandru Radovici
 
2004-ASR-cours administration -linux.pdf
mohammed merchichi
 
Autour du Reverse Engineering des Malwares
Aymen Bentijani
 
Présentation Unix/Linux (mise à jour 2016)
Emmanuel Florac
 
Présentation unix linux
Emmanuel Florac
 
Dans les entrailles du langage C
Stephanie Ouillon
 
coursjdipmdkpc,EdqkjcÊdpofpofjpoeMJOQDLo.pdf
YdydiaKPLOYA
 
Virtualiastion des systèmes d'exploitations
SGHIOUAR abdelfettah
 
Publicité

Dernier (7)

PDF
Présentation UCOPIA et ses fonctionnalités
ZakariaRAHOUI2
 
PDF
CHAPITRE 5_Déplacement des données DBA.pdf
houcemswissi1
 
PDF
Circuit Breaker pattern avec Resilience4j
SOUFIANE MOUHTARAM
 
PDF
Google Remote Procedure Call Web Service
SOUFIANE MOUHTARAM
 
PDF
linkyfi presentation et ses fonctionnalité
ZakariaRAHOUI2
 
PDF
CHAPITRE1_Architecture du Serveur Oracle.pdf
houcemswissi1
 
PDF
Généralités sur balisage (Tagging) en git
SOUFIANE MOUHTARAM
 
Présentation UCOPIA et ses fonctionnalités
ZakariaRAHOUI2
 
CHAPITRE 5_Déplacement des données DBA.pdf
houcemswissi1
 
Circuit Breaker pattern avec Resilience4j
SOUFIANE MOUHTARAM
 
Google Remote Procedure Call Web Service
SOUFIANE MOUHTARAM
 
linkyfi presentation et ses fonctionnalité
ZakariaRAHOUI2
 
CHAPITRE1_Architecture du Serveur Oracle.pdf
houcemswissi1
 
Généralités sur balisage (Tagging) en git
SOUFIANE MOUHTARAM
 

Utilisation d'un système de tag des objets elf

  • 1. Mise en place d'un système de tag sur les objets ELF Thierry GAYET Lors de l'inspection d'un objet ELF (binaire, librairie dynamiques, … ), il peut être intéressant de connaître les éléments qui sont entrés dans la phase de génération (version du noyau, version du compilateur, version des binutils, tag SVN ou GIT, … ). Ces éléments peuvent servir à remonter à l'origine d'un bug et donc aider aux investigations. 1. Les objets binaire ELF sous Linux ELF (Executable and Linkable Format, format exécutable et liable ; anciennement Executable and Linking Format) est un format de fichier binaire utilisé pour l'enregistrement de code compilé (objets, exécutables, bibliothèques de fonctions). Il a été développé par l’USL (Unix System Laboratories) pour remplacer les anciens formats a.out et COFF qui avaient atteint leurs limites. Aujourd'hui, ce format est utilisé dans la plupart des systèmes d'exploitation de type Unix (GNU/Linux, Solaris, IRIX, System V, BSD), à l'exception de Mac OS X. Chaque fichier ELF est constitué d'une en-tête ELF, suivi par les données du fichier. Les données de fichier peuvent inclure: • Un tableau d'en-tête de programme, décrivant zéro ou plusieurs segments ; • Un tableau d'en-tête de section, décrivant zéro ou plusieurs sections ; • Les données référencées par des entrées dans la table d'en-tête du programme ou le tableau d'en-tête de la section ; Les segments contiennent des informations qui sont nécessaires à l'exécution d'exécution du fichier, tandis que les sections contiennent des données importantes pour la liaison et la relocalisation. Chaque octet dans le fichier entier est pris par une section à la fois, mais il peut y avoir octets orphelins qui ne sont pas couverts par une section. Dans le cas normal d'un exécutable UNIX une ou plusieurs sections sont enfermés dans un segment.
  • 2. Architecture du format ELF. 2. Quelques commandes pour jouer avec ELF Qu'il soit ELF32 (x86 32 bits) ou ELF64 (x86 - 64 bits), la commande file donne la carte d'identité d'un objet sous linux : $ file ./myBinElf myBinElf: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x8070f79e36c1d0b20889559eaa5a3c91efaabb8c, not stripped $ file /lib/libcryptsetup.so.4.0.0 libcryptsetup.so.4.0.0: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, BuildID[sha1]=0x134928597054b3e93f142dd94c2179ff56e0fc55, stripped ReadELF est un programme utile pour extraire les éléments de l'entête ELF : $ readelf -h ./myBinElf ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: Intel 80386 Version: 0x1 Entry point address: 0x8048310 Start of program headers: 52 (bytes into file) Start of section headers: 4400 (bytes into file) Flags: 0x0 Size of this header: 52 (bytes)
  • 3. Size of program headers: 32 (bytes) Number of program headers: 8 Size of section headers: 40 (bytes) Number of section headers: 29 Section header string table index: 26 Quelques explications sont les bienvenue : Nous pouvons remarques quelques données au début : 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Ces quatre premier octets représentent le nombre magique permettant d'identifier le type du fichier : 7f 45 4c 46 Les octets suivant représentent des meta-données du fichier comme la version, la taille, le type d'encodage des données : Data: 2's complement, little endian Type: EXEC (Executable file) Cela spécifie si le ELF est exécutable. Un fichier ELF peur être relogeable, un objet partage, un core file ou un fichier spécifique à un processeur. Par exemple, un driver dynamique est relogeable de part son point d'entrée. Entry point address: 0x8048310 Le point d'entrée de l'exécutable est _start(). Readelf permet également de lister des sections : $ readelf -S ./myBinElf There are 30 section headers, starting at offset 0x1148: Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .interp PROGBITS 08048154 000154 000013 00 A 0 0 1 [ 2] .note.ABI-tag NOTE 08048168 000168 000020 00 A 0 0 4 [ 3] .note.gnu.build-i NOTE 08048188 000188 000024 00 A 0 0 4 [ 4] .gnu.hash GNU_HASH 080481ac 0001ac 000020 04 A 5 0 4 [ 5] .dynsym DYNSYM 080481cc 0001cc 000080 10 A 6 1 4 [ 6] .dynstr STRTAB 0804824c 00024c 000077 00 A 0 0 1 [ 7] .gnu.version VERSYM 080482c4 0002c4 000010 02 A 5 0 2 [ 8] .gnu.version_r VERNEED 080482d4 0002d4 000030 00 A 6 1 4 [ 9] .rel.dyn REL 08048304 000304 000008 08 A 5 0 4 [10] .rel.plt REL 0804830c 00030c 000030 08 A 5 12 4 [11] .init PROGBITS 0804833c 00033c 00002e 00 AX 0 0 4 [12] .plt PROGBITS 08048370 000370 000070 04 AX 0 0 16 [13] .text PROGBITS 080483e0 0003e0 00020c 00 AX 0 0 16 [14] .fini PROGBITS 080485ec 0005ec 00001a 00 AX 0 0 4 [15] .rodata PROGBITS 08048608 000608 000042 00 A 0 0 4
  • 4. [16] .eh_frame_hdr PROGBITS 0804864c 00064c 000044 00 A 0 0 4 [17] .eh_frame PROGBITS 08048690 000690 000104 00 A 0 0 4 [18] .ctors PROGBITS 08049f14 000f14 000008 00 WA 0 0 4 [19] .dtors PROGBITS 08049f1c 000f1c 000008 00 WA 0 0 4 [20] .jcr PROGBITS 08049f24 000f24 000004 00 WA 0 0 4 [21] .dynamic DYNAMIC 08049f28 000f28 0000c8 08 WA 6 0 4 [22] .got PROGBITS 08049ff0 000ff0 000004 04 WA 0 0 4 [23] .got.plt PROGBITS 08049ff4 000ff4 000024 04 WA 0 0 4 [24] .data PROGBITS 0804a018 001018 000008 00 WA 0 0 4 [25] .bss NOBITS 0804a020 001020 000008 00 WA 0 0 4 [26] .comment PROGBITS 00000000 001020 00002a 01 MS 0 0 1 [27] .shstrtab STRTAB 00000000 00104a 0000fc 00 0 0 1 [28] .symtab SYMTAB 00000000 0015f8 000460 10 29 45 4 [29] .strtab STRTAB 00000000 001a58 000259 00 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings) I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific) Ainsi que les segments : $ readelf --segments ./myBinElf Elf file type is EXEC (Executable file) Entry point 0x80483e0 There are 9 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4 INTERP 0x000154 0x08048154 0x08048154 0x00013 0x00013 R 0x1 [Requesting program interpreter: /lib/ld-linux.so.2] LOAD 0x000000 0x08048000 0x08048000 0x00794 0x00794 R E 0x1000 LOAD 0x000f14 0x08049f14 0x08049f14 0x0010c 0x00114 RW 0x1000 DYNAMIC 0x000f28 0x08049f28 0x08049f28 0x000c8 0x000c8 RW 0x4 NOTE 0x000168 0x08048168 0x08048168 0x00044 0x00044 R 0x4 GNU_EH_FRAME 0x00064c 0x0804864c 0x0804864c 0x00044 0x00044 R 0x4 GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4 GNU_RELRO 0x000f14 0x08049f14 0x08049f14 0x000ec 0x000ec R 0x1 Section to Segment mapping: Segment Sections... 00 01 .interp 02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r
  • 5. .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame 03 .ctors .dtors .jcr .dynamic .got .got.plt .data .bss 04 .dynamic 05 .note.ABI-tag .note.gnu.build-id 06 .eh_frame_hdr 07 08 .ctors .dtors .jcr .dynamic .got 3. Le système de TAG : En s'appuyant sur ce format dont tous les objets binaires (programmes, librairies dynamiques, …) utilisent, il est possible de rajouter une section personnalisée à ce format dynamique. Il est donc possible de rajouter dans cette section un ensemble de données cohérent qui résumerait la chaîne de génération d'un binaire. En effet, il peut cela peut être utile de façon a reproduire un bug dans le but de le résoudre. Le données à inclure sont libre, mais pourrait être : • version de la toolchain (gcc, ld, … ) ; • version de la glibc ; • version des sources du noyau ; • version des binutils (ar, strip, ranlib, … ) ; • date et heure du build ; • tag du système de gestion de versions utilisé (SVN, Mercurial, Git, … ) ; • ... Cela pourrait être résumé avec un identifiant du build si sauvegarde de la carte identité des build en base de données ; 4. Génération et pose d'un TAG avec objcopy Un tag est simplement un fichier texte dans lequel on écrit des données importantes. Il peut donc être personnalisé à souhait : $ touch ./myTag $ echo "TOOLCHAIN = " $(TOOLCHAIN_VERSION) GCC v$ (GCC_VERSION) >> ./myTag $ echo "TARGET = " $(TARGET_ID) >> ./myTag $ echo "BUILT = " $(shell date +"%Y/%m/%d %H:%M: %S") on $(BUILD_HOST) $(BUILD_KIND) >> ./myTag Pour faire simple, nous allons utiliser un tag avec juste une salutation : echo "bonjour Thierry" > ./mytag Avant d'appliquer un TAG dans les sections du header ELF, il peut être nécessaire par sécurité de supprimer un ancien TAG similaire : $ objcopy --remove-section MYTAG ./myBinElf Ensuite, nous pouvons ajouter notre TAG au binaire : $ objcopy --add-section MYTAG=./myTag --set-section-flags MYTAG=contents ./myBinElf On peut vérifier que le tag est bien présent :
  • 6. $ readelf -all ./myBinElf | grep MYTAG [27] MYTAG PROGBITS 00000000 00104a 000010 00 W 0 0 1 5. Extraction du TAG avec objcopy Maintenant nous avons besoin d'extraire ce TAG pour pouvoir connaître sont contenu. Nous allons utilise l'outil objcopy et dd pour ce faire. De façon, à simplifier l'extraction, je propose un petit script shell « extractTAG.sh » : IN_F=$1 OUT_F=$2 SECTION=$3 objdump -h $IN_F | grep $SECTION | awk '{print "dd if='$IN_F' of='$OUT_F' bs=1 count=$[0x" $3 "] skip=$[0x" $6 "]"}' | bash Une fois le script rendu exécutable avec un chmod +x, son utilisant se fait de la façon suivante : ./extractTAG.sh ./myBinElf MYTAG_dump.txt MYTAG 16+0 enregistrements lus 16+0 enregistrements écrits 16 octets (16 B) copiés, 4,2532e-05 s, 376 kB/s $ cat ./MYTAG_dump.txt bonjour Thierry Nous retrouvons donc bien notre salutation d'origine. 6. Conclusion Nous avons vu la façon de poser un tag dans dans une nouvelle section ELF d'un binaire. De même, nous avons également vu comme procédé à son extraction. Généralisé, à un système de build, cela pourrait permettre de suivre la génération d'un binaire et aussi de remonté aux contexte de génération en se basant sur les données inclus dans cette section. 7. Liens • http://manpagesfr.free.fr/man/man5/elf.5.html • http://pwet.fr/man/linux/formats/elf • http://elftoolchain.sourceforge.net/for-review/libelf-by-example-20100111.pdf • http://developers.sun.com/solaris/articles/elf.html • http://docs.oracle.com/cd/E19082-01/819-0690/chapter6-43405/index.html • http://www.skyfree.org/linux/references/ELF_Format.pdf • http://www.linuxjournal.com/article/1059 • http://unixhelp.ed.ac.uk/CGI/man-cgi?objcopy+1 • http://mylinuxbook.com/readelf-command/ • http://www.bottomupcs.com/elf.html • http://www.ensta-paristech.fr/~diam/dev/online/elf-howto-1996_07_14/ELF- HOWTO.html#toc • http://fr.slideshare.net/varunmahajan06/gnu-linux-programstructure • http://linuxgazette.berlios.de/issue84/hawk.html • http://asm.sourceforge.net/articles/startup.html
  • 7. • http://stackoverflow.com/questions/13908276/loading-elf-file-in-c-in-user-space • http://linux.die.net/man/1/file • http://linux.die.net/man/1/readelf • http://linux.die.net/man/1/objdump