ÄLVA

Förstå ELF-filformatet

Förstå ELF-filformatet

Från källkod till binär kod

Programmering börjar med att ha en smart idé och skriva källkod på ett valfritt programmeringsspråk, till exempel C, och spara källkoden i en fil. Med hjälp av en adekvat kompilator, till exempel GCC, översätts din källkod först till objektkod. Så småningom översätter länkaren objektkoden till en binär fil som länkar objektkoden med de refererade biblioteken. Den här filen innehåller de enskilda instruktionerna som maskinkod som förstås av CPU: n och körs så snart det kompilerade programmet körs.

Den binära filen som nämns ovan följer en specifik struktur, och en av de vanligaste heter ELF som förkortar Executable and Linkable Format. Det används ofta för körbara filer, flyttbara objektfiler, delade bibliotek och kärndumpar.

För 20 år sedan - 1999 - har 86open-projektet valt ELF som standard binärt filformat för Unix och Unix-liknande system på x86-processorer. Lyckligtvis hade ELF-formatet tidigare dokumenterats i både System V Application Binary Interface och Tool Interface Standard [4]. Detta faktum förenklade enormt avtalet om standardisering mellan olika leverantörer och utvecklare av Unix-baserade operativsystem.

Anledningen till beslutet var designen av ELF - flexibilitet, utbyggbarhet och plattformsstöd för olika endianformat och adressstorlekar. ELFs design är inte begränsad till en specifik processor, instruktionsuppsättning eller hårdvaruarkitektur. För en detaljerad jämförelse av körbara filformat, ta en titt här [3].

Sedan dess används ELF-formatet av flera olika operativsystem. Bland annat inkluderar detta Linux, Solaris / Illumos, Free-, Net- och OpenBSD, QNX, BeOS / Haiku och Fuchsia OS [2]. Dessutom hittar du den på mobila enheter som kör Android, Maemo eller Meego OS / Sailfish OS samt på spelkonsoler som PlayStation Portable, Dreamcast och Wii.

Specifikationen klargör inte filnamnstillägget för ELF-filer. I användning finns en mängd olika bokstavskombinationer, till exempel .axf, .soptunna, .älva, .o, .prx, .puff, .ko, .så, och .mod, eller ingen.

Strukturen för en ELF-fil

På en Linux-terminal ger kommandot man elf dig en praktisk sammanfattning om strukturen för en ELF-fil:

Listning 1: ELF-strukturs manpage

$ man elf
ELF (5) Linux-programmerarhandbok ELF (5)
NAMN
elf - format för körbara filer och ELF-filer (Linking Format)
SYNOPSIS
#omfatta
BESKRIVNING
Rubrikfilen definierar formatet för ELF-körbar binär
filer. Bland dessa filer finns normala körbara filer, flyttbara
objektfiler, kärnfiler och delade bibliotek.
En körbar fil som använder ELF-filformatet består av en ELF-rubrik,
följt av en programhuvudtabell eller en sektionstabell eller båda.
ELF-rubriken är alltid vid offset noll för filen. Programmet
sidhuvudstabell och sektionstabellens förskjutning i filen är
definieras i ELF-rubriken. De två tabellerna beskriver resten av
filens särdrag.
..

Som du kan se från beskrivningen ovan består en ELF-fil av två sektioner - en ELF-rubrik och fildata. Fildatasektionen kan bestå av en programhuvudtabell som beskriver noll eller fler segment, en sektionshuvudtabell som beskriver noll eller fler sektioner, som följs av data som hänvisas till av poster från programhuvudtabellen och sektionshuvudtabellen. Varje segment innehåller information som är nödvändig för körning av filen under körning, medan avsnitt innehåller viktig information för länkning och omlokalisering. Figur 1 illustrerar detta schematiskt.

ELF-rubriken

ELF-rubriken är 32 byte lång och identifierar filens format. Det börjar med en sekvens av fyra unika byte som är 0x7F följt av 0x45, 0x4c och 0x46 som översätts till de tre bokstäverna E, L och F. Bland andra värden indikerar rubriken också om det är en ELF-fil för 32- eller 64-bitarsformat, använder liten eller stor ändamålsenlighet, visar ELF-versionen samt för vilket operativsystem filen kompilerades för att samverka med rätt applikations binärt gränssnitt (ABI) och CPU-instruktionsuppsättning.

Hexdumpen för binärfilens beröring ser ut som följer:

.Listing 2: Hexdumpen för den binära filen

$ hd / usr / bin / touch | huvud -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 erbjuder readelf-kommandot som tillhandahålls i GNU-paketet "binutils". Tillsammans med switch -h (kortversion för “-fil-header”) visar den snyggt rubriken för en ELF-fil. Listning 3 illustrerar detta för kommandotouch.

