NISSE

Forståelse af ELF-filformat

Forståelse af ELF-filformat

Fra kildekode til binær kode

Programmering starter med at have en klog idé og skrive kildekode på et programmeringssprog efter eget valg, for eksempel C, og gemme kildekoden i en fil. Ved hjælp af en passende kompilator, for eksempel GCC, oversættes din kildekode først til objektkode. Til sidst oversætter linkeren objektkoden til en binær fil, der linker objektkoden til de refererede biblioteker. Denne fil indeholder de enkelte instruktioner som maskinkode, der forstås af CPU'en, og udføres, så snart det kompilerede program køres.

Den ovennævnte binære fil følger en bestemt struktur, og en af ​​de mest almindelige er navngivet ELF, der forkortes Executable and Linkable Format. Det bruges i vid udstrækning til eksekverbare filer, flyttbare objektfiler, delte biblioteker og kernedumps.

For tyve år siden - i 1999 - har 86open-projektet valgt ELF som standard binært filformat til Unix og Unix-lignende systemer på x86-processorer. Heldigvis var ELF-formatet tidligere blevet dokumenteret i både System V Application Binary Interface og Tool Interface Standard [4]. Denne kendsgerning forenklede enormt aftalen om standardisering mellem de forskellige leverandører og udviklere af Unix-baserede operativsystemer.

Årsagen til denne beslutning var designet af ELF - fleksibilitet, udvidelighed og support på tværs af platforme til forskellige endianformater og adressestørrelser. ELFs design er ikke begrænset til en bestemt processor, instruktionssæt eller hardwarearkitektur. For en detaljeret sammenligning af eksekverbare filformater, se her [3].

Siden da er ELF-formatet brugt af flere forskellige operativsystemer. Dette inkluderer blandt andet Linux, Solaris / Illumos, Free-, Net- og OpenBSD, QNX, BeOS / Haiku og Fuchsia OS [2]. Desuden finder du det på mobile enheder, der kører Android, Maemo eller Meego OS / Sailfish OS såvel som på spilkonsoller som PlayStation Portable, Dreamcast og Wii.

Specifikationen præciserer ikke filtypenavnet for ELF-filer. I brug er en række bogstavkombinationer, såsom .axf, .beholder, .nisse, .o, .prx, .pust, .ko, .så, og .mod eller ingen.

Strukturen i en ELF-fil

På en Linux-terminal giver kommandoen man elf dig et praktisk resumé om strukturen i en ELF-fil:

Liste 1: ELF-strukturens manpage

$ mand alf
ELF (5) Linux Programmer's Manual ELF (5)
NAVN
elf - format af eksekverbare og ELF-filer (Linking Format)
SYNOPSIS
#omfatte
BESKRIVELSE
Overskriftsfilen definerer formatet for ELF-eksekverbar binær
filer. Blandt disse filer er normale eksekverbare filer, der kan flyttes
objektfiler, kernefiler og delte biblioteker.
En eksekverbar fil, der bruger ELF-filformatet, består af en ELF-header,
efterfulgt af en programoverskriftstabel eller en sektionstabel eller begge dele.
ELF-headeren er altid ved offset nul for filen. Programmet
header-tabel og sektionens header-tabel's forskydning i filen er
defineret i ELF-headeren. De to tabeller beskriver resten af
filens særlige forhold.
..

Som du kan se fra beskrivelsen ovenfor, består en ELF-fil af to sektioner - en ELF-header og fildata. Fildatasektionen kan bestå af en programoverskriftstabel, der beskriver nul eller flere segmenter, en sektionsoverskriftstabel, der beskriver nul eller flere sektioner, der efterfølges af data, der henvises til af poster fra programoverskriftstabellen, og sektionens overskriftstabel. Hvert segment indeholder oplysninger, der er nødvendige for kørsel af filen, mens sektioner indeholder vigtige data til sammenkædning og flytning. Figur 1 illustrerer dette skematisk.

ELF-headeren

ELF-headeren er 32 byte lang og identificerer filens format. Det starter med en sekvens på fire unikke bytes, der er 0x7F efterfulgt af 0x45, 0x4c og 0x46, der oversættes til de tre bogstaver E, L og F. Blandt andre værdier angiver overskriften også, om det er en ELF-fil til 32- eller 64-bit-format, bruger lidt eller stor endianness, viser ELF-versionen samt for hvilket operativsystem filen blev kompileret til for at kunne samarbejde med højre binære interface (ABI) og cpu-instruktionssæt.

Hexdumpen af ​​den binære filberøring ser således ud:

.Liste 2: Hexdump af den binære fil

$ hd / usr / bin / touch | hoved -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 | [email protected] @… |
00000040 06 00 00 00 05 00 00 00 40 00 00 00 00 00 00 00 | [email protected] |

