ELF

Înțelegerea formatului de fișier ELF

Înțelegerea formatului de fișier ELF

De la codul sursă la codul binar

Programarea începe cu o idee inteligentă și scrierea codului sursă într-un limbaj de programare la alegere, de exemplu C, și salvarea codului sursă într-un fișier. Cu ajutorul unui compilator adecvat, de exemplu GCC, primul cod sursă este tradus în cod obiect. În cele din urmă, linkerul traduce codul obiect într-un fișier binar care leagă codul obiect cu bibliotecile la care se face referire. Acest fișier conține instrucțiunile unice ca cod de mașină care sunt înțelese de CPU și sunt executate imediat ce programul compilat este rulat.

Fișierul binar menționat mai sus urmează o structură specifică, iar unul dintre cele mai frecvente se numește ELF care prescurtează Executable and Linkable Format. Este utilizat pe scară largă pentru fișiere executabile, fișiere obiect relocabile, biblioteci partajate și depozite de bază.

Acum douăzeci de ani - în 1999 - proiectul 86open a ales ELF ca format de fișier binar standard pentru sistemele Unix și Unix-like pe procesoarele x86. Din fericire, formatul ELF a fost documentat anterior atât în ​​interfața binară de aplicație System V, cât și în standardul de interfață instrument [4]. Acest fapt a simplificat enorm acordul de standardizare între diferiții furnizori și dezvoltatori de sisteme de operare bazate pe Unix.

Motivul din spatele acestei decizii a fost proiectarea ELF - flexibilitate, extensibilitate și suport multiplataforma pentru diferite formate endian și dimensiuni de adresă. Proiectarea ELF nu se limitează la un anumit procesor, set de instrucțiuni sau arhitectură hardware. Pentru o comparație detaliată a formatelor de fișiere executabile, aruncați o privire aici [3].

De atunci, formatul ELF este utilizat de mai multe sisteme de operare diferite. Printre altele, acesta include Linux, Solaris / Illumos, Free-, Net- și OpenBSD, QNX, BeOS / Haiku și Fuchsia OS [2]. Mai mult, îl veți găsi pe dispozitive mobile care rulează Android, Maemo sau Meego OS / Sailfish OS, precum și pe console de jocuri precum PlayStation Portable, Dreamcast și Wii.

Specificația nu clarifică extensia numelui de fișier pentru fișierele ELF. În uz este o varietate de combinații de litere, cum ar fi .axf, .cos, .elf, .o, .prx, .sufla, .ko, .deci si .mod sau none.

Structura unui fișier ELF

Pe un terminal Linux, comanda man elf vă oferă un rezumat la îndemână despre structura unui fișier ELF:

Listarea 1: Pagina de manual a structurii ELF

$ om elf
ELF (5) Manual pentru programator Linux ELF (5)
NUME
elf - formatul fișierelor Executable and Linking Format (ELF)
REZUMAT
#include
DESCRIERE
Fișierul antet definește formatul binarului executabil ELF
fișiere. Printre aceste fișiere se află fișiere executabile normale, relocabile
fișiere obiect, fișiere de bază și biblioteci partajate.
Un fișier executabil care utilizează formatul de fișier ELF constă dintr-un antet ELF,
urmat de un tabel de antet de program sau un tabel de antet de secțiune, sau ambele.
Antetul ELF este întotdeauna la zero de offset al fișierului. Programul
tabelul de antet și decalajul tabelului de antet din secțiune sunt
definit în antetul ELF. Cele două tabele descriu restul
particularitățile fișierului.
..

După cum puteți vedea din descrierea de mai sus, un fișier ELF constă din două secțiuni - un antet ELF și date de fișier. Secțiunea de date a fișierului poate consta dintr-un tabel de antet de program care descrie zero sau mai multe segmente, un tabel de antet de secțiune care descrie zero sau mai multe secțiuni, care este urmat de date menționate de intrări din tabelul de antet de program și tabelul de antet de secțiune. Fiecare segment conține informații necesare execuției în timp de execuție a fișierului, în timp ce secțiunile conțin date importante pentru conectare și relocare. Figura 1 ilustrează schematic acest lucru.

Antetul ELF

Antetul ELF are o lungime de 32 de octeți și identifică formatul fișierului. Începe cu o secvență de patru octeți unici care sunt 0x7F urmată de 0x45, 0x4c și 0x46 care se traduce în cele trei litere E, L și F. Printre alte valori, antetul indică, de asemenea, dacă este un fișier ELF pentru formatul de 32 sau 64 de biți, folosește un endianness mic sau mare, arată versiunea ELF, precum și pentru ce sistem de operare a fost compilat fișierul pentru a interopera cu interfață binară corectă a aplicației (ABI) și set de instrucțiuni CPU.

Descărcarea hexagonală a atingerii fișierului binar arată după cum urmează:

.Listarea 2: hexdump-ul fișierului binar

$ hd / usr / bin / touch | cap -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 | [e-mail protejat] @… |
00000040 06 00 00 00 05 00 00 00 40 00 00 00 00 00 00 00 00 | [e-mail protejat] |

