Zrozumienie formatu pliku ELF

Zrozumienie formatu pliku ELF

Od kodu źródłowego do kodu binarnego

Programowanie zaczyna się od sprytnego pomysłu i pisania kodu źródłowego w wybranym języku programowania, na przykład C, i zapisywaniu kodu źródłowego w pliku. Za pomocą odpowiedniego kompilatora, na przykład GCC, kod źródłowy jest przetłumaczony na kod obiektu, najpierw. Ostatecznie Linker tłumaczy kod obiektu na plik binarny, który łączy kod obiektu z bibliotekami odwołanymi. Ten plik zawiera pojedyncze instrukcje jako kod maszynowy, który jest rozumiany przez procesor i są wykonywane, gdy tylko program skompilowany zostanie uruchomiony.

Plik binarny wspomniany powyżej jest zgodny z konkretną strukturą, a jeden z najczęstszych jest nazywany elf. Jest powszechnie używany do plików wykonywalnych, plików obiektów relokatywnych, bibliotek udostępnionych i zrzutów podstawowych.

Dwadzieścia lat temu - w 1999 r. Na szczęście format ELF został wcześniej udokumentowany zarówno w interfejsie binarnym System V Application, jak i standardu interfejsu narzędzi [4]. Fakt ten niezwykle uproszczył zgodę na standaryzację między różnymi dostawcami i deweloperami systemów operacyjnych opartych na UNIX.

Przyczyną tej decyzji było projektowanie elfa - elastyczność, rozszerzalność i wsparcie międzyplatformowe dla różnych formatów endianowych i rozmiarów adresów. Projekt ELF nie ogranicza się do określonego procesora, zestawu instrukcji lub architektury sprzętowej. Aby uzyskać szczegółowe porównanie formatów plików wykonywalnych, zajrzyj tutaj [3].

Od tego czasu format ELF jest używany przez kilka różnych systemów operacyjnych. Obejmuje to między innymi Linux, Solaris/Illumos, Free-, Net- i OpenBSD, QNX, Beos/Haiku i Fuchsia OS [2]. Ponadto znajdziesz go na urządzeniach mobilnych z Androidem, Maemo lub Meego OS/Sailfish OS, a także na konsolach do gry, takich jak PlayStation Portable, Dreamcast i Wii.

Specyfikacja nie wyjaśnia rozszerzenia nazwy pliku dla plików ELF. W użyciu jest różnorodne kombinacje liter, takie jak .AXF, .kosz, .elf, .o, .Prx, .ptyś, .Ko, .tak i .mod lub brak.

Struktura pliku elfa

Na terminalu Linux Elf Command Man zawiera przydatne podsumowanie o strukturze pliku ELF:

Lista 1: Manpage struktury ELF

$ man elf
ELF (5) Podręcznik programisty Linux ELF (5)
NAZWA
ELF - Format plików formatu wykonywalnego i łączącego (ELF)
STRESZCZENIE
#włączać
OPIS
Plik nagłówka określa format binarny elf
akta. Wśród tych plików znajdują się normalne pliki wykonywalne, przenoszone
Pliki obiektowe, pliki podstawowe i biblioteki udostępnione.
Plik wykonywalny za pomocą formatu pliku ELF składa się z nagłówka ELF,
a następnie tabela nagłówka programu lub stół nagłówka sekcji lub oba.
Nagłówek ELF jest zawsze na zero przesunięcia pliku. Program
Tabela nagłówka i przesunięcie tabeli nagłówka sekcji w pliku to
zdefiniowane w nagłówku elfa. Dwa stoły opisują resztę
szczegółowe funkcje pliku.

Jak widać z powyższego opisu, plik ELF składa się z dwóch sekcji - nagłówka ELF i danych plików. Sekcja danych plików może składać się z tabeli nagłówka programu opisującej zero lub więcej segmentów, tabelę nagłówka sekcji opisującej zero lub więcej sekcji, po których następują dane, o których mowa w tabeli nagłówka programu oraz tabela nagłówka sekcji. Każdy segment zawiera informacje niezbędne do wykonywania pliku w czasie wykonywania, podczas gdy sekcje zawierają ważne dane do łączenia i relokacji. Rysunek 1 ilustruje to schematycznie.