Debian GNU / Linux tilbyder readelf-kommandoen, der findes i GNU 'binutils' -pakken. Ledsaget af switch -h (kort version til "-fil-header") viser det pænt overskriften på en ELF-fil. Liste 3 illustrerer dette for kommandotouch.

.Liste 3: Visning af headeren på en ELF-fil

$ readelf -h / usr / bin / touch
ELF header:
Magi: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Klasse: ELF64
Data: 2's komplement, lille endian
Version: 1 (nuværende)
OS / ABI: UNIX - System V
ABI-version: 0
Type: EXEC (eksekverbar fil)
Maskine: Avancerede mikroenheder X86-64
Version: 0x1
Indgangsadresse: 0x4025e3
Start af programoverskrifter: 64 (bytes i fil)
Start af sektionsoverskrifter: 58408 (bytes i fil)
Flag: 0x0
Størrelse på denne overskrift: 64 (bytes)
Størrelse på programoverskrifter: 56 (bytes)
Antal programoverskrifter: 9
Størrelse på sektionsoverskrifter: 64 (bytes)
Antal sektionsoverskrifter: 27
Sektionsoverskrift strengindeks: 26

Programoverskriften

Programoverskriften viser de segmenter, der er brugt under kørsel, og fortæller systemet, hvordan man opretter et procesbillede. Overskriften fra liste 2 viser, at ELF-filen består af 9 programoverskrifter, der hver har en størrelse på 56 byte, og den første overskrift starter ved byte 64.

Igen hjælper readelf-kommandoen med at udtrække oplysningerne fra ELF-filen. Omskifteren -l (kort for -program-headere eller -segmenter) afslører flere detaljer som vist i liste 4.

.Liste 4: Vis oplysninger om programoverskrifterne

$ readelf -l / usr / bin / touch
Elf-filtype er EXEC (eksekverbar fil)
Indgangspunkt 0x4025e3
Der er 9 programoverskrifter, der starter ved forskydning 64
Programoverskrifter:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000001f8 0x00000000000001f8 R E 8
INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238
0x000000000000001c 0x000000000000001c R 1
[Anmodende om programtolk: / lib64 / ld-linux-x86-64.så.2]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x000000000000d494 0x000000000000d494 R E 200000
LOAD 0x000000000000de10 0x000000000060de10 0x000000000060de10
0x0000000000000524 0x0000000000000748 RW 200000
DYNAMIC 0x000000000000de28 0x000000000060de28 0x000000000060de28
0x00000000000001d0 0x00000000000001d0 RW 8
BEMÆRK 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
Afsnit til segment kortlægning:
Segmentafsnit ..
00
01 .interp
02 .interp .Bemærk.ABI-tag .Bemærk.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .i det .plt .tekst .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .jcr .dynamisk .fik .fik.plt .data .bss
04 .dynamisk
05 .Bemærk.ABI-tag .Bemærk.gnu.build-id
06 .eh_frame_hdr
07
08 .init_array .fini_array .jcr .dynamisk .fik

Sektionens overskrift

Den tredje del af ELF-strukturen er sektionens overskrift. Det er meningen at liste de enkelte sektioner af binærsystemet. Afbryderen -S (kort for -sektion-headere eller -sections) viser de forskellige headers. Med hensyn til berøringskommandoen er der 27 sektionsoverskrifter, og liste 5 viser de første fire af dem plus den sidste, kun. Hver linje dækker sektionsstørrelsen, sektionstypen samt dens adresse og hukommelsesforskydning.

.Liste 5: Sektionsoplysninger afsløret af readelf

