Forstå ELF -filformatet

Forstå ELF -filformatet

Fra kildekode til binær kode

Programmering starter med å ha en smart idé, og skrive kildekode på et programmeringsspråk etter eget valg, for eksempel C, og lagre kildekoden i en fil. Ved hjelp av en tilstrekkelig kompilator, for eksempel GCC, blir kildekoden din oversatt til objektkode, først. Etter hvert oversetter linkeren objektkoden til en binær fil som kobler objektkoden til de refererte bibliotekene. Denne filen inneholder enkeltinstruksjonene som maskinkode som forstås av CPU, og utføres så snart det sammensatte programmet kjøres.

Den binære filen som er nevnt ovenfor, følger en spesifikk struktur, og en av de vanligste heter ELF som forkorter kjørbart og koblingbart format. Det er mye brukt til kjørbare filer, flyttbare objektfiler, delte biblioteker og kjernedumps.

For tjue år siden - I 1999 - har 86open -prosjektet valgt ELF som standard binære filformat for UNIX og UNIX -lignende systemer på x86 -prosessorer. Heldigvis hadde ELF -formatet tidligere blitt dokumentert i både System V Application Binary Interface, og verktøygrensesnittstandarden [4]. Dette faktum forenklet avtalen om standardisering mellom de forskjellige leverandørene og utviklerne av UNIX-baserte operativsystemer.

Årsaken bak den avgjørelsen var utformingen av ELF - fleksibilitet, utvidbarhet og støtte for plattform for forskjellige endianformater og adressestørrelser. ELFs design er ikke begrenset til en spesifikk prosessor, instruksjonssett eller maskinvarearkitektur. For en detaljert sammenligning av kjørbare filformater, ta en titt her [3].

Siden den gang er ELF -formatet i bruk av flere forskjellige operativsystemer. Blant andre inkluderer dette Linux, Solaris/Illumos, Free-, Net- og OpenBSD, QNX, Beos/Haiku og Fuchsia OS [2]. Videre finner du det på mobile enheter som kjører Android, Maemo eller Meego OS/Sailfish OS, så vel som på spillkonsoller som PlayStation Portable, Dreamcast og Wii.

Spesifikasjonen avklarer ikke filtvengden for ELF -filer. I bruk er en rekke bokstavkombinasjoner, for eksempel .AXF, .søppelkasse, .Alv, .o, .prx, .puff, .ko, .Så, og .mod, eller ingen.

Strukturen til en ELF -fil

På en Linux -terminal gir Command Man Elf deg et nyttig sammendrag om strukturen til en ELF -fil:

Oppføring 1: Manpagen til alvestrukturen

$ mann alv
ELF (5) Linux Programmers manuelle ELF (5)
NAVN
ELF - Format av kjørbare og koblingsformat (ELF) -filer
Synopsis
#inkludere
BESKRIVELSE
Headerfilen definerer formatet til ELF -kjørbar binær
filer. Blant disse filene er normale kjørbare filer, flyttbare
Objektfiler, kjernefiler og delte biblioteker.
En kjørbar fil som bruker ELF -filformatet består av en ELF -overskrift,
etterfulgt av et programtabell for programoverskrift eller en tabell for seksjonen, eller begge deler.
ELF -overskriften er alltid på forskjøvet null av filen. Programmet
overskriftstabellen og seksjonstopptabellens forskyvning i filen er
definert i alvhodet. De to bordene beskriver resten av
Spesialiteter i filen.
..

Som du ser fra beskrivelsen over, består en ELF -fil av to seksjoner - en ELF -overskrift og fildata. Fildata -seksjonen kan bestå av en programtabell som beskriver null eller flere segmenter, en tabell for seksjonen som beskriver null eller flere seksjoner, som blir fulgt av data referert til av oppføringer fra programtabellen, og tabellen for seksjon. Hvert segment inneholder informasjon som er nødvendig for utførelse av kjøretid, mens seksjoner inneholder viktige data for kobling og flytting. Figur 1 illustrerer dette skjematisk.

ELF -overskriften

ELF -overskriften er 32 byte lang, og identifiserer formatet til filen. Det starter med en sekvens på fire unike byte som er 0x7F etterfulgt av 0x45, 0x4c og 0x46 som oversettes til de tre bokstavene E, L og F. Blant andre verdier indikerer overskriften også om det er en ELF-fil for 32 eller 64-biters format, bruker liten eller stor endiansness, viser ELF-versjonen så vel som operativsystemet filen ble samlet for for å kunne samarbeide med den Right Application Binary Interface (ABI) og CPU Instruksjonssett.

Hexdump av den binære filen berører som følger:

.Oppføring 2: HexDump av den binære filen

$ HD/usr/bin/touch | Hode -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 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 |… @.8… @… |
00000040 06 00 00 00 05 00 00 00 40 00 00 00 00 00 00 00 |… @… |

Debian Gnu/Linux tilbyr lesekommandoen som er gitt i GNU 'Binutils' -pakken. Ledsaget av bryteren -h (kortversjon for "-file-header") viser den pent overskriften til en ELF-fil. Oppføring 3 illustrerer dette for kommandoen berøring.

