mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-23 13:13:41 +00:00
389 lines
23 KiB
Markdown
389 lines
23 KiB
Markdown
# Informacje podstawowe o ELF
|
|
|
|
<details>
|
|
|
|
<summary><strong>Naucz się hakować AWS od zera do bohatera z</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
|
|
|
* Czy pracujesz w **firmie z branży cyberbezpieczeństwa**? Chcesz zobaczyć, jak Twoja **firma jest reklamowana na HackTricks**? lub chcesz mieć dostęp do **najnowszej wersji PEASS lub pobrać HackTricks w formacie PDF**? Sprawdź [**PLANY SUBSKRYPCYJNE**](https://github.com/sponsors/carlospolop)!
|
|
* Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family)
|
|
* Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com)
|
|
* **Dołącz do** [**💬**](https://emojipedia.org/speech-balloon/) [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** mnie na **Twitterze** 🐦[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
|
|
* **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do** [**repozytorium hacktricks**](https://github.com/carlospolop/hacktricks) **i** [**repozytorium hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
|
|
|
</details>
|
|
|
|
## Nagłówki programu
|
|
|
|
Opisują one loaderowi, jak załadować **ELF** do pamięci:
|
|
```bash
|
|
readelf -lW lnstat
|
|
|
|
Elf file type is DYN (Position-Independent Executable file)
|
|
Entry point 0x1c00
|
|
There are 9 program headers, starting at offset 64
|
|
|
|
Program Headers:
|
|
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
|
|
PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x0001f8 0x0001f8 R 0x8
|
|
INTERP 0x000238 0x0000000000000238 0x0000000000000238 0x00001b 0x00001b R 0x1
|
|
[Requesting program interpreter: /lib/ld-linux-aarch64.so.1]
|
|
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x003f7c 0x003f7c R E 0x10000
|
|
LOAD 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x000528 0x001190 RW 0x10000
|
|
DYNAMIC 0x00fc58 0x000000000001fc58 0x000000000001fc58 0x000200 0x000200 RW 0x8
|
|
NOTE 0x000254 0x0000000000000254 0x0000000000000254 0x0000e0 0x0000e0 R 0x4
|
|
GNU_EH_FRAME 0x003610 0x0000000000003610 0x0000000000003610 0x0001b4 0x0001b4 R 0x4
|
|
GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10
|
|
GNU_RELRO 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x0003b8 0x0003b8 R 0x1
|
|
|
|
Section to Segment mapping:
|
|
Segment Sections...
|
|
00
|
|
01 .interp
|
|
02 .interp .note.gnu.build-id .note.ABI-tag .note.package .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 .dynamic .got .data .bss
|
|
04 .dynamic
|
|
05 .note.gnu.build-id .note.ABI-tag .note.package
|
|
06 .eh_frame_hdr
|
|
07
|
|
08 .init_array .fini_array .dynamic .got
|
|
```
|
|
Poprzedni program ma **9 nagłówków programu**, następnie **mapowanie segmentów** wskazuje, w którym nagłówku programu (od 00 do 08) **znajduje się każda sekcja**.
|
|
|
|
### PHDR - Nagłówek programu
|
|
|
|
Zawiera tabele nagłówków programów oraz same metadane.
|
|
|
|
### INTERP
|
|
|
|
Wskazuje ścieżkę do ładowacza, który ma załadować binarny plik do pamięci.
|
|
|
|
### LOAD
|
|
|
|
Te nagłówki służą do wskazania, **jak załadować binarny plik do pamięci**.\
|
|
Każdy nagłówek **LOAD** wskazuje obszar **pamięci** (rozmiar, uprawnienia i wyrównanie) oraz wskazuje bajty ELF **do skopiowania tam**.
|
|
|
|
Na przykład drugi ma rozmiar 0x1190, powinien znajdować się pod adresem 0x1fc48 z uprawnieniami do odczytu i zapisu oraz zostanie wypełniony wartościami 0x528 od przesunięcia 0xfc48 (nie wypełnia całej zarezerwowanej przestrzeni). Ta pamięć będzie zawierać sekcje `.init_array .fini_array .dynamic .got .data .bss`.
|
|
|
|
### DYNAMIC
|
|
|
|
Ten nagłówek pomaga łączyć programy z ich zależnościami bibliotecznymi i stosować relokacje. Sprawdź sekcję **`.dynamic`**.
|
|
|
|
### NOTE
|
|
|
|
Przechowuje informacje metadanych dostawcy o binarnym pliku.
|
|
|
|
### GNU\_EH\_FRAME
|
|
|
|
Definiuje lokalizację tabel odwijania stosu, używanych przez debuggery i funkcje obsługi wyjątków C++.
|
|
|
|
### GNU\_STACK
|
|
|
|
Zawiera konfigurację obrony przed wykonywaniem kodu ze stosu. Jeśli jest włączona, binarny plik nie będzie mógł wykonywać kodu ze stosu.
|
|
|
|
### GNU\_RELRO
|
|
|
|
Wskazuje konfigurację RELRO (Relocation Read-Only) binarnego pliku. Ta ochrona oznacza jako tylko do odczytu pewne sekcje pamięci (takie jak `GOT` lub tabele `init` i `fini`) po załadowaniu programu i przed jego uruchomieniem.
|
|
|
|
W poprzednim przykładzie kopiowanych jest 0x3b8 bajtów do 0x1fc48 jako tylko do odczytu, wpływając na sekcje `.init_array .fini_array .dynamic .got .data .bss`.
|
|
|
|
Zauważ, że RELRO może być częściowy lub pełny, wersja częściowa nie chroni sekcji **`.plt.got`**, która jest używana do **opóźnionego wiązania** i wymaga, aby ta przestrzeń pamięci miała **uprawnienia do zapisu**, aby zapisać adresy bibliotek za pierwszym razem, gdy ich lokalizacja jest wyszukiwana.
|
|
|
|
### TLS
|
|
|
|
Definiuje tabelę wpisów TLS, która przechowuje informacje o zmiennych lokalnych wątku.
|
|
|
|
## Nagłówki sekcji
|
|
|
|
Nagłówki sekcji dają bardziej szczegółowy widok binarnego pliku ELF.
|
|
```
|
|
objdump lnstat -h
|
|
|
|
lnstat: file format elf64-littleaarch64
|
|
|
|
Sections:
|
|
Idx Name Size VMA LMA File off Algn
|
|
0 .interp 0000001b 0000000000000238 0000000000000238 00000238 2**0
|
|
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
|
1 .note.gnu.build-id 00000024 0000000000000254 0000000000000254 00000254 2**2
|
|
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
|
2 .note.ABI-tag 00000020 0000000000000278 0000000000000278 00000278 2**2
|
|
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
|
3 .note.package 0000009c 0000000000000298 0000000000000298 00000298 2**2
|
|
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
|
4 .gnu.hash 0000001c 0000000000000338 0000000000000338 00000338 2**3
|
|
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
|
5 .dynsym 00000498 0000000000000358 0000000000000358 00000358 2**3
|
|
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
|
6 .dynstr 000001fe 00000000000007f0 00000000000007f0 000007f0 2**0
|
|
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
|
7 .gnu.version 00000062 00000000000009ee 00000000000009ee 000009ee 2**1
|
|
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
|
8 .gnu.version_r 00000050 0000000000000a50 0000000000000a50 00000a50 2**3
|
|
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
|
9 .rela.dyn 00000228 0000000000000aa0 0000000000000aa0 00000aa0 2**3
|
|
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
|
10 .rela.plt 000003c0 0000000000000cc8 0000000000000cc8 00000cc8 2**3
|
|
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
|
11 .init 00000018 0000000000001088 0000000000001088 00001088 2**2
|
|
CONTENTS, ALLOC, LOAD, READONLY, CODE
|
|
12 .plt 000002a0 00000000000010a0 00000000000010a0 000010a0 2**4
|
|
CONTENTS, ALLOC, LOAD, READONLY, CODE
|
|
13 .text 00001c34 0000000000001340 0000000000001340 00001340 2**6
|
|
CONTENTS, ALLOC, LOAD, READONLY, CODE
|
|
14 .fini 00000014 0000000000002f74 0000000000002f74 00002f74 2**2
|
|
CONTENTS, ALLOC, LOAD, READONLY, CODE
|
|
15 .rodata 00000686 0000000000002f88 0000000000002f88 00002f88 2**3
|
|
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
|
16 .eh_frame_hdr 000001b4 0000000000003610 0000000000003610 00003610 2**2
|
|
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
|
17 .eh_frame 000007b4 00000000000037c8 00000000000037c8 000037c8 2**3
|
|
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
|
18 .init_array 00000008 000000000001fc48 000000000001fc48 0000fc48 2**3
|
|
CONTENTS, ALLOC, LOAD, DATA
|
|
19 .fini_array 00000008 000000000001fc50 000000000001fc50 0000fc50 2**3
|
|
CONTENTS, ALLOC, LOAD, DATA
|
|
20 .dynamic 00000200 000000000001fc58 000000000001fc58 0000fc58 2**3
|
|
CONTENTS, ALLOC, LOAD, DATA
|
|
21 .got 000001a8 000000000001fe58 000000000001fe58 0000fe58 2**3
|
|
CONTENTS, ALLOC, LOAD, DATA
|
|
22 .data 00000170 0000000000020000 0000000000020000 00010000 2**3
|
|
CONTENTS, ALLOC, LOAD, DATA
|
|
23 .bss 00000c68 0000000000020170 0000000000020170 00010170 2**3
|
|
ALLOC
|
|
24 .gnu_debugaltlink 00000049 0000000000000000 0000000000000000 00010170 2**0
|
|
CONTENTS, READONLY
|
|
25 .gnu_debuglink 00000034 0000000000000000 0000000000000000 000101bc 2**2
|
|
CONTENTS, READONLY
|
|
```
|
|
### Sekcje metadanych
|
|
|
|
* **Tabela ciągów**: Zawiera wszystkie ciągi potrzebne przez plik ELF (ale nie te, które faktycznie są używane przez program). Na przykład zawiera nazwy sekcji takie jak `.text` lub `.data`. Jeśli sekcja `.text` znajduje się na przesunięciu 45 w tabeli ciągów, użyje liczby **45** w polu **nazwa**.
|
|
* Aby znaleźć, gdzie znajduje się tabela ciągów, ELF zawiera wskaźnik do tabeli ciągów.
|
|
* **Tabela symboli**: Zawiera informacje o symbolach, takie jak nazwa (przesunięcie w tabeli ciągów), adres, rozmiar i więcej metadanych o symbolu.
|
|
|
|
### Główne sekcje
|
|
|
|
* **`.text`**: Instrukcje programu do wykonania.
|
|
* **`.data`**: Zmienne globalne zdefiniowane wartością w programie.
|
|
* **`.bss`**: Zmienne globalne pozostawione niezainicjowane (lub zainicjowane na zero). Zmienne tutaj są automatycznie inicjowane na zero, zapobiegając tym samym dodawaniu niepotrzebnych zer do pliku binarnego.
|
|
* **`.rodata`**: Stałe zmienne globalne (sekcja tylko do odczytu).
|
|
* **`.tdata`** i **`.tbss`**: Podobne do .data i .bss, gdy używane są zmienne lokalne wątku (`__thread_local` w C++ lub `__thread` w).
|
|
* **`.dynamic`**: Patrz poniżej.
|
|
|
|
## Symbole
|
|
|
|
Symbole to nazwane lokalizacje w programie, które mogą być funkcją, globalnym obiektem danych, zmiennymi lokalnymi wątku...
|
|
```
|
|
readelf -s lnstat
|
|
|
|
Symbol table '.dynsym' contains 49 entries:
|
|
Num: Value Size Type Bind Vis Ndx Name
|
|
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
|
|
1: 0000000000001088 0 SECTION LOCAL DEFAULT 12 .init
|
|
2: 0000000000020000 0 SECTION LOCAL DEFAULT 23 .data
|
|
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strtok@GLIBC_2.17 (2)
|
|
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND s[...]@GLIBC_2.17 (2)
|
|
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strlen@GLIBC_2.17 (2)
|
|
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fputs@GLIBC_2.17 (2)
|
|
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND exit@GLIBC_2.17 (2)
|
|
8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _[...]@GLIBC_2.34 (3)
|
|
9: 0000000000000000 0 FUNC GLOBAL DEFAULT UND perror@GLIBC_2.17 (2)
|
|
10: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[...]
|
|
11: 0000000000000000 0 FUNC WEAK DEFAULT UND _[...]@GLIBC_2.17 (2)
|
|
12: 0000000000000000 0 FUNC GLOBAL DEFAULT UND putc@GLIBC_2.17 (2)
|
|
[...]
|
|
```
|
|
Każdy wpis symbolu zawiera:
|
|
|
|
- **Nazwę**
|
|
- **Atrybuty wiązania** (słabe, lokalne lub globalne): Symbol lokalny może być dostępny tylko przez program, podczas gdy symbole globalne są udostępniane poza programem. Obiekt słaby to na przykład funkcja, która może zostać zastąpiona inną.
|
|
- **Typ**: NOTYPE (brak określonego typu), OBJECT (zmienna danych globalnych), FUNC (funkcja), SECTION (sekcja), FILE (plik źródłowy dla debuggerów), TLS (zmienna lokalna wątku), GNU_IFUNC (funkcja pośrednia do relokacji)
|
|
- Indeks **sekcji**, w której się znajduje
|
|
- **Wartość** (adres w pamięci)
|
|
- **Rozmiar**
|
|
|
|
## Sekcja dynamiczna
|
|
```
|
|
readelf -d lnstat
|
|
|
|
Dynamic section at offset 0xfc58 contains 28 entries:
|
|
Tag Type Name/Value
|
|
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
|
|
0x0000000000000001 (NEEDED) Shared library: [ld-linux-aarch64.so.1]
|
|
0x000000000000000c (INIT) 0x1088
|
|
0x000000000000000d (FINI) 0x2f74
|
|
0x0000000000000019 (INIT_ARRAY) 0x1fc48
|
|
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
|
|
0x000000000000001a (FINI_ARRAY) 0x1fc50
|
|
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
|
|
0x000000006ffffef5 (GNU_HASH) 0x338
|
|
0x0000000000000005 (STRTAB) 0x7f0
|
|
0x0000000000000006 (SYMTAB) 0x358
|
|
0x000000000000000a (STRSZ) 510 (bytes)
|
|
0x000000000000000b (SYMENT) 24 (bytes)
|
|
0x0000000000000015 (DEBUG) 0x0
|
|
0x0000000000000003 (PLTGOT) 0x1fe58
|
|
0x0000000000000002 (PLTRELSZ) 960 (bytes)
|
|
0x0000000000000014 (PLTREL) RELA
|
|
0x0000000000000017 (JMPREL) 0xcc8
|
|
0x0000000000000007 (RELA) 0xaa0
|
|
0x0000000000000008 (RELASZ) 552 (bytes)
|
|
0x0000000000000009 (RELAENT) 24 (bytes)
|
|
0x000000000000001e (FLAGS) BIND_NOW
|
|
0x000000006ffffffb (FLAGS_1) Flags: NOW PIE
|
|
0x000000006ffffffe (VERNEED) 0xa50
|
|
0x000000006fffffff (VERNEEDNUM) 2
|
|
0x000000006ffffff0 (VERSYM) 0x9ee
|
|
0x000000006ffffff9 (RELACOUNT) 15
|
|
0x0000000000000000 (NULL) 0x0
|
|
```
|
|
Katalog NEEDED wskazuje, że program **musi załadować wymienioną bibliotekę**, aby kontynuować. Katalog NEEDED zostaje uzupełniony, gdy współdzielona **biblioteka jest w pełni operacyjna i gotowa do użycia**.
|
|
|
|
## Przesunięcia
|
|
|
|
Ładowacz musi również przesunąć zależności po ich załadowaniu. Te przesunięcia są wskazane w tabeli przesunięć w formatach REL lub RELA, a liczba przesunięć jest podana w sekcjach dynamicznych RELSZ lub RELASZ.
|
|
```
|
|
readelf -r lnstat
|
|
|
|
Relocation section '.rela.dyn' at offset 0xaa0 contains 23 entries:
|
|
Offset Info Type Sym. Value Sym. Name + Addend
|
|
00000001fc48 000000000403 R_AARCH64_RELATIV 1d10
|
|
00000001fc50 000000000403 R_AARCH64_RELATIV 1cc0
|
|
00000001fff0 000000000403 R_AARCH64_RELATIV 1340
|
|
000000020008 000000000403 R_AARCH64_RELATIV 20008
|
|
000000020010 000000000403 R_AARCH64_RELATIV 3330
|
|
000000020030 000000000403 R_AARCH64_RELATIV 3338
|
|
000000020050 000000000403 R_AARCH64_RELATIV 3340
|
|
000000020070 000000000403 R_AARCH64_RELATIV 3348
|
|
000000020090 000000000403 R_AARCH64_RELATIV 3350
|
|
0000000200b0 000000000403 R_AARCH64_RELATIV 3358
|
|
0000000200d0 000000000403 R_AARCH64_RELATIV 3360
|
|
0000000200f0 000000000403 R_AARCH64_RELATIV 3370
|
|
000000020110 000000000403 R_AARCH64_RELATIV 3378
|
|
000000020130 000000000403 R_AARCH64_RELATIV 3380
|
|
000000020150 000000000403 R_AARCH64_RELATIV 3388
|
|
00000001ffb8 000a00000401 R_AARCH64_GLOB_DA 0000000000000000 _ITM_deregisterTM[...] + 0
|
|
00000001ffc0 000b00000401 R_AARCH64_GLOB_DA 0000000000000000 __cxa_finalize@GLIBC_2.17 + 0
|
|
00000001ffc8 000f00000401 R_AARCH64_GLOB_DA 0000000000000000 stderr@GLIBC_2.17 + 0
|
|
00000001ffd0 001000000401 R_AARCH64_GLOB_DA 0000000000000000 optarg@GLIBC_2.17 + 0
|
|
00000001ffd8 001400000401 R_AARCH64_GLOB_DA 0000000000000000 stdout@GLIBC_2.17 + 0
|
|
00000001ffe0 001e00000401 R_AARCH64_GLOB_DA 0000000000000000 __gmon_start__ + 0
|
|
00000001ffe8 001f00000401 R_AARCH64_GLOB_DA 0000000000000000 __stack_chk_guard@GLIBC_2.17 + 0
|
|
00000001fff8 002e00000401 R_AARCH64_GLOB_DA 0000000000000000 _ITM_registerTMCl[...] + 0
|
|
|
|
Relocation section '.rela.plt' at offset 0xcc8 contains 40 entries:
|
|
Offset Info Type Sym. Value Sym. Name + Addend
|
|
00000001fe70 000300000402 R_AARCH64_JUMP_SL 0000000000000000 strtok@GLIBC_2.17 + 0
|
|
00000001fe78 000400000402 R_AARCH64_JUMP_SL 0000000000000000 strtoul@GLIBC_2.17 + 0
|
|
00000001fe80 000500000402 R_AARCH64_JUMP_SL 0000000000000000 strlen@GLIBC_2.17 + 0
|
|
00000001fe88 000600000402 R_AARCH64_JUMP_SL 0000000000000000 fputs@GLIBC_2.17 + 0
|
|
00000001fe90 000700000402 R_AARCH64_JUMP_SL 0000000000000000 exit@GLIBC_2.17 + 0
|
|
00000001fe98 000800000402 R_AARCH64_JUMP_SL 0000000000000000 __libc_start_main@GLIBC_2.34 + 0
|
|
00000001fea0 000900000402 R_AARCH64_JUMP_SL 0000000000000000 perror@GLIBC_2.17 + 0
|
|
00000001fea8 000b00000402 R_AARCH64_JUMP_SL 0000000000000000 __cxa_finalize@GLIBC_2.17 + 0
|
|
00000001feb0 000c00000402 R_AARCH64_JUMP_SL 0000000000000000 putc@GLIBC_2.17 + 0
|
|
00000001feb8 000d00000402 R_AARCH64_JUMP_SL 0000000000000000 opendir@GLIBC_2.17 + 0
|
|
00000001fec0 000e00000402 R_AARCH64_JUMP_SL 0000000000000000 fputc@GLIBC_2.17 + 0
|
|
00000001fec8 001100000402 R_AARCH64_JUMP_SL 0000000000000000 snprintf@GLIBC_2.17 + 0
|
|
00000001fed0 001200000402 R_AARCH64_JUMP_SL 0000000000000000 __snprintf_chk@GLIBC_2.17 + 0
|
|
00000001fed8 001300000402 R_AARCH64_JUMP_SL 0000000000000000 malloc@GLIBC_2.17 + 0
|
|
00000001fee0 001500000402 R_AARCH64_JUMP_SL 0000000000000000 gettimeofday@GLIBC_2.17 + 0
|
|
00000001fee8 001600000402 R_AARCH64_JUMP_SL 0000000000000000 sleep@GLIBC_2.17 + 0
|
|
00000001fef0 001700000402 R_AARCH64_JUMP_SL 0000000000000000 __vfprintf_chk@GLIBC_2.17 + 0
|
|
00000001fef8 001800000402 R_AARCH64_JUMP_SL 0000000000000000 calloc@GLIBC_2.17 + 0
|
|
00000001ff00 001900000402 R_AARCH64_JUMP_SL 0000000000000000 rewind@GLIBC_2.17 + 0
|
|
00000001ff08 001a00000402 R_AARCH64_JUMP_SL 0000000000000000 strdup@GLIBC_2.17 + 0
|
|
00000001ff10 001b00000402 R_AARCH64_JUMP_SL 0000000000000000 closedir@GLIBC_2.17 + 0
|
|
00000001ff18 001c00000402 R_AARCH64_JUMP_SL 0000000000000000 __stack_chk_fail@GLIBC_2.17 + 0
|
|
00000001ff20 001d00000402 R_AARCH64_JUMP_SL 0000000000000000 strrchr@GLIBC_2.17 + 0
|
|
00000001ff28 001e00000402 R_AARCH64_JUMP_SL 0000000000000000 __gmon_start__ + 0
|
|
00000001ff30 002000000402 R_AARCH64_JUMP_SL 0000000000000000 abort@GLIBC_2.17 + 0
|
|
00000001ff38 002100000402 R_AARCH64_JUMP_SL 0000000000000000 feof@GLIBC_2.17 + 0
|
|
00000001ff40 002200000402 R_AARCH64_JUMP_SL 0000000000000000 getopt_long@GLIBC_2.17 + 0
|
|
00000001ff48 002300000402 R_AARCH64_JUMP_SL 0000000000000000 __fprintf_chk@GLIBC_2.17 + 0
|
|
00000001ff50 002400000402 R_AARCH64_JUMP_SL 0000000000000000 strcmp@GLIBC_2.17 + 0
|
|
00000001ff58 002500000402 R_AARCH64_JUMP_SL 0000000000000000 free@GLIBC_2.17 + 0
|
|
00000001ff60 002600000402 R_AARCH64_JUMP_SL 0000000000000000 readdir64@GLIBC_2.17 + 0
|
|
00000001ff68 002700000402 R_AARCH64_JUMP_SL 0000000000000000 strndup@GLIBC_2.17 + 0
|
|
00000001ff70 002800000402 R_AARCH64_JUMP_SL 0000000000000000 strchr@GLIBC_2.17 + 0
|
|
00000001ff78 002900000402 R_AARCH64_JUMP_SL 0000000000000000 fwrite@GLIBC_2.17 + 0
|
|
```plaintext
|
|
00000001ff80 002a00000402 R_AARCH64_JUMP_SL 0000000000000000 fflush@GLIBC_2.17 + 0
|
|
00000001ff88 002b00000402 R_AARCH64_JUMP_SL 0000000000000000 fopen64@GLIBC_2.17 + 0
|
|
00000001ff90 002c00000402 R_AARCH64_JUMP_SL 0000000000000000 __isoc99_sscanf@GLIBC_2.17 + 0
|
|
00000001ff98 002d00000402 R_AARCH64_JUMP_SL 0000000000000000 strncpy@GLIBC_2.17 + 0
|
|
00000001ffa0 002f00000402 R_AARCH64_JUMP_SL 0000000000000000 __assert_fail@GLIBC_2.17 + 0
|
|
00000001ffa8 003000000402 R_AARCH64_JUMP_SL 0000000000000000 fgets@GLIBC_2.17 + 0
|
|
```
|
|
### Statyczne przemieszczenia
|
|
|
|
Jeśli **program jest załadowany w innym miejscu** niż preferowany adres (zwykle 0x400000) z powodu zajęcia adresu lub z powodu **ASLR** lub innych powodów, statyczne przemieszczenie **poprawia wskaźniki**, które miały wartości oczekujące, że binarny zostanie załadowany w preferowanym adresie.
|
|
|
|
Na przykład dowolna sekcja typu `R_AARCH64_RELATIV` powinna zmienić adres w przemieszczeniu plus wartość dodaną.
|
|
|
|
### Dynamiczne przemieszczenia i GOT
|
|
|
|
Przemieszczenie może również odnosić się do symbolu zewnętrznego (jak funkcja zależności). Na przykład funkcja malloc z libC. Wtedy, ładowacz podczas ładowania libC pod adresem sprawdzającym, gdzie jest załadowana funkcja malloc, zapisze ten adres w tabeli GOT (Global Offset Table) (wskazanej w tabeli przemieszczeń), gdzie powinien być określony adres malloc.
|
|
|
|
### Tabela łączenia procedur
|
|
|
|
Sekcja PLT pozwala na leniwe wiązanie, co oznacza, że rozwiązanie lokalizacji funkcji będzie wykonywane za pierwszym razem, gdy zostanie ona użyta.
|
|
|
|
Więc gdy program wywołuje malloc, faktycznie wywołuje odpowiadającą lokalizację `malloc` w PLT (`malloc@plt`). Za pierwszym razem, gdy jest wywoływana, rozwiązuje adres `malloc` i przechowuje go, więc następnym razem, gdy jest wywoływana malloc, używany jest ten adres zamiast kodu PLT.
|
|
|
|
## Inicjalizacja programu
|
|
|
|
Po załadowaniu programu nadszedł czas na jego uruchomienie. Jednak pierwszy kod, który jest uruchamiany, **nie zawsze jest funkcją `main`**. Dzieje się tak na przykład w C++, gdy **zmienna globalna jest obiektem klasy**, ten obiekt musi być **zainicjowany** **przed** uruchomieniem funkcji main, jak w:
|
|
```cpp
|
|
#include <stdio.h>
|
|
// g++ autoinit.cpp -o autoinit
|
|
class AutoInit {
|
|
public:
|
|
AutoInit() {
|
|
printf("Hello AutoInit!\n");
|
|
}
|
|
~AutoInit() {
|
|
printf("Goodbye AutoInit!\n");
|
|
}
|
|
};
|
|
|
|
AutoInit autoInit;
|
|
|
|
int main() {
|
|
printf("Main\n");
|
|
return 0;
|
|
}
|
|
```
|
|
Zauważ, że te zmienne globalne znajdują się w `.data` lub `.bss`, ale w listach `__CTOR_LIST__` i `__DTOR_LIST__` obiekty do zainicjowania i zniszczenia są przechowywane w celu śledzenia ich.
|
|
|
|
Z kodu C można uzyskać ten sam wynik, korzystając z rozszerzeń GNU:
|
|
```c
|
|
__attributte__((constructor)) //Add a constructor to execute before
|
|
__attributte__((destructor)) //Add to the destructor list
|
|
```
|
|
Z perspektywy kompilatora, aby wykonać te czynności przed i po wykonaniu funkcji `main`, można utworzyć funkcję `init` i funkcję `fini`, które będą odwoływane w sekcji dynamicznej jako **`INIT`** i **`FIN`** oraz umieszczone w sekcjach `init` i `fini` pliku ELF.
|
|
|
|
Inną opcją, jak wspomniano, jest odwołanie do list **`__CTOR_LIST__`** i **`__DTOR_LIST__** w wpisach **`INIT_ARRAY`** i **`FINI_ARRAY`** sekcji dynamicznej, a ich długość jest określana przez **`INIT_ARRAYSZ`** i **`FINI_ARRAYSZ`**. Każdy wpis to wskaźnik funkcji, który zostanie wywołany bez argumentów.
|
|
|
|
Ponadto możliwe jest posiadanie **`PREINIT_ARRAY`** z **wskaźnikami**, które zostaną wykonane **przed** wskaźnikami **`INIT_ARRAY`**.
|
|
|
|
### Kolejność inicjalizacji
|
|
|
|
1. Program jest wczytywany do pamięci, statyczne zmienne globalne są inicjowane w sekcji **`.data`**, a niezainicjowane są zerowane w sekcji **`.bss`**.
|
|
2. Wszystkie **zależności** programu lub bibliotek są **inicjowane**, a następnie wykonywane jest **dynamiczne łączenie**.
|
|
3. Wykonywane są funkcje **`PREINIT_ARRAY`**.
|
|
4. Wykonywane są funkcje **`INIT_ARRAY`**.
|
|
5. Jeśli istnieje wpis **`INIT`**, zostaje on wywołany.
|
|
6. Jeśli to biblioteka, dlopen kończy działanie tutaj, jeśli to program, nadszedł czas na wywołanie **prawdziwego punktu wejścia** (funkcji `main`).
|
|
|
|
## Pamięć lokalna wątku (TLS)
|
|
|
|
Są one definiowane za pomocą słowa kluczowego **`__thread_local`** w C++ lub rozszerzenia GNU **`__thread`**.
|
|
|
|
Każdy wątek będzie utrzymywał unikalne miejsce dla tej zmiennej, dzięki czemu tylko wątek może uzyskać dostęp do swojej zmiennej.
|
|
|
|
Gdy jest to używane, sekcje **`.tdata`** i **`.tbss`** są używane w pliku ELF. Są to odpowiedniki `.data` (zainicjowane) i `.bss` (niezainicjowane), ale dla TLS.
|
|
|
|
Każda zmienna ma wpis w nagłówku TLS określający rozmiar i przesunięcie TLS, czyli przesunięcie, które będzie używane w lokalnej przestrzeni danych wątku.
|
|
|
|
`__TLS_MODULE_BASE` to symbol używany do odwołania do bazowego adresu pamięci lokalnej wątku i wskazuje na obszar w pamięci zawierający wszystkie dane lokalne wątku modułu.
|