.Listing 3: Visar rubriken för en ELF-fil

$ readelf -h / usr / bin / touch
ELF-rubrik:
Magi: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Klass: ELF64
Data: 2-komplement, liten endian
Version: 1 (nuvarande)
OS / ABI: UNIX - System V
ABI-version: 0
Typ: EXEC (körbar fil)
Maskin: Advanced Micro Devices X86-64
Version: 0x1
Ingångsadress: 0x4025e3
Start av programrubriker: 64 (byte i fil)
Start för sektionsrubriker: 58408 (byte i fil)
Flaggor: 0x0
Storlek på denna rubrik: 64 (byte)
Storlek på programrubriker: 56 (byte)
Antal programrubriker: 9
Storlek på sektionsrubriker: 64 (byte)
Antal sektionsrubriker: 27
Sektionens rubriksträngtabellindex: 26

Programrubriken

Programrubriken visar segmenten som används vid körning och berättar för systemet hur man skapar en processbild. Rubriken från Listing 2 visar att ELF-filen består av 9 programrubriker som har en storlek på 56 byte vardera, och den första rubriken börjar vid byte 64.

Återigen hjälper kommandot readelf att extrahera informationen från ELF-filen. Växeln -l (kort för -program-rubriker eller -segment) avslöjar mer information som visas i Listing 4.

.Listning 4: Visa information om programrubrikerna

$ readelf -l / usr / bin / touch
Elf-filtyp är EXEC (körbar fil)
Ingångspunkt 0x4025e3
Det finns 9 programrubriker som börjar vid förskjutning 64
Programrubriker:
Typ Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000001f8 0x00000000000001f8 R E 8
INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238
0x000000000000001c 0x000000000000001c R 1
[Begär programtolk: / lib64 / ld-linux-x86-64.så.2]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x000000000000d494 0x000000000000d494 R E 200000
LAST 0x000000000000de10 0x000000000060de10 0x000000000060de10
0x0000000000000524 0x0000000000000748 RW 200000
DYNAMIC 0x000000000000de28 0x000000000060de28 0x000000000060de28
0x00000000000001d0 0x00000000000001d0 RW 8
OBS 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
Avsnitt till segmentmappning:
Segmentavsnitt ..
00
01 .interp
02 .interp .notera.ABI-tagg .notera.gnu.bygg-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .i det .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .jcr .dynamisk .fick .fick.plt .data .bss
04 .dynamisk
05 .notera.ABI-tagg .notera.gnu.bygg-id
06 .eh_frame_hdr
07
08 .init_array .fini_array .jcr .dynamisk .fick

Avsnittets rubrik

Den tredje delen av ELF-strukturen är sektionsrubriken. Det är tänkt att lista de enskilda sektionerna i binären. Växeln -S (kort för -sektionsrubriker eller -sektioner) listar de olika rubrikerna. När det gäller touch-kommandot finns det 27 sektionsrubriker, och Listing 5 visar de fyra första av dem plus den sista, bara. Varje rad täcker sektionsstorlek, sektionstyp samt dess adress och minnesförskjutning.

.Listning 5: Sektionsdetaljer avslöjade av readelf

