Az ELF fájlformátum megértése

Understanding Elf File Format



A forráskódtól a bináris kódig

A programozás azzal kezdődik, hogy van egy okos ötletünk, és a forráskódot egy tetszőleges programozási nyelven, például C -ben írjuk, és a forráskódot fájlba mentjük. Egy megfelelő fordító, például a GCC segítségével a forráskódot először objektumkódra fordítják le. Végül a linker lefordítja az objektumkódot egy bináris fájlba, amely összekapcsolja az objektumkódot a hivatkozott könyvtárakkal. Ez a fájl az egyetlen utasításokat gépi kódként tartalmazza, amelyeket a CPU megért, és a fordított program futtatása után végrehajtásra kerülnek.

A fent említett bináris fájl egy speciális struktúrát követ, és az egyik leggyakoribb az ELF név, amely a végrehajtható és a linkelhető formátumot rövidíti. Széles körben használják futtatható fájlokhoz, áthelyezhető objektumfájlokhoz, megosztott könyvtárakhoz és alapvető lerakatokhoz.







Húsz évvel ezelőtt-1999-ben-a 86open projekt az ELF-et választotta szabványos bináris fájlformátumként a Unix és Unix-szerű rendszerekhez x86 processzorokon. Szerencsére az ELF formátumot korábban már dokumentálták a System V Application Binary Interface és a Tool Interface Standard [4] szabványokban. Ez a tény rendkívül leegyszerűsítette a Unix-alapú operációs rendszerek különböző gyártói és fejlesztői közötti szabványosítási megállapodást.



Ennek a döntésnek az oka az ELF kialakítása volt-rugalmasság, bővíthetőség és platformok közötti támogatás a különböző endiánus formátumokhoz és címméretekhez. Az ELF tervezése nem korlátozódik egy adott processzorra, utasításkészletre vagy hardver architektúrára. A végrehajtható fájlformátumok részletes összehasonlítását itt találja [3].



Azóta az ELF formátumot számos különböző operációs rendszer használja. Ide tartozik többek között a Linux, a Solaris/Illumos, a Free-, a Net- és az OpenBSD, a QNX, a BeOS/Haiku és a Fuchsia OS [2]. Továbbá megtalálható Android, Maemo vagy Meego OS/Sailfish operációs rendszert futtató mobileszközökön, valamint olyan játékkonzolokon, mint a PlayStation Portable, a Dreamcast és a Wii.





A specifikáció nem tisztázza az ELF fájlok fájlnévkiterjesztését. Különféle betűkombinációk használatban vannak, például .axf, .bin, .elf, .o, .prx, .puff, .ko, .so és .mod, vagy nincs.

Az ELF fájl felépítése

Linux terminálon a man elf parancs egy praktikus összefoglalót ad az ELF fájl felépítéséről:



1. lista: Az ELF struktúra kezelőlapja

$ férfi tizenegy

ELF (5) Linux programozó kézikönyv ELF (5)

NÉV
elf - Végrehajtható és összekapcsolható formátumú (ELF) fájlok formátuma

SZINOPSZIS
#befoglalni

LEÍRÁS
A fejlécfájl határozza meg az ELF futtatható bináris formátumát
fájlokat. Ezen fájlok között vannak normál futtatható fájlok, áthelyezhetők
objektumfájlok, alapvető fájlok és megosztott könyvtárak.

Az ELF fájlformátumot használó futtatható fájl egy ELF fejlécből áll,
ezt követi egy program fejléc táblázat vagy egy szakasz fejléc táblázat, vagy mindkettő.
Az ELF fejléc mindig a fájl nulla eltolásával van. A program
fejléc táblázat és a szakasz fejléc táblázat eltolása a fájlban
az ELF fejlécében definiált. A két táblázat leírja a többi
az irat sajátosságai.

...

Amint a fenti leírásból látható, az ELF fájl két részből áll - egy ELF fejlécből és a fájladatokból. A fájladat -szakasz tartalmazhat egy programfejléc -táblázatot, amely nulla vagy több szegmenst ír le, egy szakaszfejléc -táblázatot, amely leírja a nulla vagy több szakaszt, amelyet a programfejléc -táblázat bejegyzései által hivatkozott adatok követnek, és a szakaszfejléc -táblázatot. Minden szegmens olyan információkat tartalmaz, amelyek a fájl futási idejű végrehajtásához szükségesek, míg a szakaszok fontos adatokat tartalmaznak az összekapcsoláshoz és az áthelyezéshez. Az 1. ábra ezt sematikusan szemlélteti.

Az ELF fejléce

Az ELF fejléc 32 bájt hosszú, és azonosítja a fájl formátumát. Négy egyedi bájtos szekvenciával kezdődik, amelyek 0x7F, majd 0x45, 0x4c és 0x46, amelyek három E, L és F betűvé alakulnak. Többek között a fejléc azt is jelzi, hogy ez egy ELF fájl 32 vagy 64 bites formátum, kis vagy nagy végtelenséget használ, megmutatja az ELF verziót, valamint azt, hogy a fájl melyik operációs rendszerhez lett összeállítva, hogy együttműködjön a megfelelő alkalmazás bináris interfésszel (ABI) és a CPU utasításkészlettel.

