Pochopenie formátu súboru ELF

Understanding Elf File Format



Od zdrojového kódu k binárnemu kódu

Programovanie začína múdrou myšlienkou a napísaním zdrojového kódu v programovacom jazyku podľa vášho výberu, napríklad C, a uložením zdrojového kódu do súboru. S pomocou adekvátneho kompilátora, napríklad GCC, sa váš zdrojový kód najskôr preloží do objektového kódu. Linker nakoniec preloží kód objektu do binárneho súboru, ktorý prepojí kód objektu s odkazovanými knižnicami. Tento súbor obsahuje jediné inštrukcie ako strojový kód, ktorým procesor rozumie a sú spustené ihneď po spustení kompilovaného programu.

Vyššie uvedený binárny súbor má špecifickú štruktúru a jeden z najbežnejších má názov ELF, ktorý skratkuje spustiteľný a prepojiteľný formát. Je široko používaný pre spustiteľné súbory, premiestniteľné súbory objektov, zdieľané knižnice a základné skládky.







Pred dvadsiatimi rokmi-v roku 1999-si projekt 86open vybral ELF ako štandardný formát binárnych súborov pre systémy Unix a systémy podobné unixom na procesoroch x86. Našťastie bol formát ELF predtým dokumentovaný v binárnom rozhraní aplikácie System V aj v štandarde rozhrania nástroja [4]. Táto skutočnosť enormne zjednodušila dohodu o štandardizácii medzi rôznymi dodávateľmi a vývojármi operačných systémov založených na Unixe.



Dôvodom tohto rozhodnutia bol návrh ELF-flexibilita, rozšíriteľnosť a podpora viacerých platforiem pre rôzne endianové formáty a veľkosti adries. Dizajn spoločnosti ELF nie je obmedzený na konkrétny procesor, inštrukčnú sadu alebo hardvérovú architektúru. Podrobné porovnanie spustiteľných formátov súborov nájdete tu [3].



Odvtedy formát ELF používa niekoľko rôznych operačných systémov. Okrem iného sem patria Linux, Solaris/Illumos, Free-, Net- a OpenBSD, QNX, BeOS/Haiku a Fuchsia OS [2]. Ďalej ho nájdete na mobilných zariadeniach so systémom Android, Maemo alebo Meego OS/Sailfish OS, ako aj na herných konzolách ako PlayStation Portable, Dreamcast a Wii.





Špecifikácia nevysvetľuje príponu súboru pre súbory ELF. Používa sa množstvo kombinácií písmen, napríklad .axf, .bin, .elf, .o, .prx, .puff, .ko, .so a .mod, alebo žiadne.

Štruktúra súboru ELF

Na termináli Linux vám príkaz man elf poskytne užitočné zhrnutie štruktúry súboru ELF:



Výpis 1: Manpage štruktúry ELF

$ muž jedenásť

ELF (5) Príručka programátora Linuxu ELF (5)

NÁZOV
elf - formát súborov spustiteľných a prepojovacích formátov (ELF)

SYNOPSA
#zahrnúť

POPIS
Hlavičkový súbor definuje formát spustiteľného binárneho súboru ELF
súbory. Medzi týmito súbormi sú normálne spustiteľné súbory, ktoré je možné premiestniť
objektové súbory, základné súbory a zdieľané knižnice.

Spustiteľný súbor používajúci formát súboru ELF pozostáva z hlavičky ELF,
nasleduje tabuľka záhlaví programu alebo tabuľka záhlaví sekcií alebo oboje.
Hlavička ELF je vždy na offsetovej nule súboru. Program
tabuľka záhlavia a posun tabuľky záhlavia sekcie v súbore sú
definované v hlavičke ELF. Tieto dve tabuľky popisujú zvyšok
špecifiká súboru.

...

