Forstå ELF -filformatet

Understanding Elf File Format



Fra kildekode til binær kode

Programmering starter med at have en smart idé og skrive kildekode på et programmeringssprog efter eget valg, for eksempel C, og gemme kildekoden i en fil. Ved hjælp af en passende kompilator, f.eks. GCC, oversættes din kildekode først til objektkode. Til sidst oversætter linkeren objektkoden til en binær fil, der forbinder objektkoden med de refererede biblioteker. Denne fil indeholder de enkelte instruktioner som maskinkode, der forstås af CPU'en og udføres, så snart det kompilerede program køres.

Den ovennævnte binære fil følger en specifik struktur, og en af ​​de mest almindelige hedder ELF, der forkorter eksekverbart og sammenkædeligt format. Det bruges i vid udstrækning til eksekverbare filer, flytbare objektfiler, delte biblioteker og kernedumpe.







For tyve år siden-i 1999-har 86open-projektet valgt ELF som standard binært filformat for Unix og Unix-lignende systemer på x86-processorer. Heldigvis var ELF -formatet tidligere blevet dokumenteret i både System V Application Binary Interface og Tool Interface Standard [4]. Denne kendsgerning forenklede enormt aftalen om standardisering mellem de forskellige leverandører og udviklere af Unix-baserede operativsystemer.



Årsagen bag denne beslutning var designet af ELF-fleksibilitet, udvidelsesmuligheder og cross-platform support til forskellige endianformater og adressestørrelser. ELFs design er ikke begrænset til en specifik processor, instruktionssæt eller hardware -arkitektur. For en detaljeret sammenligning af eksekverbare filformater, se her [3].



Siden da har ELF -formatet været i brug af flere forskellige operativsystemer. Blandt andet inkluderer dette Linux, Solaris/Illumos, Free-, Net- og OpenBSD, QNX, BeOS/Haiku og Fuchsia OS [2]. Desuden finder du det på mobile enheder, der kører Android, Maemo eller Meego OS/Sailfish OS samt på spilkonsoller som PlayStation Portable, Dreamcast og Wii.





Specifikationen tydeliggør ikke filnavnudvidelsen til ELF -filer. I brug er en række forskellige bogstavkombinationer, f.eks. .Axf, .bin, .elf, .o, .prx, .puff, .ko, .so og .mod, eller ingen.

Strukturen af ​​en ELF -fil

På en Linux -terminal giver kommandoen man elf dig et praktisk resumé om strukturen i en ELF -fil:



Liste 1: ELF -strukturens manpage

$ mand elleve

ELF (5) Linux Programmerings Manual ELF (5)

NAVN
elf - format af ELF -filer (Executable and Linking Format)

SYNOPSIS
#omfatte

BESKRIVELSE
Overskriftsfilen definerer formatet for ELF -eksekverbar binær
filer. Blandt disse filer er normale eksekverbare filer, der kan flyttes
objektfiler, kernefiler og delte biblioteker.

En eksekverbar fil ved hjælp af ELF -filformatet består af et ELF -header,
efterfulgt af en programoverskriftstabel eller en sektionsoverskriftstabel eller begge dele.
ELF -overskriften er altid ved offset nul for filen. Programmet
overskriftstabel og sektionsoverskriftstabellens forskydning i filen er
defineret i ELF -overskriften. De to tabeller beskriver resten af
filens særlige forhold.

...

Som du kan se fra beskrivelsen ovenfor, består en ELF -fil af to sektioner - en ELF -overskrift og fildata. Fildatasektionen kan bestå af en programoverskriftstabel, der beskriver nul eller flere segmenter, en sektionsoverskriftstabel, der beskriver nul eller flere sektioner, der efterfølges af data, der henvises til ved poster fra programoverskriftstabellen, og sektionsoverskriftstabellen. Hvert segment indeholder oplysninger, der er nødvendige for filtimering, mens sektioner indeholder vigtige data til sammenkædning og flytning. Figur 1 illustrerer dette skematisk.

ELF Header

ELF -headeren er 32 bytes lang og identificerer filformatet. Det starter med en sekvens på fire unikke bytes, der er 0x7F efterfulgt af 0x45, 0x4c og 0x46, som oversættes til de tre bogstaver E, L og F. Blandt andre værdier angiver overskriften også, om det er en ELF -fil til 32 eller 64-bit-format, bruger lidt eller stor endianness, viser ELF-versionen samt for hvilket operativsystem filen blev kompileret til for at interoperere med den rigtige applikations binære grænseflade (ABI) og cpu-instruktionssæt.

Hexdumpen i den binære filberøring ser således ud:

.Liste 2: Den binære fils hexdump