.Oppføring 3: Viser overskriften til 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: 2s komplement, Little Endian
Versjon: 1 (strøm)
OS/ABI: UNIX - System V
ABI -versjon: 0
Type: exec (kjørbar fil)
Maskin: avanserte mikroenheter x86-64
Versjon: 0x1
Inngangspunktadresse: 0x4025E3
Start av programoverskrifter: 64 (byte til fil)
Start av seksjonsoverskrifter: 58408 (byte til fil)
Flagg: 0x0
Størrelse på denne overskriften: 64 (byte)
Størrelse på programoverskrifter: 56 (byte)
Antall programoverskrifter: 9
Størrelse på seksjonsoverskrifter: 64 (byte)
Antall seksjonsoverskrifter: 27
Seksjonshode streng tabellindeks: 26

Programoverskriften

Programoverskriften viser segmentene som brukes ved kjøretid, og forteller systemet hvordan du lager et prosessbilde. Overskriften fra Listing 2 viser at ELF -filen består av 9 programoverskrifter som har en størrelse på 56 byte hver, og den første overskriften starter på Byte 64.

Igjen hjelper lesekommandoen til å trekke ut informasjonen fra ELF -filen. Bryteren -L (forkortelse for -program -headers eller -Segmenter) avslører flere detaljer som vist i oppføring 4.

.Oppføring 4: Vis informasjon om programoverskriftene

$ readelf -l/usr/bin/touch
ELF -filtype er Exec (kjørbar fil)
Inngangspunkt 0x4025E3
Det er 9 programoverskrifter, som starter ved forskyvning 64
Programoverskrifter:
Type offset virtaddr physaddr
Filesiz memsiz flagg justeres
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000001F8 0x0000000000000001F8 R E 8
Interp 0x000000000000000238 0x0000000000400238 0x0000000000400238
0x000000000000001C 0x00000000000000001C R 1
[Be om programtolk: /lib64 /ld-linux-x86-64.så.2]
Last inn 0x000000000000000000 dollar 0x0000000000400000 0x0000000000400000
0x00000000000000D494 0x00000000000000D494 R E 200000
Last inn 0x00000000000000DE10 0x000000000060DE10 0x000000000060DE10
0x000000000000000524 0x000000000000000748 RW 200000
Dynamic 0x000000000000DE28 0x000000000060DE28 0x000000000060DE28
0x00000000000001D0 0x0000000000000001D0 RW 8
Merk 0x000000000000000254 0x000000000000400254 0x0000000000400254
0x0000000000000044 0x000000000000000044 R 4
GNU_EH_FRAME 0x000000000000BC40 0x000000000040BC40 0x00000000000040BC40
0x00000000000003a4 0x0000000000000003A4 R 4
GNU_Stack 0x0000000000000000 0x00000000000000000000000000000000 dollar 0x00000000000000
0x000000000000000000 0x000000000000000000 RW 10
GNU_RELRO 0x000000000000DE10 0x000000000060DE10 0x000000000060DE10
0x00000000000001F0 0x0000000000000001F0 R 1
Seksjon til segmentkartlegging:
Segment seksjoner ..
00
01 .Interp
02 .Interp .Merk.Abi-tag .Merk.gnu.build-id .gnu.hash .Dynsym .Dynstr .gnu.versjon .gnu.versjon_r .rela.dyn .rela.plt .i det .plt .tekst .Fini .Rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .JCR .dynamisk .har .har.plt .data .BSS
04 .dynamisk
05 .Merk.Abi-tag .Merk.gnu.build-id
06 .eh_frame_hdr
07
08 .init_array .fini_array .JCR .dynamisk .har

Seksjonshodet

Den tredje delen av ELF -strukturen er seksjonen. Det er ment å liste opp enkeltdelene av det binære. Bryteren -S (forkortelse for -seksjonshoder eller -seksjoner) viser de forskjellige overskriftene. Når det gjelder Touch -kommandoen, er det 27 seksjonsoverskrifter, og liste 5 viser de fire første av dem pluss den siste, bare. Hver linje dekker seksjonsstørrelsen, seksjonstypen så vel som sin adresse og minneforskyvning.

.Oppføring 5: Seksjonsdetaljer avslørt av Readelf

$ readelf -s/usr/bin/touch
Det er 27 seksjonsoverskrifter, som starter ved forskyvning 0xe428:
Seksjonsoverskrifter:
[NR] Navntype adresseforskyvning
Størrelse ennsize flagg lenke info justere
[0] NULL 0000000000000000 00000000
000000000000000000 000000000000000000 0 0 0 0 0 0 0 0 0 0 0 0 0 0
[ 1] .Interp Progbits 0000000000400238 00000238
000000000000001C 0000000000000000 A 0 0 1
[2] .Merk.ABI-TAG Note 0000000000400254 00000254
000000000000002020 0000000000000000 A 0 0 4
[3] .Merk.gnu.Build-I Note 0000000000400274 00000274
..
..
[26] .SHSTRTAB STRTAB 0000000000000000 0000E334
00000000000000EF 0000000000000000 0 0 1
Nøkkel til flagg:
W (skriv), a (alloc), x (utfør), m (fusjon), s (strenger), l (stor)
I (Info), L (Link Order), G (Group), T (TLS), E (Ekskluder), X (Ukjent)
O (Ekstra OS -behandling påkrevd) O (OS spesifikk), P (prosessorspesifikk)