Debian GNU / Linux oferă comanda readelf care este furnizată în pachetul GNU „binutils”. Însoțit de comutatorul -h (versiune scurtă pentru „-file-header”) afișează frumos antetul unui fișier ELF. Listarea 3 ilustrează acest lucru pentru atingerea comenzii.

.Listarea 3: Afișarea antetului unui fișier ELF

$ readelf -h / usr / bin / touch
Antet ELF:
Magie: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 00 00
Clasa: ELF64
Date: complement 2, puțin endian
Versiune: 1 (actual)
OS / ABI: UNIX - Sistemul V
Versiunea ABI: 0
Tip: EXEC (fișier executabil)
Aparat: Advanced Micro Devices X86-64
Versiune: 0x1
Adresa punctului de intrare: 0x4025e3
Începutul antetelor programului: 64 (octeți în fișier)
Începutul antetelor secțiunii: 58408 (octeți în fișier)
Steaguri: 0x0
Dimensiunea acestui antet: 64 (octeți)
Dimensiunea antetelor programului: 56 (octeți)
Număr de antete de program: 9
Dimensiunea antetelor de secțiune: 64 (octeți)
Număr de antete de secțiune: 27
Indexul tabelului șirului antetului secțiunii: 26

Antetul programului

Antetul programului arată segmentele utilizate în timpul rulării și îi spune sistemului cum să creeze o imagine de proces. Antetul din Listarea 2 arată că fișierul ELF este format din 9 antete de program care au dimensiunea de 56 de octeți fiecare, iar primul antet începe de la octeții 64.

Din nou, comanda readelf ajută la extragerea informațiilor din fișierul ELF. Comutatorul -l (prescurtarea pentru -program-headers sau -segments) dezvăluie mai multe detalii așa cum se arată în Listarea 4.

.Listarea 4: Afișați informații despre antetele programului

$ readelf -l / usr / bin / touch
Tipul de fișier ELF este EXEC (fișier executabil)
Punct de intrare 0x4025e3
Există 9 anteturi de program, începând cu offset 64
Anteturile programului:
Tastați Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000001f8 0x00000000000001f8 R E 8
INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238
0x000000000000001c 0x000000000000001c R 1
[Solicitarea interpretului de program: / lib64 / ld-linux-x86-64.asa de.2]
ÎNCĂRCARE 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x000000000000d494 0x000000000000d494 R E 200000
ÎNCĂRCARE 0x000000000000de10 0x000000000060de10 0x000000000060de10
0x0000000000000524 0x0000000000000748 RW 200000
DINAMIC 0x000000000000de28 0x000000000060de28 0x000000000060de28
0x00000000000001d0 0x00000000000001d0 RW 8
NOTĂ 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 0x00000000000060de10 0x000000000060de10
0x00000000000001f0 0x00000000000001f0 R 1
Secțiunea la cartografierea segmentată:
Segmentează secțiuni ..
00
01 .interp
02 .interp .Notă.Etichetă ABI .Notă.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.versiune .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .jcr .dinamic .a primit .a primit.plt .date .bss
04 .dinamic
05 .Notă.Etichetă ABI .Notă.gnu.build-id
06 .eh_frame_hdr
07
08 .init_array .fini_array .jcr .dinamic .a primit

Antetul secțiunii

A treia parte a structurii ELF este antetul secțiunii. Este menit să enumere secțiunile unice ale binarului. Comutatorul -S (prescurtare pentru -section-headers sau -sections) listează diferitele anteturi. În ceea ce privește comanda tactilă, există 27 de anteturi de secțiune, iar Listarea 5 arată primele patru dintre ele plus ultimul, doar. Fiecare linie acoperă dimensiunea secțiunii, tipul secțiunii, precum și adresa și decalajul de memorie.

.Listarea 5: Detaliile secțiunii dezvăluite de readelf