Ako vidíte z vyššie uvedeného popisu, súbor ELF sa skladá z dvoch sekcií - hlavičky ELF a údajov súboru. Sekcia údajov o súboroch môže pozostávať z tabuľky záhlavia programu popisujúcej nula alebo viacerých segmentov, tabuľky záhlavia sekcií opisujúcich nula alebo viacerých sekcií, za ktorou nasledujú údaje uvedené v záznamoch z tabuľky záhlavia programu a tabuľky záhlaví sekcií. Každý segment obsahuje informácie, ktoré sú potrebné na spustenie súboru za behu, zatiaľ čo sekcie obsahujú dôležité údaje na prepojenie a premiestnenie. Obrázok 1 to schematicky ilustruje.

Hlavička ELF

Hlavička ELF má 32 bajtov a identifikuje formát súboru. Začína sa to sekvenciou štyroch jedinečných bajtov 0x7F, za ktorou nasledujú 0x45, 0x4c a 0x46 a ktorá sa prekladá do troch písmen E, L a F. Okrem iných hodnôt hlavička tiež uvádza, či ide o súbor ELF pre 32 alebo 64-bitový formát, ktorý používa malú alebo veľkú endianness, zobrazuje verziu ELF a operačný systém, pre ktorý bol súbor zostavený, aby spolupracoval so správnym súborom inštrukcií binárne rozhranie (ABI) a procesor.

Hexdump binárneho súboru vyzerá takto:

.Listing 2: Hexdump binárneho súboru

$ hd/usr/bin/dotyk | hlava -5
00000000 7f 45 4c 46 02 01 01 00 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 | [chránené e -mailom] @..... |
00000040 06 00 00 00 05 00 00 00 40 40 00 00 00 00 00 00 00 00 [chránené e -mailom] |

Debian GNU/Linux ponúka príkaz readelf, ktorý je súčasťou balíka GNU „binutils“. Doplnený prepínačom -h (krátka verzia pre –súbor -hlavička) pekne zobrazuje hlavičku súboru ELF. Zoznam 3 to ilustruje na príkazovom dotyku.

.Zoznam 3: Zobrazenie hlavičky súboru ELF

$ readelf -h/usr/bin/touch
Hlavička ELF:
Mágia: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 00
Trieda: ELF64
Údaje: Doplnok 2, malý endian
Verzia: 1 (aktuálna)
OS / ABI: UNIX - systém V
Verzia ABI: 0
Typ: EXEC (spustiteľný súbor)
Stroj: Pokročilé mikro zariadenia X86-64
Verzia: 0x1
Adresa vstupného bodu: 0x4025e3
Začiatok hlavičiek programu: 64 (bajtov do súboru)
Začiatok hlavičiek sekcií: 58408 (bajtov do súboru)
Vlajky: 0x0
Veľkosť tejto hlavičky: 64 (bajtov)
Veľkosť hlavičiek programu: 56 (bajtov)
Počet hlavičiek programov: 9
Veľkosť hlavičiek sekcií: 64 (bajtov)
Počet záhlaví sekcií: 27
Register tabuľky reťazcov hlavičky sekcie: 26

Hlavička programu

Hlavička programu zobrazuje segmenty používané za behu a systému hovorí, ako vytvoriť obraz procesu. Záhlavie zo zoznamu 2 ukazuje, že súbor ELF pozostáva z 9 hlavičiek programu, z ktorých každá má veľkosť 56 bajtov, a prvé záhlavie začína na bajte 64.

Príkaz readelf opäť pomáha extrahovať informácie zo súboru ELF. Prepínač -l (skratka pre –programové hlavičky alebo –segmenty) odhalí ďalšie podrobnosti, ako je uvedené v zozname 4.

. Zoznam 4: Zobrazenie informácií o hlavičkách programu

$ readelf -l/usr/bin/touch

Typ súboru elf je EXEC (spustiteľný súbor)
Vstupný bod 0x4025e3
Existuje 9 hlavičiek programov, začínajúc od ofsetu 64

