Od zdrojového kódu po binární kód
Programování začíná chytrým nápadem a napsáním zdrojového kódu v programovacím jazyce podle vašeho výběru, například C, a uložením zdrojového kódu do souboru. S pomocí vhodného kompilátoru, například GCC, je váš zdrojový kód nejprve přeložen do objektového kódu. Nakonec linker přeloží kód objektu do binárního souboru, který propojí kód objektu s odkazovanými knihovnami. Tento soubor obsahuje jednotlivé instrukce jako strojový kód, kterým procesor rozumí a jsou provedeny, jakmile je spuštěn kompilovaný program.
Výše uvedený binární soubor sleduje konkrétní strukturu a jeden z nejběžnějších je pojmenován ELF, který zkracuje formát spustitelného a spojitelného formátu. Je široce používán pro spustitelné soubory, soubory přemístitelných objektů, sdílené knihovny a základní skládky.
Před dvaceti lety - v roce 1999 - si projekt 86open vybral ELF jako standardní formát binárního souboru pro Unix a systémy podobné Unixu na procesorech x86. Naštěstí byl formát ELF dříve dokumentován jak v binárním rozhraní aplikace System V, tak ve standardu rozhraní nástroje [4]. Tato skutečnost nesmírně zjednodušila dohodu o standardizaci mezi různými prodejci a vývojáři operačních systémů založených na Unixu.
Důvodem tohoto rozhodnutí byl návrh ELF - flexibilita, rozšiřitelnost a podpora různých platforem pro různé formáty endian a velikosti adres. Návrh ELF se neomezuje na konkrétní procesor, instrukční sadu nebo hardwarovou architekturu. Podrobné srovnání formátů spustitelných souborů naleznete zde [3].
Od té doby formát ELF používá několik různých operačních systémů. To mimo jiné zahrnuje Linux, Solaris / Illumos, Free-, Net- a OpenBSD, QNX, BeOS / Haiku a Fuchsia OS [2]. Dále jej najdete na mobilních zařízeních se systémem Android, Maemo nebo Meego OS / Sailfish OS a také na herních konzolách jako PlayStation Portable, Dreamcast a Wii.
Specifikace neobjasňuje příponu názvu souboru pro soubory ELF. Používá se celá řada kombinací písmen, například .axf, .zásobník, .Elf, .Ó, .prx, .obláček, .ko, .ano, a .mod, nebo žádný.
Struktura souboru ELF
Na terminálu Linux vám příkaz man elf poskytne užitečné shrnutí struktury souboru ELF:
Výpis 1: Stránka struktury ELF
$ man elfELF (5) Linux Programmer's Manual ELF (5)
NÁZEV
elf - formát spustitelného a spojovacího formátu (ELF)
SYNOPSE
#zahrnout
POPIS
Hlavičkový soubor
soubory. Mezi těmito soubory jsou normální spustitelné soubory, přemístitelné
objektové soubory, základní soubory a sdílené knihovny.
Spustitelný soubor ve formátu souboru ELF se skládá z hlavičky ELF,
následuje tabulka záhlaví programu nebo tabulka záhlaví sekce nebo obojí.
Záhlaví ELF je vždy na offsetu nula souboru. Program
tabulka záhlaví a posunutí tabulky záhlaví sekce v souboru jsou
definované v hlavičce ELF. Tyto dvě tabulky popisují zbytek
zvláštnosti souboru.
…
Jak vidíte z výše uvedeného popisu, soubor ELF se skládá ze dvou částí - hlavičky ELF a dat souboru. Sekce datových souborů může sestávat z tabulky záhlaví programu popisující nula nebo více segmentů, tabulky záhlaví sekce popisující nula nebo více sekcí, za kterou následují data, na která odkazují položky z tabulky záhlaví programu, a tabulky záhlaví sekce. Každý segment obsahuje informace, které jsou nezbytné pro spuštění souboru za běhu, zatímco oddíly obsahují důležitá data pro propojení a přemístění. Obrázek 1 to schematicky ilustruje.
Záhlaví ELF
Záhlaví ELF je 32 bajtů dlouhé a identifikuje formát souboru. Začíná to sekvencí čtyř jedinečných bajtů, které jsou 0x7F následované 0x45, 0x4c a 0x46, což se promítá do tří písmen E, L a F. Mezi jinými hodnotami záhlaví také označuje, zda se jedná o soubor ELF pro 32 nebo 64bitový formát, používá malou nebo velkou endianness, zobrazuje verzi ELF a také pro jaký operační systém byl soubor zkompilován za účelem spolupráce s pravé aplikační binární rozhraní (ABI) a sada instrukcí CPU.
Hexdump dotyku binárního souboru vypadá takto:
.Výpis 2: Hexdump binárního souboru
$ hd / usr / bin / touch | hlava -500000000 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 | [chráněno e-mailem] @… |
00000040 06 00 00 00 05 00 00 00 40 00 00 00 00 00 00 00 | [chráněno e-mailem] |
Debian GNU / Linux nabízí příkaz readelf, který je poskytován v balíčku GNU 'binutils'. V doprovodu přepínače -h (zkrácená verze pro „-file-header“) pěkně zobrazí hlavičku souboru ELF. Výpis 3 to ilustruje pro příkazový dotek.
.Výpis 3: Zobrazení záhlaví souboru ELF
$ readelf -h / usr / bin / touchZáhlaví ELF:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Třída: ELF64
Data: Doplněk 2, malý endian
Verze: 1 (aktuální)
OS / ABI: UNIX - Systém V
Verze ABI: 0
Typ: EXEC (spustitelný soubor)
Stroj: Advanced Micro Devices X86-64
Verze: 0x1
Adresa vstupního bodu: 0x4025e3
Začátek záhlaví programu: 64 (bajtů do souboru)
Začátek záhlaví sekce: 58408 (bajtů do souboru)
Vlajky: 0x0
Velikost této hlavičky: 64 (bajtů)
Velikost záhlaví programu: 56 (bajtů)
Počet záhlaví programu: 9
Velikost záhlaví sekcí: 64 (bajtů)
Počet záhlaví sekcí: 27
Index tabulky řetězců záhlaví sekce: 26
Záhlaví programu
Záhlaví programu zobrazuje segmenty použité za běhu a říká systému, jak vytvořit obraz procesu. Záhlaví ze seznamu 2 ukazuje, že soubor ELF se skládá z 9 záhlaví programu, které mají každý velikost 56 bajtů, a první záhlaví začíná na bajtu 64.
Příkaz readelf opět pomáhá extrahovat informace ze souboru ELF. Přepínač -l (zkratka pro -záhlaví programu nebo -segmenty) odhalí další podrobnosti, jak je uvedeno v seznamu 4.
.Výpis 4: Zobrazí informace o hlavičkách programů
$ readelf -l / usr / bin / touchTyp souboru elfů je EXEC (spustitelný soubor)
Vstupní bod 0x4025e3
K dispozici je 9 záhlaví programů, počínaje offsetem 64
Záhlaví programu:
Typ Offset VirtAddr PhysAddr
FileSiz MemSiz příznaky zarovnat
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000001f8 0x00000000000001f8 R E 8
INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238
0x000000000000001c 0x000000000000001c R 1
[Žádající programový tlumočník: / lib64 / ld-linux-x86-64.tak.2]
ZATÍŽENÍ 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x000000000000d494 0x000000000000d494 R E 200000
ZATÍŽENÍ 0x000000000000de10 0x000000000060de10 0x000000000060de10
0x0000000000000524 0x0000000000000748 RW 200000
DYNAMICKÉ 0x000000000000de28 0x000000000060de28 0x000000000060de28
0x00000000000001d0 0x00000000000001d0 RW 8
POZNÁMKA 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
Mapování řezů do segmentů:
Segmentové sekce ..
00
01 .interp
02 .interp .Poznámka.Značka ABI .Poznámka.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.verze .gnu.verze_r .rela.dyn .rela.plt .inic .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .jcr .dynamický .mám .mám.plt .data .bss
04 .dynamický
05 .Poznámka.Značka ABI .Poznámka.gnu.build-id
06 .eh_frame_hdr
07
08 .init_array .fini_array .jcr .dynamický .mám
Záhlaví sekce
Třetí částí struktury ELF je záhlaví sekce. Je určen k vypsání jednotlivých částí binárního souboru. Přepínač -S (zkratka pro -section-headers or -sections) uvádí různé záhlaví. Pokud jde o dotykový příkaz, existuje 27 záhlaví oddílů a Výpis 5 zobrazuje první čtyři z nich plus poslední, pouze. Každý řádek pokrývá velikost sekce, typ sekce i její adresu a offset paměti.
.Výpis 5: Podrobnosti sekce odhalil sám
$ readelf -S / usr / bin / touchExistuje 27 hlaviček sekcí, počínaje offsetem 0xe428:
Záhlaví sekcí:
[Nr] Název Typ Adresa Odsazení
Velikost Příznaky Velikost Odkaz Informace Zarovnat
[0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[1] .interp PROGBITS 0000000000400238 00000238
000000000000001c 0000000000000000 A 0 0 1
[2] .Poznámka.Značka ABI POZNÁMKA 0000000000400254 00000254
0000000000000020 0000000000000000 A 0 0 4
[3] .Poznámka.gnu.build-i POZNÁMKA 0000000000400274 00000274
…
…
[26] .shstrtab STRTAB 0000000000000000 0000e334
00000000000000ef 0000000000000000 0 0 1
Klíč k vlajkám:
W (zápis), A (přidělení), X (provedení), M (sloučení), S (řetězce), l (velký)
I (informace), L (pořadí odkazů), G (skupina), T (TLS), E (vyloučit), x (neznámé)
O (je vyžadováno další zpracování OS) o (specifické pro OS), p (specifické pro procesor)
Nástroje pro analýzu souboru ELF
Jak jste si mohli všimnout z výše uvedených příkladů, GNU / Linux je doplněn řadou užitečných nástrojů, které vám pomohou analyzovat soubor ELF. Prvním kandidátem, na kterého se podíváme, je obslužný program souborů.
soubor zobrazuje základní informace o souborech ELF, včetně architektury instrukční sady, pro kterou je kód v přemístitelném, spustitelném nebo sdíleném objektu určen. V seznamu 6 vám říká, že / bin / touch je 64bitový spustitelný soubor podle Linux Standard Base (LSB), dynamicky propojený a vytvořený pro jádro GNU / Linux verze 2.6.32.
.Výpis 6: Základní informace pomocí souboru
$ file / bin / touch/ bin / touch: ELF 64bitový LSB spustitelný, x86-64, verze 1 (SYSV), dynamicky propojený, tlumočník / lib64 / l,
pro GNU / Linux 2.6.32, BuildID [sha1] = ec08d609e9e8e73d4be6134541a472ad0ea34502, odstraněno
$
Druhým kandidátem je sám sebe. Zobrazuje podrobné informace o souboru ELF. Seznam přepínačů je srovnatelně dlouhý a zahrnuje všechny aspekty formátu ELF. Použití přepínače -n (zkratka pro -notes) Výpis 7 zobrazuje pouze sekce poznámek, které existují v dotyku souboru - tag verze ABI a bitstring ID sestavení.
.Výpis 7: Zobrazit vybrané části souboru ELF
$ readelf -n / usr / bin / touchZobrazení poznámek nalezených v offsetu souboru 0x00000254 s délkou 0x00000020:
Vlastník Velikost dat Popis
GNU 0x00000010 NT_GNU_ABI_TAG (značka verze ABI)
OS: Linux, ABI: 2.6.32
Zobrazení poznámek nalezených v offsetu souboru 0x00000274 s délkou 0x00000024:
Vlastník Velikost dat Popis
GNU 0x00000014 NT_GNU_BUILD_ID (jedinečný bitstring ID sestavení)
ID sestavení: ec08d609e9e8e73d4be6134541a472ad0ea34502
Všimněte si, že v systémech Solaris a FreeBSD odpovídá nástroj elfdump [7] readelf. Od roku 2019 od roku 2003 nedošlo k novému vydání nebo aktualizaci.
Číslo tři je balíček s názvem elfutils [6], který je čistě dostupný pro Linux. Poskytuje alternativní nástroje k GNU Binutils a také umožňuje ověřovat soubory ELF. Všimněte si, že všechny názvy nástrojů poskytovaných v balíčku začínají eu pro 'elf utils'.
V neposlední řadě zmíníme objdump. Tento nástroj je podobný readelf, ale zaměřuje se na soubory objektů. Poskytuje podobnou škálu informací o souborech ELF a dalších formátech objektů.
.Výpis 8: Informace o souboru extrahované objdump
$ objdump -f / bin / touch/ bin / touch: formát souboru elf64-x86-64
architektura: i386: x86-64, příznaky 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
počáteční adresa 0x00000000004025e3
$
Existuje také softwarový balíček s názvem „elfkickers“ [9], který obsahuje nástroje pro čtení obsahu souboru ELF a jeho manipulaci. Počet vydání je bohužel poměrně nízký, a proto jej pouze zmíníme a neukážeme další příklady.
Jako vývojář se místo toho můžete podívat na 'pax-utils' [10,11]. Tato sada nástrojů poskytuje řadu nástrojů, které pomáhají ověřovat soubory ELF. Například dumpelf analyzuje soubor ELF a vrátí soubor záhlaví C obsahující podrobnosti - viz obrázek 2.
Závěr
Díky kombinaci chytrého designu a vynikající dokumentace formát ELF funguje velmi dobře a je používán i po 20 letech. Výše uvedené nástroje vám umožňují nahlédnout do souboru ELF a umožňují vám zjistit, co program dělá. Toto jsou první kroky pro analýzu softwaru - šťastný hacking!
Odkazy a reference
- [1] Spustitelný a spojitelný formát (ELF), Wikipedia
- [2] Fuchsia OS
- [3] Porovnání formátů spustitelných souborů, Wikipedia
- [4] Linux Foundation, odkazované specifikace
- [5] Ciro Santilli: Výukový program Hello World ELF
- [6] balíček elfutils Debian
- [7] elfdump
- [8] Michael Boelen: 101 souborů ELF v systému Linux: porozumění a analýza
- [9] elfkickers
- [10] Tvrzené / PaX nástroje
- [11] pax-utils, balíček Debianu
Poděkování
Spisovatel by chtěl poděkovat Axelovi Beckertovi za jeho podporu při přípravě tohoto článku.