Verktøy for å analysere en ELF -fil

Som du kanskje har nevnt fra eksemplene ovenfor, blir GNU/Linux utfylt med en rekke nyttige verktøy som hjelper deg å analysere en ELF -fil. Den første kandidaten vi vil se på er filverktøyet.

Fil viser grunnleggende informasjon om ELF -filer, inkludert instruksjonssettarkitekturen som koden i en flyttbar, kjørbar eller delt objektfil er ment. I Listing 6 forteller det deg at/bin/touch er en 64-bits kjørbar fil etter Linux Standard Base (LSB), dynamisk koblet og bygget for GNU/Linux-kjernen versjon 2.6.32.

.Oppføring 6: Grunnleggende informasjon ved hjelp av fil

$ fil /bin /berøring
/bin/berøring: ELF 64-bit LSB kjørbar, x86-64, versjon 1 (SYSV), dynamisk koblet, tolk/lib64/l,
For GNU/Linux 2.6.32, buildID [SHA1] = EC08D609E9E8E73D4BE6134541A472AD0EA34502, strippet
$

Den andre kandidaten er leself. Den viser detaljert informasjon om en ELF -fil. Listen over brytere er sammenlignbart lang, og dekker alle aspektene ved ELF -formatet. Bruke Switch -N (forkortelse for -noter) Listing 7 viser bare notatseksjonene som finnes i filen Touch -ABI -versjonskoden, og Build ID BitString.

.Oppføring 7: Vis valgte seksjoner av en ELF -fil

$ readelf -n/usr/bin/touch
Visesnotater funnet ved filforskyvning 0x00000254 med lengde 0x00000020:
Eierens datastørrelse Beskrivelse
GNU 0x00000010 NT_GNU_ABI_TAG (ABI Version tag)
OS: Linux, ABI: 2.6.32
Visesnotater funnet ved filforskyvning 0x00000274 med lengde 0x00000024:
Eierens datastørrelse Beskrivelse
GNU 0x00000014 NT_GNU_BUILD_ID (Unique Build ID BITSSTRING)
Bygg ID: EC08D609E9E8E73D4BE6134541A472AD0EA34502

Legg merke til at under Solaris og FreeBSD, tilsvarer verktøyet Elfdump [7]. Fra 2019 har det ikke vært en ny utgivelse eller oppdatering siden 2003.

Nummer tre er pakken som heter Elfutils [6] som er rent tilgjengelig for Linux. Den gir alternative verktøy til GNU Binutils, og tillater også validering av ELF -filer. Merk at alle navnene på verktøyene som er gitt i pakken starter med EU for 'ELF -utils'.

Sist, men ikke minst, vil vi nevne objdump. Dette verktøyet ligner på leself, men fokuserer på objektfiler. Det gir et lignende utvalg av informasjon om ELF -filer og andre objektformater.

.Oppføring 8: Filinformasjon trukket ut av objdump

$ objdump -f /bin /berøring
/bin/berøring: Filformat ELF64-X86-64
Arkitektur: I386: x86-64, flagg 0x00000112:
Exec_p, has_syms, d_paged
Start adresse 0x00000000004025E3
$

Det er også en programvarepakke kalt 'Elfkickers' [9] som inneholder verktøy for å lese innholdet i en ELF -fil, samt manipulere den. Dessverre er antall utgivelser ganske lavt, og det er derfor vi bare nevner det, og viser ikke ytterligere eksempler.

Som utvikler kan du se på 'PAX-UTILS' [10,11], i stedet. Dette settet med verktøy gir en rekke verktøy som hjelper til med å validere ELF -filer. Som et eksempel analyserer Dumpelf ELF -filen, og returnerer en C -overskriftsfil som inneholder detaljene - se figur 2.

Konklusjon

Takket være en kombinasjon av smart design og utmerket dokumentasjon fungerer ELF -formatet veldig bra, og er fremdeles i bruk etter 20 år. Verktøyene vist ovenfor gir deg en innsikt i en ELF -fil, og lar deg finne ut hva et program gjør. Dette er de første trinnene for å analysere programvare - lykkelig hacking!

Lenker og referanser
  • [1] Kjørbart og koblingbart format (ELF), Wikipedia
  • [2] Fuchsia OS
  • [3] Sammenligning av kjørbare filformater, Wikipedia
  • [4] Linux Foundation, refererte spesifikasjoner
  • [5] Ciro Santilli: Elf Hello World Tutorial
  • [6] Elfutils Debian -pakke
  • [7] Elfdump
  • [8] Michael Boelen: 101 av ELF -filer på Linux: Forståelse og analyse
  • [9] Elfkickers
  • [10] herdede/pax verktøy
  • [11] PAX-UTILS, Debian-pakke
Anerkjennelser

Forfatteren vil takke Axel Beckert for hans støtte angående utarbeidelsen av denne artikkelen.