$ readelf -S / usr / bin / touch
Der er 27 sektionsoverskrifter, der starter ved forskydning 0xe428:
Sektionsoverskrifter:
[Nr] Navn Type Adresse Offset
Størrelse EntSize-flag Link Info Juster
[0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[1] .interp PROGBITS 0000000000400238 00000238
000000000000001c 0000000000000000 A 0 0 1
[2] .Bemærk.ABI-tag BEMÆRK 0000000000400254 00000254
0000000000000020 0000000000000000 A 0 0 4
[3] .Bemærk.gnu.build-i BEMÆRK 0000000000400274 00000274
..
..
[26] .shstrtab STRTAB 0000000000000000 0000e334
00000000000000ef 0000000000000000 0 0 1
Nøgle til flag:
W (skriv), A (allokering), X (udfør), M (flet), S (strenge), l (stor)
I (info), L (linkrækkefølge), G (gruppe), T (TLS), E (ekskluder), x (ukendt)
O (ekstra OS-behandling krævet) o (OS-specifik), p (processor-specifik)

Værktøjer til at analysere en ELF-fil

Som du måske har bemærket fra eksemplerne ovenfor, er GNU / Linux uddybet med et antal nyttige værktøjer, der hjælper dig med at analysere en ELF-fil. Den første kandidat, vi vil se på, er filværktøjet.

filen viser grundlæggende oplysninger om ELF-filer, herunder instruktions-sætarkitekturen, som koden i en flytbar, eksekverbar eller delt objektfil er beregnet til. I liste 6 fortæller det dig, at / bin / touch er en 64-bit eksekverbar fil, der følger Linux Standard Base (LSB), dynamisk forbundet og bygget til GNU / Linux-kerneversion 2.6.32.

.Liste 6: Grundlæggende information ved hjælp af fil

$ fil / bin / touch
/ bin / touch: ELF 64-bit LSB eksekverbar, x86-64, version 1 (SYSV), dynamisk forbundet, tolk / lib64 / l,
til GNU / Linux 2.6.32, BuildID [sha1] = ec08d609e9e8e73d4be6134541a472ad0ea34502, fjernet
$

Den anden kandidat er readelf. Det viser detaljerede oplysninger om en ELF-fil. Listen over kontakter er sammenlignelig lang og dækker alle aspekter af ELF-formatet. Brug af switch -n (kort for -noter) Listing 7 viser kun de noteafsnit, der findes i filberøringen - ABI-versionskoden og build-id-bitstrengen.

.Liste 7: Vis valgte sektioner af en ELF-fil

$ readelf -n / usr / bin / touch
Viser noter fundet ved filoffset 0x00000254 med længde 0x00000020:
Ejer Datastørrelse Beskrivelse
GNU 0x00000010 NT_GNU_ABI_TAG (ABI-versionskode)
Styresystem: Linux, ABI: 2.6.32
Viser noter fundet ved filforskydning 0x00000274 med længde 0x00000024:
Ejer Datastørrelse Beskrivelse
GNU 0x00000014 NT_GNU_BUILD_ID (unik build-id-bitstreng)
Bygge-id: ec08d609e9e8e73d4be6134541a472ad0ea34502

Bemærk, at under Solaris og FreeBSD svarer elfdump [7] med readelf. Fra og med 2019 har der ikke været en ny udgivelse eller opdatering siden 2003.

Nummer tre er pakken med navnet elfutils [6], der kun er tilgængelig for Linux. Det giver alternative værktøjer til GNU Binutils og tillader også validering af ELF-filer. Bemærk, at alle navnene på hjælpeprogrammerne i pakken starter med eu for 'elf utils'.

Sidst men ikke mindst vil vi nævne objdump. Dette værktøj svarer til readelf, men fokuserer på objektfiler. Det giver et lignende udvalg af oplysninger om ELF-filer og andre objektformater.

.Liste 8: Filoplysninger ekstraheret af objdump

$ objdump -f / bin / touch
/ bin / touch: filformat elf64-x86-64
arkitektur: i386: x86-64, flag 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
startadresse 0x00000000004025e3
$

Der er også en softwarepakke kaldet 'elfkickers' [9], som indeholder værktøjer til at læse indholdet af en ELF-fil samt manipulere den. Desværre er antallet af udgivelser ret lavt, og det er derfor, vi bare nævner det og viser ikke flere eksempler.

Som udvikler kan du i stedet se på 'pax-utils' [10,11]. Dette sæt værktøjer indeholder et antal værktøjer, der hjælper med at validere ELF-filer. Som et eksempel analyserer dumpelf ELF-filen og returnerer en C-headerfil, der indeholder detaljerne - se figur 2.

Konklusion

Takket være en kombination af smart design og fremragende dokumentation fungerer ELF-formatet meget godt og er stadig i brug efter 20 år. De viste hjælpeprogrammer giver dig et indblik i en ELF-fil og giver dig mulighed for at finde ud af, hvad et program laver. Dette er de første trin til analyse af software - glad hacking!

Links og referencer
  • [1] Executable and Linkable Format (ELF), Wikipedia
  • [2] Fuchsia OS
  • [3] Sammenligning af eksekverbare filformater, Wikipedia
  • [4] Linux Foundation, refererede specifikationer
  • [5] Ciro Santilli: ELF Hello World Tutorial
  • [6] Debian-pakke til elfutils
  • [7] alfdump
  • [8] Michael Boelen: 101 af ELF-filer på Linux: forståelse og analyse
  • [9] elfkickers
  • [10] Hærdede / PaX-hjælpeprogrammer
  • [11] pax-utils, Debian-pakke
Anerkendelser

Forfatteren vil gerne takke Axel Beckert for hans støtte til udarbejdelsen af ​​denne artikel.

Bedste Linux Distros til spil i 2021
Linux-operativsystemet er kommet langt fra dets originale, enkle, serverbaserede udseende. Dette operativsystem er forbedret enormt i de senere år og ...
Sådan registreres og streames din gaming-session på Linux
Tidligere blev spil kun betragtet som en hobby, men med tiden oplevede spilindustrien en enorm vækst med hensyn til teknologi og antallet af spillere....
Bedste spil at spille med håndsporing
Oculus Quest introducerede for nylig den gode idé om håndsporing uden controllere. Med et stadigt stigende antal spil og aktiviteter, der udfører supp...