$ hd/usr/bin/touch | hoved -5
00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 | .ELF ........... |
00000010 02 00 3e 00 01 00 00 00 e3 25 40 00 00 00 00 00 | ..> ......% @ ..... |
00000020 40 00 00 00 00 00 00 00 00 28 e4 00 00 00 00 00 00 | @ ....... (....... |
00000030 00 00 00 00 40 00 38 00 09 00 40 00 1b 00 1a 00 | [e -mail beskyttet] @..... |
00000040 06 00 00 00 05 00 00 00 40 00 00 00 00 00 00 00 | [e -mail beskyttet] |

Debian GNU/Linux tilbyder kommandoen readelf, der findes i GNU 'binutils' -pakken. Ledsaget af switch -h (kort version til –file -header) viser det pænt overskriften på en ELF -fil. Liste 3 illustrerer dette for kommando -berøring.

.Liste 3: Visning af overskriften på en ELF -fil

$ readelf -h/usr/bin/touch
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Klasse: ELF64
Data: 2's komplement, lille endian
Version: 1 (nuværende)
OS / ABI: UNIX - System V
ABI -version: 0
Type: EXEC (eksekverbar fil)
Maskine: Avancerede mikroenheder X86-64
Version: 0x1
Indgangsadresse: 0x4025e3
Start af programoverskrifter: 64 (bytes i fil)
Start af sektionsoverskrifter: 58408 (bytes i fil)
Flag: 0x0
Størrelse på dette overskrift: 64 (bytes)
Størrelse på programoverskrifter: 56 (bytes)
Antal programoverskrifter: 9
Størrelse på sektionsoverskrifter: 64 (bytes)
Antal sektionsoverskrifter: 27
Tabelindeks for sektionsoverskriftstreng: 26

Programoverskriften

Programoverskriften viser segmenterne, der bruges i løbetid, og fortæller systemet, hvordan man opretter et procesbillede. Overskriften fra liste 2 viser, at ELF -filen består af 9 programoverskrifter, der hver har en størrelse på 56 bytes, og den første overskrift starter ved byte 64.

Igen hjælper readelf -kommandoen med at udtrække oplysningerne fra ELF -filen. Omskifteren -l (forkortelse for –program -overskrifter eller –segmenter) afslører flere detaljer som vist i liste 4.

.Liste 4: Vis oplysninger om programoverskrifterne

$ readelf -l/usr/bin/touch

Elf -filtype er EXEC (eksekverbar fil)
Indgangspunkt 0x4025e3
Der er 9 programoverskrifter, der starter ved forskydning 64

Programoverskrifter:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flag Juster
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000001f8 0x00000000000001f8 R E 8
INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238
0x000000000000001c 0x000000000000001c R 1
[Anmodning om programfortolker: /lib64/ld-linux-x86-64.so.2]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x000000000000d494 0x000000000000d494 R E 200000
LOAD 0x000000000000de10 0x000000000060de10 0x000000000060de10
0x0000000000000524 0x0000000000000748 RW 200000
DYNAMISK 0x000000000000de28 0x000000000060de28 0x000000000060de28
0x00000000000001d0 0x00000000000001d0 RW 8
BEMÆRK 0x0000000000000254 0x0000000000400254 0x0000000000400254
0x0000000000000044 0x0000000000000044 R 4
GNU_EH_FRAME 0x000000000000bc40 0x000000000040bc40 0x000000000040bc40
0x00000000000003a4 0x00000000000003a4 R 4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 10
GNU_RELRO 0x000000000000de10 0x000000000060de10 0x000000000060de10
0x00000000000001f0 0x00000000000001f0 R 1

Afsnit til segmenteringstilknytning:
Segment sektioner ...
00
01 .interp
02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini. rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss
04. Dynamisk
05 .note.ABI-tag .note.gnu.build-id
06 .eh_frame_hdr
07
08 .init_array .fini_array .jcr .dynamic .got

Sektionsoverskriften

Den tredje del af ELF -strukturen er sektionsoverskriften. Det er meningen at liste de enkelte sektioner af binæret. Omskifteren -S (forkortelse for –section -headers eller –sections) viser de forskellige headers. Hvad angår berøringskommandoen, er der 27 sektionsoverskrifter, og liste 5 viser kun de første fire af dem plus den sidste. Hver linje dækker sektionsstørrelse, sektionstype samt adresse og hukommelsesforskydning.

.Liste 5: Afsnittet detaljer afsløret af readelf

$ readelf -S/usr/bin/touch
Der er 27 sektionsoverskrifter, der starter ved forskydning 0xe428:

Sektionsoverskrifter:
[Nr] Navnetype Adresse Offset
Størrelse EntSize Flag Link Info Juster
[0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[1] .interp PROGBITS 0000000000400238 00000238
000000000000001c 0000000000000000 A 0 0 1
[2] .note.ABI-tag NOTE 0000000000400254 00000254
0000000000000020 0000000000000000 A 0 0 4
[3] .note.gnu.build-i NOTE 0000000000400274 00000274
...
...
[26] .shstrtab STRTAB 0000000000000000 0000e334
00000000000000ef 0000000000000000 0 0 1
Nøgle til flag:
W (skriv), A (fordel), X (udfør), M (flet), S (strenge), l (stor)
I (info), L (linkorder), G (group), T (TLS), E (exclude), x (ukendt)
O (ekstra OS -behandling påkrævet) o (OS -specifik), p (processorspecifik)

Værktøjer til at analysere en ELF -fil

Som du måske har bemærket fra eksemplerne ovenfor, er GNU/Linux udbygget med en række nyttige værktøjer, der hjælper dig med at analysere en ELF -fil. Den første kandidat, vi vil se på, er filværktøjet.

fil viser grundlæggende oplysninger om ELF -filer, herunder instruktionssætets arkitektur, hvortil koden i en flytbar, eksekverbar eller delt objektfil er beregnet. I liste 6 fortæller det dig, at/bin/touch er en 64-bit eksekverbar fil, der følger Linux Standard Base (LSB), dynamisk forbundet og er bygget til GNU/Linux-kerneversionen 2.6.32.

.Liste 6: Grundlæggende oplysninger ved hjælp af fil

$ file /bin /touch
/bin/touch: ELF 64-bit LSB eksekverbar, x86-64, version 1 (SYSV), dynamisk forbundet, tolk/lib64/l,
til GNU/Linux 2.6.32, BuildID [sha1] = ec08d609e9e8e73d4be6134541a472ad0ea34502, fjernet
$

Den anden kandidat er færdig. Det viser detaljerede oplysninger om en ELF -fil. Listen over switches er forholdsvis lang og dækker alle aspekter af ELF -formatet. Brug af switch -n (forkortelse for –notes) Liste 7 viser kun de notatsektioner, der findes i filberøring -ABI -versionstagget og build -ID -bitstrengen.

.Liste 7: Vis udvalgte sektioner af en ELF -fil

$ readelf -n/usr/bin/touch

Viser noter fundet ved filforskydning 0x00000254 med længde 0x00000020:
Ejer Datastørrelse Beskrivelse
GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)
OS: Linux, ABI: 2.6.32

Viser noter fundet ved filforskydning 0x00000274 med længde 0x00000024:
Ejer Datastørrelse Beskrivelse
GNU 0x00000014 NT_GNU_BUILD_ID (unikt build -ID bitstreng)
Byg ID: ec08d609e9e8e73d4be6134541a472ad0ea34502

Bemærk, at under Solaris og FreeBSD svarer elfdumpen [7] til readelf. Fra 2019 har der ikke været en ny udgivelse eller opdatering siden 2003.

Nummer tre er pakken med navnet elfutils [6], der er rent tilgængelig til Linux. Det giver alternative værktøjer til GNU Binutils og tillader også validering af ELF -filer. Bemærk, at alle navnene på værktøjerne i pakken starter med eu for 'elf utils'.

Sidst men ikke mindst vil vi nævne objdump. Dette værktøj ligner readelf, men fokuserer på objektfiler. Det giver en lignende række oplysninger om ELF -filer og andre objektformater.

.Liste 8: Filinformation udvundet af objdump

$ objdump -f /bin /touch

/bin/touch: filformat elf64-x86-64
arkitektur: i386: x86-64, flag 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
startadresse 0x00000000004025e3

$

Der er også en softwarepakke kaldet 'elfkickers' [9], som indeholder værktøjer til at læse indholdet af en ELF -fil samt manipulere den. Desværre er antallet af udgivelser ret lavt, og derfor nævner vi det bare og viser ikke flere eksempler.

Som udvikler kan du i stedet se på 'pax-utils' [10,11]. Dette sæt værktøjer indeholder en række værktøjer, der hjælper med at validere ELF -filer. Som et eksempel analyserer dumpelf ELF -filen og returnerer en C -headerfil med detaljerne - se figur 2.

Konklusion

Takket være en kombination af smart design og fremragende dokumentation fungerer ELF -formatet meget godt og er stadig i brug efter 20 år. Værktøjerne vist ovenfor giver dig et indblik i en ELF -fil, og lader dig finde ud af, hvad et program laver. Dette er de første trin til analyse af software - glad hacking!

Links og referencer
Anerkendelser

Forfatteren vil gerne takke Axel Beckert for hans støtte vedrørende forberedelsen af ​​denne artikel.