$ readelf -S / usr / bin / touch
Există 27 de antete de secțiune, începând cu offset 0xe428:
Anteturi de secțiune:
[Nr] Tip de nume Adresă Offset
Dimensiune EntSize Steaguri Informații link Aliniere
[0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[1] .interp PROGBITS 0000000000400238 00000238
000000000000001c 0000000000000000 A 0 0 1
[2] .Notă.ABI-tag NOTĂ 0000000000400254 00000254
0000000000000020 0000000000000000 A 0 0 4
[3] .Notă.gnu.build-i NOTĂ 0000000000400274 00000274
..
..
[26] .shstrtab STRTAB 0000000000000000 0000e334
00000000000000ef 0000000000000000 0 0 1
Cheia steagurilor:
W (scriere), A (alocare), X (executare), M (îmbinare), S (șiruri), l (mare)
I (informații), L (comanda link-ului), G (grup), T (TLS), E (exclude), x (necunoscut)
O (este necesară procesarea suplimentară a sistemului de operare)

Instrumente pentru analiza unui fișier ELF

După cum probabil ați observat din exemplele de mai sus, GNU / Linux este completat cu o serie de instrumente utile care vă ajută să analizați un fișier ELF. Primul candidat pe care îl vom analiza este utilitarul de fișiere.

fișier afișează informații de bază despre fișierele ELF, inclusiv arhitectura setului de instrucțiuni pentru care este destinat codul dintr-un fișier obiect relocabil, executabil sau partajat. În lista 6 vă spune că / bin / touch este un fișier executabil pe 64 de biți care urmează Linux Standard Base (LSB), conectat dinamic și construit pentru kernel-ul GNU / Linux versiunea 2.6.32.

.Listarea 6: Informații de bază folosind fișier

$ file / bin / touch
/ bin / touch: executabil ELF pe 64 de biți LSB, x86-64, versiunea 1 (SYSV), legat dinamic, interpret / lib64 / l,
pentru GNU / Linux 2.6.32, BuildID [sha1] = ec08d609e9e8e73d4be6134541a472ad0ea34502, dezbrăcat
$

Al doilea candidat este readelf. Afișează informații detaliate despre un fișier ELF. Lista de comutatoare este relativ lungă și acoperă toate aspectele formatului ELF. Utilizarea comutatorului -n (prescurtare pentru -note) Listarea 7 prezintă numai secțiunile de notă care există în atingerea fișierului - eticheta de versiune ABI și șirul de biți ID de construcție.

.Listarea 7: Afișați secțiunile selectate ale unui fișier ELF

$ readelf -n / usr / bin / touch
Afișarea notelor găsite la fișierul offset 0x00000254 cu lungimea 0x00000020:
Proprietar Dimensiune date Descriere
GNU 0x00000010 NT_GNU_ABI_TAG (etichetă versiune ABI)
Sistem de operare: Linux, ABI: 2.6.32
Afișarea notelor găsite la offsetul fișierului 0x00000274 cu lungimea 0x00000024:
Proprietar Dimensiune date Descriere
GNU 0x00000014 NT_GNU_BUILD_ID (șir de biți ID de construcție unic)
ID compilare: ec08d609e9e8e73d4be6134541a472ad0ea34502

Rețineți că sub Solaris și FreeBSD, utilitarul elfdump [7] corespunde cu readelf. Începând din 2019, nu a mai existat o nouă versiune sau actualizare din 2003.

Numărul trei este pachetul numit elfutils [6] care este pur disponibil pentru Linux. Oferă instrumente alternative la GNU Binutils și permite, de asemenea, validarea fișierelor ELF. Rețineți că toate numele utilitarelor furnizate în pachet încep cu eu pentru „elf utils”.

Nu în ultimul rând vom menționa objdump. Acest instrument este similar cu readelf, dar se concentrează pe fișierele obiect. Oferă o gamă similară de informații despre fișierele ELF și alte formate de obiecte.

.Listarea 8: Informații despre fișiere extrase prin objdump

$ objdump -f / bin / touch
/ bin / touch: format de fișier elf64-x86-64
arhitectură: i386: x86-64, steaguri 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
adresa de pornire 0x00000000004025e3
$

Există, de asemenea, un pachet software numit „elfkickers” [9] care conține instrumente pentru a citi conținutul unui fișier ELF și pentru a-l manipula. Din păcate, numărul lansărilor este destul de redus și de aceea doar îl menționăm și nu prezentăm exemple suplimentare.

În calitate de dezvoltator, este posibil să aruncați o privire la „pax-utils” [10,11]. Acest set de utilități oferă o serie de instrumente care ajută la validarea fișierelor ELF. De exemplu, dumpelf analizează fișierul ELF și returnează un fișier antet C care conține detaliile - vezi Figura 2.

Concluzie

Datorită combinației de design inteligent și documentație excelentă, formatul ELF funcționează foarte bine și este încă în uz după 20 de ani. Utilitățile prezentate mai sus vă permit să vizualizați un fișier ELF și vă permit să vă dați seama ce face un program. Aceștia sunt primii pași pentru analiza software-ului - hacking-ul fericit!

Linkuri și referințe
  • [1] Format executabil și legabil (ELF), Wikipedia
  • [2] Fuchsia OS
  • [3] Compararea formatelor de fișiere executabile, Wikipedia
  • [4] Linux Foundation, Specificații de referință
  • [5] Ciro Santilli: Tutorial ELF Hello World
  • [6] pachetul Debian elfutils
  • [7] elfdump
  • [8] Michael Boelen: 101 de fișiere ELF pe Linux: Înțelegere și analiză
  • [9] elfkickers
  • [10] Utilități întărite / PaX
  • [11] pax-utils, pachetul Debian
Mulțumiri

Scriitorul ar dori să-i mulțumească lui Axel Beckert pentru sprijinul acordat în ceea ce privește pregătirea acestui articol.

Cele mai bune emulatoare pentru console de jocuri pentru Linux
Acest articol va enumera programele populare de emulare a consolei de jocuri disponibile pentru Linux. Emularea este un strat de compatibilitate softw...
Best Linux Distros for Gaming in 2021
The Linux operating system has come a long way from its original, simple, server-based look. This OS has immensely improved in recent years and has no...
Cum să capturați și să transmiteți în flux sesiunea de jocuri pe Linux
În trecut, jocurile erau considerate doar un hobby, dar cu timpul industria jocurilor a cunoscut o creștere imensă în ceea ce privește tehnologia și n...