A bináris fájl érintésének hexdumpja a következőképpen néz ki:

. 2. lista: A bináris fájl hexdumpja

$ hd/usr/bin/touch | fej -5
00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 | .MAGA ........... |
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 | [email protected] @..... |
00000040 06 00 00 00 05 00 00 00 40 00 00 00 00 00 00 | | [email védett] |

A Debian GNU/Linux felajánlja a GNU „binutils” csomagban található readelf parancsot. A -h kapcsolóval együtt (rövid verzió a –file -header számára) szépen megjeleníti az ELF fájl fejlécét. A 3. lista ezt szemlélteti a parancsérintéshez.

. 3. lista: ELF fájl fejlécének megjelenítése

$ readelf -h/usr/bin/touch
ELF fejléc:
Varázslat: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Osztály: ELF64
Adatok: 2 kiegészítése, kis endián
Verzió: 1 (aktuális)
OS / ABI: UNIX - V rendszer
ABI verzió: 0
Típus: EXEC (végrehajtható fájl)
Gép: Advanced Micro Devices X86-64
Verzió: 0x1
Belépési pont címe: 0x4025e3
A program fejléceinek kezdete: 64 (bájt fájlba)
A szakasz fejlécének kezdete: 58408 (bájt fájlba)
Zászlók: 0x0
A fejléc mérete: 64 (bájt)
A programfejlécek mérete: 56 (bájt)
Programfejlécek száma: 9
A szakasz fejléceinek mérete: 64 (bájt)
Szakaszfejlécek száma: 27
Szakasz fejléc karakterlánc táblázat index: 26

A program fejléce

A program fejléce megmutatja a futás közben használt szegmenseket, és megmondja a rendszernek, hogyan hozhat létre folyamatképet. A 2. lista fejléce azt mutatja, hogy az ELF fájl 9 programfejlécből áll, amelyek egyenként 56 bájtosak, és az első fejléc 64 bájtnál kezdődik.

Ismét a readelf parancs segít kinyerni az információkat az ELF fájlból. Az -l kapcsoló (a –program -fejlécek vagy –szegmensek rövidítése) további részleteket tár fel, amint azt a 4. lista mutatja.

. 4. lista: Információk megjelenítése a program fejléceiről

$ readelf -l/usr/bin/touch

Az elf fájltípus EXEC (végrehajtható fájl)
Belépési pont 0x4025e3
9 programfejléc van, a 64 eltolással kezdve

Programfejlécek:
Típus Offset VirtAddr PhysAddr
FileSiz MemSiz jelzők igazítása
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000001f8 0x00000000000001f8 R E 8
INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238
0x000000000000001c 0x000000000000001c R 1
[Programtolmács kérése: /lib64/ld-linux-x86-64.so.2]
TERHELÉS 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x000000000000d494 0x000000000000d494 R E 200000
LOAD 0x000000000000de10 0x000000000060de10 0x0000000000606010
0x0000000000000524 0x0000000000000748 RW 200000
DINAMIKUS 0x000000000000de28 0x000000000060de28 0x0000000000606028
0x00000000000001d0 0x00000000000001d0 RW 8
MEGJEGYZÉS 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

Szakasz -szegmens leképezés:
Szakaszszakaszok ...
00
01 .interp
02 .interp .megjegyzés.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 .dinamikus
05 .megjegyzés.ABI-tag .note.gnu.build-id
06 .eh_frame_hdr
07
08 .init_array .fini_array .jcr .dynamic .got

A szakasz fejléce

Az ELF szerkezet harmadik része a szakaszfejléc. Célja a bináris egyes szakaszainak felsorolása. A -S kapcsoló (röviden –section -headers vagy –sections) felsorolja a különböző fejléceket. Ami az érintőparancsot illeti, 27 szakaszfejléc van, és az 5. lista csak az első négyet és az utolsót mutatja. Minden sor lefedi a szakasz méretét, a szakasz típusát, valamint címét és memóriaeltolását.

. 5. lista: A szakasz részletei önmaguk által felfedve

$ readelf -S/usr/bin/touch
27 szakaszfejléc van, a 0xe428 eltolással kezdve:

Szakasz fejlécei:
[Nr] Név Típus Cím Eltolás
Méret EntSize Flags Link Info Align
[0] NULL 0000000000000000 00000000
0000000000000000 000000000000000000 0 0 0
[1] .interp PROGBITS 0000000000400238 00000238
000000000000001c 0000000000000000 A 0 0 1
[2] .megjegyzés.ABI-tag MEGJEGYZÉS 0000000000400254 00000254
0000000000000020 000000000000000000 A 0 0 4
[3] .note.gnu.build-i MEGJEGYZÉS 0000000000400274 00000274
...
...
[26] .shstrtab STRTAB 0000000000000000 0000e334
00000000000000ef 0000000000000000 0 0 1
Kulcs a zászlókhoz:
W (írás), A (alloc), X (végrehajtás), M (egyesítés), S (karakterláncok), l (nagy)
I (info), L (linkek sorrendje), G (csoport), T (TLS), E (kizárás), x (ismeretlen)
O (extra operációs rendszer -feldolgozás szükséges) o (operációs rendszer -specifikus), p (processzor -specifikus)