Nagłówek elfa

Nagłówek ELF ma 32 bajty długości i identyfikuje format pliku. Zaczyna się od sekwencji czterech unikalnych bajtów, które są 0x7f, a następnie 0x45, 0x4c i 0x46, które tłumaczy się na trzy litery E, L i F. Wśród innych wartości nagłówek wskazuje również, czy jest to plik ELF dla formatu 32 lub 64-bitowego, używa niewielkiej lub dużej endianness, pokazuje wersję ELF, a także do którego systemu operacyjnego plik został skompilowany odpowiedni zestaw binarny aplikacji (ABI) i instrukcje CPU.

Szesnastka binarnego dotyku pliku wygląda następująco:

.Lista 2: Szesnastka pliku binarnego

$ hd/usr/bin/touch | głowa -5
00000000 7F 45 4C 46 02 01 01 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 28 E4 00 00 00 00 00 00 |@… (… |
00000030 00 00 00 40 00 38 00 09 00 40 00 1B 00 1A 00 |… @.8… @… |
00000040 06 00 00 00 05 00 00 00 40 00 00 00 00 00 00 |… @… |

Debian GNU/Linux oferuje polecenie Readelf, które jest dostarczane w pakiecie GNU „Binutils”. W towarzystwie przełącznika -h (krótka wersja „-file-header”) ładnie wyświetla nagłówek pliku elfa. Lista 3 ilustruje to dla dotyku poleceń.

.Lista 3: Wyświetlanie nagłówka pliku ELF

$ readelf -h/usr/bin/touch
Nagłówek elfów:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Klasa: ELF64
Dane: Uzupełnienie 2, Little Endian
Wersja: 1 (bieżący)
OS/ABI: UNIX - System V
Wersja ABI: 0
Typ: exec (plik wykonywalny)
Maszyna: Zaawansowane mikro urządzenia x86-64
Wersja: 0x1
Adres punktu wejścia: 0x4025e3
Początek nagłówków programu: 64 (bajty w pliku)
Początek nagłówków sekcji: 58408 (bajty w pliku)
Flagi: 0x0
Rozmiar tego nagłówka: 64 (bajty)
Rozmiar nagłówków programu: 56 (bajty)
Liczba nagłówków programu: 9
Rozmiar nagłówków sekcji: 64 (bajty)
Liczba nagłówków sekcji: 27
Sekcja String String Table Indeks: 26

Nagłówek programu

Nagłówek programu pokazuje segmenty używane w czasie wykonywania i mówi systemowi, jak utworzyć obraz procesu. Nagłówek z Listing 2 pokazuje, że plik ELF składa się z 9 nagłówków programowych o wielkości 56 bajtów każdy, a pierwszy nagłówek zaczyna się od Bajte 64.

Ponownie, polecenie Readelf pomaga wyodrębnić informacje z pliku elfa. Przełącznik -l (krótki dla -programów lub -segmenty) ujawnia więcej szczegółów, jak pokazano na liście 4.

.Lista 4: Wyświetl informacje o nagłówkach programu

$ readelf -l/usr/bin/touch
Typ pliku ELF to exec (plik wykonywalny)
Punkt wejścia 0x4025e3
Istnieje 9 nagłówków programowych, zaczynając od offset 64
Nagłówki programowe:
Wpisz przesunięcie Virtaddr Physaddr
Flagi Memsiz PLIFEIZ wyrównaj
PHDR 0x00000000000040 0x0000000000400040 0x0000000000400040
0x000000000001f8 0x00000000000001f8 r e 8
Interp 0x00000000000238 0x0000000000400238 0x0000000000400238
0x000000000000001c 0x00000000000000001c R 1
[Żądanie interpretera programu: /lib64 /ld-linux-x86-64.Więc.2]
Załaduj 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x0000000000d494 0x000000000000d494 R E 200000
Załaduj 0x0000000000de10 0x000000000060de10 0x000000000060de10
0x00000000000524 0x0000000000000748 RW 200000
Dynamic 0x0000000000de28 0x000000000060de28 0x000000000060de28
0x000000000001d0 0x00000000000001d0 RW 8
Uwaga 0x00000000000254 0x0000000000400254 0x0000000000400254
0x0000000000000044 0x0000000000000044 R 4
GNU_EH_FRAME 0x000000000000BC40 0x000000000040BC40 0x000000000040BC40
0x000000000003a4 0x00000000000003a4 R 4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x000000000000000000 RW 10
GNU_RELRO 0X000000000000DE10 0x000000000060DE10 0x0000000060DE10
0x000000000001f0 0x00000000000001f0 r 1
Sekcja do mapowania segmentu:
Sekcje segmentowe…
00
01 .interp
02 .interp .notatka.Abi-tag .notatka.gnu antylopa.kompilacja .gnu antylopa.haszysz .Dynsym .Dynstr .gnu antylopa.wersja .gnu antylopa.wersja_r .rela.Dyn .rela.plt .w tym .plt .tekst .fini .Rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .Jcr .dynamiczny .dostał .dostał.plt .dane .BSS
04 .dynamiczny
05 .notatka.Abi-tag .notatka.gnu antylopa.kompilacja
06 .eh_frame_hdr
07
08 .init_array .fini_array .Jcr .dynamiczny .dostał

Nagłówek sekcji

Trzecia część struktury ELF to nagłówek sekcji. Ma to wymienić pojedyncze sekcje binarnego. Switch -s (krótkie dla -sektorowe lub -sekcje) wymienia różne nagłówki. Jeśli chodzi o polecenie dotykowe, istnieje 27 nagłówków sekcji, a lista 5 pokazuje tylko pierwsze z nich plus tylko ostatnie. Każda linia obejmuje rozmiar sekcji, typ sekcji, a także jego adres i przesunięcie pamięci.

.Lista 5: Szczegóły sekcji ujawnione przez Readelf

$ readelf -s/usr/bin/touch
Istnieje 27 nagłówków sekcji, zaczynając od przesunięcia 0xe428:
Nagłówki sekcji:
[NR] Typ nazwy
Rozmiar flagi Flagi Informacje o linku
[0] NULL 000000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[1] .interp progbits 0000000000400238 00000238
000000000000001C 0000000000000000 A 0 0 1
[2] .notatka.Uwaga ABI-TAG 0000000000400254 00000254
0000000000000020 0000000000000000 A 0 0 4
[3] .notatka.gnu antylopa.Build-i Uwaga 0000000000400274 00000274


[26] .SHSTRAB STTAB 000000000000000000 0000E334
00000000000000EF 0000000000000000 0 0 1
Klucz do flag:
W (zapisz), A (alloc), x (wykonaj), m (scal), s (struny), l (duże)
I (Info), L (kolejność linku), g (grupa), t (tls), e (wyklucz), x (nieznany)
O (Wymagane dodatkowe przetwarzanie OS) O (specyficzne dla OS), P (specyficzne dla procesora)

Narzędzia do analizy pliku ELF

Jak można zauważyć z powyższych przykładów, GNU/Linux jest rozwinięty z wieloma przydatnymi narzędziami, które pomagają przeanalizować plik ELF. Pierwszym kandydatem, na który będziemy się przyjrzeć, jest narzędzie pliku.

Plik wyświetla podstawowe informacje o plikach elfów, w tym architektura zestawu instrukcji, dla których kod w pliku obiektowym jest przenoszony, wykonywalny lub udostępniony. Na liście 6 mówi, że/bin/touch to 64-bitowy plik wykonywalny zgodnie z bazą standardową Linux (LSB), dynamicznie połączoną i zbudowaną dla jądra GNU/Linux wersja 2.6.32.

.Lista 6: Podstawowe informacje za pomocą pliku

$ plik /bin /touch
/bin/touch: elf 64-bit LSB wykonywalny, x86-64, wersja 1 (SYSV), dynamicznie połączone, interpreter/lib64/l,
dla GNU/Linux 2.6.32, BuildId [SHA1] = EC08D609E9E8E73D4BE6134541A472AD0EA34502, Stripped
$

Drugi kandydat to czytanie. Wyświetla szczegółowe informacje o pliku ELF. Lista przełączników jest porównywalnie długa i obejmuje wszystkie aspekty formatu ELF. Za pomocą przełącznika -n (krótkiego dla -Notes) Listing 7 pokazuje tylko sekcje notatek, które istnieją w pliku dotyk.

.Lista 7: Wyświetl wybrane sekcje pliku ELF

$ readelf -n/usr/bin/touch
Wyświetlanie notatek znalezionych w przesunięciu pliku 0x00000254 o długości 0x00000020:
Opis rozmiaru danych właściciela
GNU 0x00000010 NT_GNU_ABI_TAG (Tag wersji ABI)
OS: Linux, ABI: 2.6.32
Wyświetlanie notatek znalezionych w przesunięciu pliku 0x00000274 o długości 0x00000024:
Opis rozmiaru danych właściciela
GNU 0x00000014 NT_GNU_BUILD_ID (unikalny identyfikator budowy bitstring)
Kompicja ID: EC08D609E9E8E73D4BE6134541A472AD0EA34502

Zauważ, że w ramach Solaris i FreeBSD elfdump użyteczności [7] odpowiada odczytowi. Od 2019 r. Nie ma nowej wersji ani aktualizacji od 2003 roku.

Numer trzy to pakiet o nazwie Elfutils [6], który jest wyłącznie dostępny dla Linux. Zapewnia alternatywne narzędzia dla Binutils GNU, a także umożliwia sprawdzanie poprawności plików ELF. Zauważ, że wszystkie nazwy narzędzi podanych w pakiecie zaczynają się od UE dla „ELF Utils”.

Wreszcie wspomnimy o objdump. To narzędzie jest podobne do odczytu, ale koncentruje się na plikach obiektów. Zapewnia podobny zakres informacji o plikach ELF i innych formatach obiektów.

.Lista 8: Informacje o pliku wyodrębnione przez objdump

$ objdump -f /bin /touch
/bin/touch: format pliku elf64-x86-64
Architektura: i386: x86-64, flagi 0x00000112:
Exec_p, HAS_SYMS, D_PAGED
Rozpoczęcie adres 0x00000000004025e3
$

Istnieje również pakiet oprogramowania o nazwie „Elfkickers” [9], który zawiera narzędzia do odczytu zawartości pliku ELF, a także manipulowanie. Niestety liczba wydań jest raczej niska i dlatego po prostu o tym wspominamy i nie pokazujemy kolejnych przykładów.

Jako deweloper możesz rzucić okiem na „Pax-Utils” [10,11],. Ten zestaw narzędzi zapewnia szereg narzędzi, które pomagają weryfikacji plików ELF. Jako przykład, zrzucanie analizuje plik ELF i zwraca plik nagłówka C zawierający szczegóły - patrz Rysunek 2.

Wniosek

Dzięki połączeniu sprytnego projektu i doskonałej dokumentacji format ELF działa bardzo dobrze i nadal jest używany po 20 latach. Narzędzia pokazane powyżej umożliwiają widok na plik ELF i pozwala dowiedzieć się, co robi program. To są pierwsze kroki do analizy oprogramowania - Happy Hacking!

Linki i referencje
  • [1] Format wykonywalny i połączony (ELF), Wikipedia
  • [2] Fuchsia OS
  • [3] Porównanie formatów plików wykonywalnych, Wikipedia
  • [4] Linux Foundation, odwołane specyfikacje
  • [5] Ciro Santilli: Elf Hello World Tutorial
  • [6] Elfutils Pakiet Debian
  • [7] Elfdump
  • [8] Michael Boelen: 101 plików ELF w Linux: zrozumienie i analiza
  • [9] Elfkickers
  • [10] Użytkownicy stwardnienia/Pax
  • [11] Pax-Utils, Pakiet Debian
Podziękowanie

Pisarz chciałby podziękować Axelowi Beckertowi za jego wsparcie w zakresie przygotowania tego artykułu.