$ readelf -S / usr / bin / touch
Det finns 27 sektionsrubriker som börjar vid offset 0xe428:
Avdelningsrubriker:
[Nr] Namn Typ Adress Offset
Storlek EntSize-flaggor Länkinfo Justera
[0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[1] .interp PROGBITS 0000000000400238 00000238
000000000000001c 0000000000000000 A 0 0 1
[2] .notera.ABI-tag OBS 0000000000400254 00000254
0000000000000020 0000000000000000 A 0 0 4
[3] .notera.gnu.build-i OBS 0000000000400274 00000274
..
..
[26] .shstrtab STRTAB 0000000000000000 0000e334
00000000000000ef 0000000000000000 0 0 1
Nyckel till flaggor:
W (skriv), A (allokera), X (exekvera), M (slå samman), S (strängar), l (stor)
I (info), L (länkordning), G (grupp), T (TLS), E (exkludera), x (okänd)
O (extra OS-bearbetning krävs) o (OS-specifik), p (processor-specifik)

Verktyg för att analysera en ELF-fil

Som du kanske har noterat från exemplen ovan är GNU / Linux utarbetat med ett antal användbara verktyg som hjälper dig att analysera en ELF-fil. Den första kandidaten vi kommer att titta på är filverktyget.

filen visar grundläggande information om ELF-filer, inklusive instruktionsuppsättningsarkitekturen för vilken koden i en flyttbar, körbar eller delad objektfil är avsedd. I lista 6 berättar det att / bin / touch är en 64-bitars körbar fil som följer Linux Standard Base (LSB), dynamiskt länkad och byggd för GNU / Linux-kärnversion 2.6.32.

.Listning 6: Grundläggande information med fil

$ file / bin / touch
/ bin / touch: ELF 64-bitars LSB körbar, x86-64, version 1 (SYSV), dynamiskt länkad, tolk / lib64 / l,
för GNU / Linux 2.6.32, BuildID [sha1] = ec08d609e9e8e73d4be6134541a472ad0ea34502, avskalad
$

Den andra kandidaten är självläst. Den visar detaljerad information om en ELF-fil. Listan över omkopplare är jämförbar lång och täcker alla aspekter av ELF-formatet. Användning av växeln -n (kort för -noter) Listning 7 visar endast de anteckningsavsnitt som finns i filrörelsen - ABI-versionstaggen och build ID-bitsträng.

.Listning 7: Visa valda sektioner av en ELF-fil

$ readelf -n / usr / bin / touch
Visar anteckningar som hittades vid filoffset 0x00000254 med längd 0x00000020:
Ägare Datastorlek Beskrivning
GNU 0x00000010 NT_GNU_ABI_TAG (ABI-versionstagg)
OS: Linux, ABI: 2.6.32
Visar anteckningar som hittades vid filoffset 0x00000274 med längd 0x00000024:
Ägare Datastorlek Beskrivning
GNU 0x00000014 NT_GNU_BUILD_ID (unik bygg-ID bitsträng)
Bygg-ID: ec08d609e9e8e73d4be6134541a472ad0ea34502

Observera att elfdump [7] under Solaris och FreeBSD motsvarar readelf. Från och med 2019 har det inte kommit någon ny version eller uppdatering sedan 2003.

Nummer tre är paketet med namnet elfutils [6] som är rent tillgängligt för Linux. Det ger alternativa verktyg till GNU Binutils och tillåter också validering av ELF-filer. Observera att alla namn på verktygen i paketet börjar med eu för 'elf utils'.

Sist men inte minst kommer vi att nämna objdump. Detta verktyg liknar readelf men fokuserar på objektfiler. Det ger ett liknande utbud av information om ELF-filer och andra objektformat.

.Lista 8: Filinformation extraherad av objdump

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

Det finns också ett mjukvarupaket som heter 'elfkickers' [9] som innehåller verktyg för att läsa innehållet i en ELF-fil samt manipulera den. Tyvärr är antalet utgåvor ganska lågt, och det är därför vi bara nämner det och visar inga ytterligare exempel.

Som utvecklare kan du istället titta på 'pax-utils' [10,11]. Denna uppsättning verktyg erbjuder ett antal verktyg som hjälper till att validera ELF-filer. Som ett exempel analyserar dumpelf ELF-filen och returnerar en C-rubrikfil som innehåller detaljerna - se figur 2.

Slutsats

Tack vare en kombination av smart design och utmärkt dokumentation fungerar ELF-formatet mycket bra och används fortfarande efter 20 år. Verktygen som visas ovan ger dig en inblick i en ELF-fil och låter dig ta reda på vad ett program gör. Det här är de första stegen för att analysera programvara - glad hacking!

Länkar och referenser
  • [1] Körbart och länkbart format (ELF), Wikipedia
  • [2] Fuchsia OS
  • [3] Jämförelse av körbara filformat, Wikipedia
  • [4] Linux Foundation, refererade specifikationer
  • [5] Ciro Santilli: ELF Hello World Tutorial
  • [6] elfutils Debian-paket
  • [7] elfdump
  • [8] Michael Boelen: 101 av ELF-filer på Linux: Förståelse och analys
  • [9] elfkickers
  • [10] Härdade / PaX-verktyg
  • [11] pax-utils, Debian-paket
Bekräftelser

Författaren vill tacka Axel Beckert för hans stöd angående utarbetandet av denna artikel.

Mus AppyMouse styrplatta och muspekare för Windows-surfplattor
AppyMouse styrplatta och muspekare för Windows-surfplattor
Surfplattanvändare saknar ofta muspekaren, särskilt när de brukar använda bärbara datorer. Pekskärmen Smartphones och surfplattor har många fördelar o...
Mus Mellan musknappen fungerar inte i Windows 10
Mellan musknappen fungerar inte i Windows 10
De mittknappen hjälper dig att bläddra igenom långa webbsidor och skärmar med mycket data. Om det slutar, kommer du sluta använda tangentbordet för at...
Mus Hur man ändrar vänster och höger musknapp på Windows 10 PC
Hur man ändrar vänster och höger musknapp på Windows 10 PC
Det är en hel norm att alla datormusenheter är ergonomiskt utformade för högerhänta användare. Men det finns musenheter tillgängliga som är speciellt ...