Hlavičky programu:
Zadajte Offset VirtAddr PhysAddr
Zarovnať vlajky FileSiz MemSiz
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000001f8 0x0000000000000001f8 R E 8
INTERP 0x0000000000000238 0x000000000000400238 0x0000000000400238
0x000000000000001001c 0x00000000000000001001c R 1
[Žiadajúci interpret programu: /lib64/ld-linux-x86-64.so.2]
ZATOŽTE 0x000000000000000000 0x0000000000400000 0x0000000000400400000
0x000000000000d494 0x00000000000000d494 R E 200000
ZATOŽTE 0x000000000000de10 0x000000000060de10 0x00000000006060de10
0x0000000000000524 0x000000000000000748 RW 200000
DYNAMIC 0x00000000000000de28 0x000000000060de28 0x00000000006060de28
0x00000000000001d0 0x0000000000000001d0 RW 8
POZNÁMKA 0x0000000000000254 0x000000000000400254 0x0000000000400254
0x000000000000004444 0x00000000000000004444 R 4
GNU_EH_FRAME 0x00000000000000bc40 0x00000000004040bc40 0x00000000004040bc40
0x00000000000003a4 0x0000000000000003a4 R 4
GNU_STACK 0x000000000000000000 0x000000000000000000 0x000000000000000000
0x0000000000000000 0x000000000000000000 RW 10
GNU_RELRO 0x000000000000dede10 0x000000000060de10 0x00000000006060de10
0x00000000000001f0 0x0000000000000001f0 R 1

Mapovanie sekcií na segmenty:
Segmentové sekcie ...
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 .dynamický
05 .note.ABI-tag .note.gnu.build-id
06 .eh_frame_hdr
07
08 .init_array .fini_array .jcr .dynamic .got

Hlavička sekcie

Treťou časťou štruktúry ELF je záhlavie sekcie. Cieľom je uviesť zoznam jednotlivých sekcií binárneho súboru. Prepínač -S (skratka pre –sekčné hlavičky alebo –sekcie) uvádza rôzne hlavičky. Pokiaľ ide o dotykový príkaz, existuje 27 hlavičiek sekcií a v zozname 5 sú uvedené iba prvé štyri z nich a posledné. Každý riadok pokrýva veľkosť sekcie, typ sekcie, ako aj jej adresu a ofset pamäte.

. Zoznam 5: Podrobnosti o sekcii odhalené readelfom

$ readelf -S/usr/bin/dotyk
Existuje 27 hlavičiek sekcií, začínajúcich s posunom 0xe428:

Hlavičky sekcií:
[Nr] Názov Typ Adresa Offset
Size EntSize Flags Link Info Align
[0] NULL 0000000000000000 00 00000000
0000000000000000 000000000000000000 0 0 0
[1] .interp PROGBITS 0000000000400238 00000238
000000000000001001 000000000000000000 A 0 0 1
[2] .note.ABI-tag POZNÁMKA 0000000000400254 00000254
0000000000000000 00 0000000000000000 A 0 0 4
[3] .note.gnu.build-i POZNÁMKA 0000000000400274 00000274
...
...
[26] .shstrtab STRTAB 000000000000000000 0000e334
00000000000000ef 000000000000000000 0 0 1
Kľúč k vlajkam:
W (zápis), A (pridelenie), X (spustenie), M (zlúčenie), S (reťazce), l (veľké)
I (informácie), L (poradie odkazov), G (skupina), T (TLS), E (vylúčiť), x (neznáme)
O (vyžaduje sa ďalšie spracovanie OS) o (špecifické pre OS), p (špecifické pre procesor)

Nástroje na analýzu súboru ELF

Ako ste si mohli všimnúť z vyššie uvedených príkladov, GNU/Linux je doplnený o množstvo užitočných nástrojov, ktoré vám pomôžu analyzovať súbor ELF. Prvým kandidátom, na ktorého sa pozrieme, je súborový nástroj.

súbor zobrazuje základné informácie o súboroch ELF vrátane architektúry sady inštrukcií, pre ktorú je kód v premiestniteľnom, spustiteľnom alebo zdieľanom objekte určený. V zozname 6 vám hovorí, že/bin/touch je 64-bitový spustiteľný súbor podľa Linux Standard Base (LSB), dynamicky prepojený a vytvorený pre jadro GNU/Linux verzie 2.6.32.