Eszközök egy ELF fájl elemzéséhez

Amint azt a fenti példákból már megjegyezte, a GNU/Linux számos hasznos eszközzel rendelkezik, amelyek segítenek az ELF fájl elemzésében. Az első jelölt, akit megvizsgálunk, a fájl segédprogram.

fájl alapvető információkat jelenít meg az ELF fájlokról, beleértve azokat az utasításkészletek architektúráját, amelyekhez az áthelyezhető, végrehajtható vagy megosztott objektumfájlban található kódot szánják. A 6. listában azt mondja, hogy a/bin/touch egy 64 bites futtatható fájl, amely a Linux Standard Base (LSB) szabványt követi, dinamikusan összekapcsolva, és a GNU/Linux 2.6.32-es verzióhoz készült.

. 6. lista: Alapvető információk fájl használatával

$ file /bin /touch
/bin/touch: ELF 64 bites LSB futtatható, x86-64, 1-es verzió (SYSV), dinamikusan linkelt, tolmács/lib64/l,
GNU/Linux 2.6.32 esetén, BuildID [sha1] = ec08d609e9e8e73d4be6134541a472ad0ea34502, lecsupaszítva
$

A második jelölt önmaga. Részletes információkat jelenít meg egy ELF fájlról. A kapcsolók listája viszonylag hosszú, és lefedi az ELF formátum minden aspektusát. A -n kapcsolóval (röviden –notes) A ​​7. lista csak azokat a megjegyzésrészeket mutatja, amelyek a fájl érintésében léteznek -az ABI verziócímkét és a build azonosító bitstringet.

. 7. lista: Az ELF fájl kiválasztott szakaszainak megjelenítése

$ readelf -n/usr/bin/touch

A 0x00000254 fájl eltolásában talált megjegyzések megjelenítése 0x00000020 hosszúsággal:
Tulajdonos Adatok mérete Leírás
GNU 0x00000010 NT_GNU_ABI_TAG (ABI verziócímke)
Operációs rendszer: Linux, ABI: 2.6.32

A 0x00000274 fájlkorrekcióban talált megjegyzések megjelenítése 0x00000024 hosszúsággal:
Tulajdonos Adatok mérete Leírás
GNU 0x00000014 NT_GNU_BUILD_ID (egyedi build azonosító bitstring)
Építési azonosító: ec08d609e9e8e73d4be6134541a472ad0ea34502

Vegye figyelembe, hogy a Solaris és a FreeBSD alatt az elfdump segédprogram [7] megfelel a readelf -nek. 2019 -től 2003 óta nem volt új kiadás vagy frissítés.

A harmadik szám az elfutils [6] nevű csomag, amely pusztán Linux számára elérhető. Alternatív eszközöket biztosít a GNU Binutils számára, és lehetővé teszi az ELF fájlok érvényesítését is. Ne feledje, hogy a csomagban található segédprogramok összes neve az „elf utils” eu -val kezdődik.

Végül, de nem utolsósorban megemlítjük az objdumpot. Ez az eszköz hasonló a readelf -hez, de az objektumfájlokra összpontosít. Hasonló információt nyújt az ELF fájlokról és más objektumformátumokról.

. 8. lista: Az objdump által kinyert fájlinformációk

$ objdump -f /bin /touch

/bin/touch: fájlformátum elf64-x86-64
architektúra: i386: x86-64, zászlók 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
kezdőcím 0x00000000004025e3

$

Van egy „elfkickers” [9] nevű szoftvercsomag is, amely eszközöket tartalmaz az ELF fájl tartalmának olvasásához és kezeléséhez. Sajnos a kiadások száma meglehetősen alacsony, ezért csak megemlítjük, és nem mutatunk további példákat.

Fejlesztőként ehelyett megnézheti a „pax-utils” [10,11]. Ez a segédprogram számos olyan eszközt kínál, amelyek segítenek az ELF fájlok ellenőrzésében. Például a dumpelf elemzi az ELF fájlt, és visszaad egy C fejléc fájlt, amely tartalmazza a részleteket - lásd 2. ábra.

Következtetés

Az okos tervezés és a kiváló dokumentáció kombinációjának köszönhetően az ELF formátum nagyon jól működik, és 20 év után is használatban van. A fent bemutatott segédprogramok betekintést nyújtanak egy ELF fájlba, és megtudhatják, mit csinál egy program. Ezek az első lépések a szoftverek elemzéséhez - boldog hackelést!

Hivatkozások és hivatkozások
Köszönetnyilvánítás

Az író köszönetet mond Axel Beckertnek a cikk elkészítéséhez nyújtott támogatásáért.