.Seznam 6: Základné informácie pomocou súboru

$ súbor /bin /dotyk
/bin/touch: 64-bitový spustiteľný súbor ELF LSB, x86-64, verzia 1 (SYSV), dynamicky prepojený, interpret/lib64/l,
pre GNU/Linux 2.6.32, BuildID [sha1] = ec08d609e9e8e73d4be6134541a472ad0ea34502, zbavený
$

Druhý kandidát je pripravený na prečítanie. Zobrazuje podrobné informácie o súbore ELF. Zoznam prepínačov je porovnateľne dlhý a pokrýva všetky aspekty formátu ELF. Použitím prepínača -n (skratka – poznámky) Výpis 7 zobrazuje iba sekcie poznámok, ktoré sa nachádzajú v dotyku súboru -značku verzie ABI a bitový reťazec ID zostavy.

.Seznam 7: Zobrazenie vybraných sekcií súboru ELF

$ readelf -n/usr/bin/touch

Zobrazujú sa poznámky nájdené pri offsete súboru 0x00000254 s dĺžkou 0x00000020:
Vlastník Údaje o veľkosti Popis
GNU 0x00000010 NT_GNU_ABI_TAG (značka verzie ABI)
OS: Linux, ABI: 2.6.32

Zobrazujú sa poznámky nájdené pri offsete súboru 0x00000274 s dĺžkou 0x00000024:
Vlastník Údaje o veľkosti Popis
GNU 0x00000014 NT_GNU_BUILD_ID (bitový reťazec ID jedinečného zostavenia)
ID zostavy: ec08d609e9e8e73d4be6134541a472ad0ea34502

Všimnite si toho, že v systémoch Solaris a FreeBSD nástroj elfdump [7] korešponduje s readelf. Od roku 2019 neexistuje žiadne nové vydanie ani aktualizácia od roku 2003.

Číslo tri je balík s názvom elfutils [6], ktorý je k dispozícii iba pre Linux. Poskytuje alternatívne nástroje k GNU Binutils a tiež umožňuje validáciu súborov ELF. Všimnite si toho, že všetky názvy nástrojov uvedených v balíku začínajú na eu pre „elf utils“.

V neposlednom rade spomenieme objdump. Tento nástroj je podobný readelf, ale zameriava sa na objektové súbory. Poskytuje podobný rozsah informácií o súboroch ELF a iných objektových formátoch.

.Seznam 8: Informácie o súbore extrahované pomocou objdump

$ objdump -f /bin /touch

/bin/touch: formát súboru elf64-x86-64
architektúra: i386: x86-64, vlajky 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
štartovacia adresa 0x0000000000404025e3

$

Existuje aj softvérový balík s názvom „elfkickers“ [9], ktorý obsahuje nástroje na čítanie obsahu súboru ELF a na manipuláciu s ním. Počet vydaní je bohužiaľ dosť nízky, a preto to uvádzame a neukazujeme ďalšie príklady.

Ako vývojár sa môžete namiesto toho pozrieť na „pax-utils“ [10,11]. Táto sada nástrojov poskytuje množstvo nástrojov, ktoré pomáhajú pri validácii súborov ELF. Dumpelf napríklad analyzuje súbor ELF a vráti súbor hlavičky C obsahujúci podrobnosti - pozri obrázok 2.

Záver

Vďaka kombinácii chytrého dizajnu a vynikajúcej dokumentácie formát ELF funguje veľmi dobre a používa sa aj po 20 rokoch. Vyššie uvedené pomocné programy vám poskytnú prehľad o súbore ELF a umožnia vám zistiť, čo program robí. Toto sú prvé kroky k analýze softvéru - šťastné hackovanie!

Odkazy a referencie
Poďakovanie

Autor by chcel poďakovať Axelovi Beckertovi za podporu pri príprave tohto článku.