mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/binary-exploitation/basic-stack-binary-exploitation-met
This commit is contained in:
parent
400a0110da
commit
110fa22551
@ -37,20 +37,22 @@ Segment Sections...
|
||||
07
|
||||
08 .init_array .fini_array .dynamic .got
|
||||
```
|
||||
Poprzedni program ma **9 nagłówków programów**, a następnie **mapowanie segmentów** wskazuje, w którym nagłówku programu (od 00 do 08) **znajduje się każda sekcja**.
|
||||
Poprzedni program ma **9 nagłówków programów**, a **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 i same metadane.
|
||||
Zawiera tabele nagłówków programów oraz metadane.
|
||||
|
||||
### INTERP
|
||||
|
||||
Wskazuje ścieżkę do loadera, który ma być użyty do załadowania binarnego do pamięci.
|
||||
|
||||
> Wskazówka: Statycznie linkowane lub statyczne binaria PIE nie będą miały wpisu `INTERP`. W takich przypadkach nie ma zaangażowanego dynamicznego loadera, co wyłącza techniki, które na nim polegają (np. `ret2dlresolve`).
|
||||
|
||||
### LOAD
|
||||
|
||||
Te nagłówki są używane do wskazania **jak załadować binarny do pamięci.**\
|
||||
Każdy nagłówek **LOAD** wskazuje obszar **pamięci** (rozmiar, uprawnienia i wyrównanie) i wskazuje bajty ELF **binarnego do skopiowania tam**.
|
||||
Każdy nagłówek **LOAD** wskazuje region **pamięci** (rozmiar, uprawnienia i wyrównanie) i wskazuje bajty ELF **binarnego do skopiowania tam**.
|
||||
|
||||
Na przykład, drugi ma rozmiar 0x1190, powinien znajdować się na 0x1fc48 z uprawnieniami do odczytu i zapisu i będzie wypełniony 0x528 z offsetu 0xfc48 (nie wypełnia całej zarezerwowanej przestrzeni). Ta pamięć będzie zawierać sekcje `.init_array .fini_array .dynamic .got .data .bss`.
|
||||
|
||||
@ -60,7 +62,13 @@ Ten nagłówek pomaga łączyć programy z ich zależnościami bibliotecznymi i
|
||||
|
||||
### NOTE
|
||||
|
||||
Przechowuje informacje metadanych dostawcy o binarnym.
|
||||
Przechowuje informacje metadane dostawcy o binarnym.
|
||||
|
||||
- Na x86-64, `readelf -n` pokaże flagi `GNU_PROPERTY_X86_FEATURE_1_*` wewnątrz `.note.gnu.property`. Jeśli zobaczysz `IBT` i/lub `SHSTK`, binarny został zbudowany z CET (Śledzenie Pośrednich Skoków i/lub Stos Cieni). Ma to wpływ na ROP/JOP, ponieważ cele pośrednich skoków muszą zaczynać się od instrukcji `ENDBR64`, a powroty są sprawdzane w stosie cieni. Zobacz stronę CET, aby uzyskać szczegóły i notatki o obejściach.
|
||||
|
||||
{{#ref}}
|
||||
../common-binary-protections-and-bypasses/cet-and-shadow-stack.md
|
||||
{{#endref}}
|
||||
|
||||
### GNU_EH_FRAME
|
||||
|
||||
@ -70,13 +78,21 @@ Definiuje lokalizację tabel unwind stosu, używanych przez debugery i funkcje o
|
||||
|
||||
Zawiera konfigurację obrony przed wykonywaniem kodu ze stosu. Jeśli jest włączona, binarny nie będzie mógł wykonywać kodu ze stosu.
|
||||
|
||||
- Sprawdź za pomocą `readelf -l ./bin | grep GNU_STACK`. Aby wymusić przełączenie podczas testów, możesz użyć `execstack -s|-c ./bin`.
|
||||
|
||||
### GNU_RELRO
|
||||
|
||||
Wskazuje konfigurację RELRO (Relocation Read-Only) binarnego. Ta ochrona oznaczy jako tylko do odczytu niektóre sekcje pamięci (jak `GOT` lub tabele `init` i `fini`) po załadowaniu programu i przed jego uruchomieniem.
|
||||
|
||||
W poprzednim przykładzie kopiuje 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 **leniwego wiązania** i potrzebuje tej przestrzeni pamięci, aby mieć **uprawnienia do zapisu**, aby zapisać adres bibliotek przy pierwszym wyszukiwaniu ich lokalizacji.
|
||||
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 **leniwego wiązania** i potrzebuje tej przestrzeni pamięci, aby mieć **uprawnienia do zapisu**, aby zapisać adres bibliotek za pierwszym razem, gdy ich lokalizacja jest wyszukiwana.
|
||||
|
||||
> Aby uzyskać techniki eksploatacji i aktualne notatki o obejściach, sprawdź dedykowaną stronę:
|
||||
|
||||
{{#ref}}
|
||||
../common-binary-protections-and-bypasses/relro.md
|
||||
{{#endref}}
|
||||
|
||||
### TLS
|
||||
|
||||
@ -145,21 +161,21 @@ CONTENTS, READONLY
|
||||
25 .gnu_debuglink 00000034 0000000000000000 0000000000000000 000101bc 2**2
|
||||
CONTENTS, READONLY
|
||||
```
|
||||
Wskazuje również lokalizację, przesunięcie, uprawnienia, ale także **typ danych**, który ma sekcja.
|
||||
To również wskazuje lokalizację, przesunięcie, uprawnienia, ale także **typ danych**, który ma sekcja.
|
||||
|
||||
### Sekcje Meta
|
||||
|
||||
- **Tabela ciągów**: Zawiera wszystkie ciągi potrzebne przez plik ELF (ale nie te, które są faktycznie używane przez program). Na przykład zawiera nazwy sekcji takie jak `.text` lub `.data`. A jeśli `.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 inne metadane dotyczące symbolu.
|
||||
- **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
|
||||
### Sekcje Główne
|
||||
|
||||
- **`.text`**: Instrukcja programu do uruchomienia.
|
||||
- **`.data`**: Zmienne globalne z określoną wartością w programie.
|
||||
- **`.bss`**: Zmienne globalne pozostawione niezainicjowane (lub zainicjowane na zero). Zmienne tutaj są automatycznie inicjowane na zero, co zapobiega dodawaniu zbędnych zer do binarnego.
|
||||
- **`.bss`**: Zmienne globalne, które nie zostały zainicjowane (lub zainicjowane na zero). Zmienne tutaj są automatycznie inicjowane na zero, co zapobiega dodawaniu zbędnych zer do binarnego.
|
||||
- **`.rodata`**: Stałe zmienne globalne (sekcja tylko do odczytu).
|
||||
- **`.tdata`** i **`.tbss`**: Jak .data i .bss, gdy używane są zmienne lokalne dla wątków (`__thread_local` w C++ lub `__thread` w C).
|
||||
- **`.tdata`** i **`.tbss`**: Podobnie jak .data i .bss, gdy używane są zmienne lokalne dla wątków (`__thread_local` w C++ lub `__thread` w C).
|
||||
- **`.dynamic`**: Zobacz poniżej.
|
||||
|
||||
## Symbole
|
||||
@ -189,11 +205,15 @@ Każdy wpis symbolu zawiera:
|
||||
|
||||
- **Nazwa**
|
||||
- **Atrybuty powiązania** (słaby, lokalny lub globalny): Lokalny symbol może być dostępny tylko przez sam program, podczas gdy symbole globalne są udostępniane poza programem. Słaby obiekt to na przykład funkcja, która może być nadpisana przez inną.
|
||||
- **Typ**: NOTYPE (typ nieokreślony), OBJECT (globalna zmienna danych), FUNC (funkcja), SECTION (sekcja), FILE (plik źródłowy dla debuggerów), TLS (zmienna lokalna wątku), GNU_IFUNC (funkcja pośrednia do relokacji)
|
||||
- **Typ**: NOTYPE (typ nieokreślony), OBJECT (globalna zmienna danych), FUNC (funkcja), SECTION (sekcja), FILE (plik źródłowy dla debuggerów), TLS (zmienna lokalna dla wątku), GNU_IFUNC (funkcja pośrednia do relokacji)
|
||||
- **Indeks sekcji**, w której się znajduje
|
||||
- **Wartość** (adres w pamięci)
|
||||
- **Rozmiar**
|
||||
|
||||
#### Wersjonowanie symboli GNU (dynsym/dynstr/gnu.version)
|
||||
|
||||
Nowoczesny glibc używa wersji symboli. Zobaczysz wpisy w `.gnu.version` i `.gnu.version_r` oraz nazwy symboli takie jak `strlen@GLIBC_2.17`. Linker dynamiczny może wymagać konkretnej wersji przy rozwiązywaniu symbolu. Przy tworzeniu ręcznych relokacji (np. ret2dlresolve) musisz podać poprawny indeks wersji, w przeciwnym razie rozwiązywanie się nie powiedzie.
|
||||
|
||||
## Sekcja dynamiczna
|
||||
```
|
||||
readelf -d lnstat
|
||||
@ -231,9 +251,26 @@ Tag Type Name/Value
|
||||
```
|
||||
Katalog NEEDED wskazuje, że program **musi załadować wspomnianą bibliotekę**, aby kontynuować. Katalog NEEDED kończy się, gdy wspólna **biblioteka jest w pełni operacyjna i gotowa** do użycia.
|
||||
|
||||
### Kolejność wyszukiwania dynamicznego loadera (RPATH/RUNPATH, $ORIGIN)
|
||||
|
||||
Wpisy `DT_RPATH` (przestarzałe) i/lub `DT_RUNPATH` wpływają na to, gdzie dynamiczny loader szuka zależności. Przybliżona kolejność:
|
||||
|
||||
- `LD_LIBRARY_PATH` (ignorowane dla programów setuid/sgid lub innych "bezpiecznych" programów)
|
||||
- `DT_RPATH` (tylko jeśli `DT_RUNPATH` nieobecny)
|
||||
- `DT_RUNPATH`
|
||||
- `ld.so.cache`
|
||||
- domyślne katalogi, takie jak `/lib64`, `/usr/lib64` itp.
|
||||
|
||||
`$ORIGIN` może być używane wewnątrz RPATH/RUNPATH, aby odwołać się do katalogu głównego obiektu. Z perspektywy atakującego ma to znaczenie, gdy kontrolujesz układ systemu plików lub środowisko. Dla wzmocnionych binariów (AT_SECURE) większość zmiennych środowiskowych jest ignorowana przez loader.
|
||||
|
||||
- Sprawdź za pomocą: `readelf -d ./bin | egrep -i 'r(path|unpath)'`
|
||||
- Szybki test: `LD_DEBUG=libs ./bin 2>&1 | grep -i find` (pokazuje decyzje dotyczące ścieżki wyszukiwania)
|
||||
|
||||
> Wskazówka dotycząca eskalacji uprawnień: Preferuj nadużywanie zapisywalnych RUNPATHów lub źle skonfigurowanych ścieżek względnych do `$ORIGIN`, które są w twoim posiadaniu. LD_PRELOAD/LD_AUDIT są ignorowane w kontekstach bezpiecznego wykonania (setuid).
|
||||
|
||||
## Relokacje
|
||||
|
||||
Loader musi również relokować zależności po ich załadowaniu. Te relokacje są wskazane w tabeli relokacji w formatach REL lub RELA, a liczba relokacji podana jest w sekcjach dynamicznych RELSZ lub RELASZ.
|
||||
Loader musi również relokować zależności po ich załadowaniu. Te relokacje są wskazane w tabeli relokacji w formatach REL lub RELA, a liczba relokacji jest podana w sekcjach dynamicznych RELSZ lub RELASZ.
|
||||
```
|
||||
readelf -r lnstat
|
||||
|
||||
@ -274,7 +311,6 @@ Offset Info Type Sym. Value Sym. Name + Addend
|
||||
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
|
||||
@ -308,13 +344,13 @@ Offset Info Type Sym. Value Sym. Name + Addend
|
||||
```
|
||||
### Statyczne Relokacje
|
||||
|
||||
Jeśli **program jest załadowany w innym miejscu** niż preferowany adres (zwykle 0x400000), ponieważ adres jest już używany lub z powodu **ASLR** lub innego powodu, statyczna relokacja **poprawia wskaźniki**, które miały wartości oczekujące, że binarny plik zostanie załadowany w preferowanym adresie.
|
||||
Jeśli **program jest ładowany w innym miejscu** niż preferowany adres (zwykle 0x400000) z powodu już używanego adresu lub z powodu **ASLR** lub innego powodu, statyczna relokacja **poprawia wskaźniki**, które miały wartości oczekujące, że binarny plik zostanie załadowany w preferowanym adresie.
|
||||
|
||||
Na przykład każda sekcja typu `R_AARCH64_RELATIV` powinna mieć zmodyfikowany adres o wartość przesunięcia relokacji plus wartość dodaną.
|
||||
Na przykład każda sekcja typu `R_AARCH64_RELATIV` powinna mieć zmodyfikowany adres na podstawie przesunięcia relokacji plus wartość addenda.
|
||||
|
||||
### Dynamiczne Relokacje i GOT
|
||||
|
||||
Relokacja może również odnosić się do zewnętrznego symbolu (jak funkcja z zależności). Na przykład funkcja malloc z libC. Wtedy, loader, ładując libC w adresie, sprawdza, gdzie funkcja malloc jest załadowana, i zapisuje ten adres w tabeli GOT (Global Offset Table) (wskazanej w tabeli relokacji), gdzie powinien być określony adres malloc.
|
||||
Relokacja może również odnosić się do zewnętrznego symbolu (jak funkcja z zależności). Na przykład funkcja malloc z libC. Wtedy, loader, ładowując libC w adresie, sprawdza, gdzie funkcja malloc jest załadowana, i zapisuje ten adres w tabeli GOT (Global Offset Table) (wskazanej w tabeli relokacji), gdzie powinien być określony adres malloc.
|
||||
|
||||
### Tabela Łączenia Procedur
|
||||
|
||||
@ -322,6 +358,24 @@ Sekcja PLT pozwala na leniwe wiązanie, co oznacza, że rozwiązywanie lokalizac
|
||||
|
||||
Więc gdy program wywołuje malloc, tak naprawdę wywołuje odpowiednią lokalizację `malloc` w PLT (`malloc@plt`). Przy pierwszym wywołaniu rozwiązuje adres `malloc` i przechowuje go, więc następnym razem, gdy wywołana zostanie `malloc`, ten adres jest używany zamiast kodu PLT.
|
||||
|
||||
#### Nowoczesne zachowania łączenia, które wpływają na eksploatację
|
||||
|
||||
- `-z now` (Pełne RELRO) wyłącza leniwe wiązanie; wpisy PLT nadal istnieją, ale GOT/PLT jest mapowane jako tylko do odczytu, więc techniki takie jak **GOT overwrite** i **ret2dlresolve** nie będą działać przeciwko głównemu binarnemu plikowi (biblioteki mogą nadal być częściowo RELRO). Zobacz:
|
||||
|
||||
{{#ref}}
|
||||
../common-binary-protections-and-bypasses/relro.md
|
||||
{{#endref}}
|
||||
|
||||
- `-fno-plt` sprawia, że kompilator wywołuje zewnętrzne funkcje przez **wejście GOT bezpośrednio** zamiast przechodzić przez stub PLT. Zobaczysz sekwencje wywołań takie jak `mov reg, [got]; call reg` zamiast `call func@plt`. To zmniejsza nadużycia związane z wykonaniem spekulacyjnym i nieco zmienia polowanie na gadżety ROP wokół stubów PLT.
|
||||
|
||||
- PIE vs static-PIE: PIE (ET_DYN z `INTERP`) potrzebuje dynamicznego loadera i wspiera zwykłą maszynerię PLT/GOT. Static-PIE (ET_DYN bez `INTERP`) ma relokacje stosowane przez loader jądra i brak `ld.so`; oczekuj braku rozwiązywania PLT w czasie wykonywania.
|
||||
|
||||
> Jeśli GOT/PLT nie jest opcją, przejdź do innych zapisywalnych wskaźników kodu lub użyj klasycznego ROP/SROP w libc.
|
||||
|
||||
{{#ref}}
|
||||
../arbitrary-write-2-exec/aw2exec-got-plt.md
|
||||
{{#endref}}
|
||||
|
||||
## Inicjalizacja Programu
|
||||
|
||||
Po załadowaniu programu nadszedł czas, aby go uruchomić. Jednak pierwszy kod, który jest uruchamiany, **nie zawsze jest funkcją `main`**. Dzieje się tak, ponieważ na przykład w C++, jeśli **zmienna globalna jest obiektem klasy**, ten obiekt musi być **zainicjowany** **przed** uruchomieniem main, jak w:
|
||||
@ -347,36 +401,73 @@ return 0;
|
||||
```
|
||||
Zauważ, że te zmienne globalne znajdują się w `.data` lub `.bss`, ale w listach `__CTOR_LIST__` i `__DTOR_LIST__` obiekty do inicjalizacji i destrukcji są przechowywane w celu ich śledzenia.
|
||||
|
||||
Z kodu C można uzyskać ten sam wynik, używając rozszerzeń GNU:
|
||||
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 działania przed i po wykonaniu funkcji `main`, można stworzyć funkcję `init` i funkcję `fini`, które będą odniesione w sekcji dynamicznej jako **`INIT`** i **`FIN`**. i są umieszczone w sekcjach `init` i `fini` ELF.
|
||||
Z perspektywy kompilatora, aby wykonać te działania przed i po wykonaniu funkcji `main`, można stworzyć funkcję `init` i funkcję `fini`, które będą odniesione w sekcji dynamicznej jako **`INIT`** i **`FIN`**. Są one umieszczane w sekcjach `init` i `fini` ELF.
|
||||
|
||||
Inną opcją, jak wspomniano, jest odniesienie do list **`__CTOR_LIST__`** i **`__DTOR_LIST__`** w wpisach **`INIT_ARRAY`** i **`FINI_ARRAY`** w sekcji dynamicznej, a długość tych list jest wskazywana przez **`INIT_ARRAYSZ`** i **`FINI_ARRAYSZ`**. Każdy wpis to wskaźnik do funkcji, która będzie wywoływana bez argumentów.
|
||||
|
||||
Ponadto, możliwe jest również posiadanie **`PREINIT_ARRAY`** z **wskaźnikami**, które będą wykonywane **przed** wskaźnikami **`INIT_ARRAY`**.
|
||||
Co więcej, możliwe jest również posiadanie **`PREINIT_ARRAY`** z **wskaźnikami**, które będą wykonywane **przed** wskaźnikami **`INIT_ARRAY`**.
|
||||
|
||||
#### Uwagi dotyczące eksploatacji
|
||||
|
||||
- W przypadku Partial RELRO te tablice znajdują się w stronach, które są nadal zapisywalne, zanim `ld.so` zmieni `PT_GNU_RELRO` na tylko do odczytu. Jeśli uzyskasz dowolny zapis wystarczająco wcześnie lub możesz celować w zapisywalne tablice biblioteki, możesz przejąć kontrolę nad przepływem, nadpisując wpis funkcją według własnego wyboru. W przypadku Full RELRO są one tylko do odczytu w czasie wykonywania.
|
||||
|
||||
- Aby wykorzystać leniwe wiązanie dynamicznego linkera do rozwiązywania dowolnych symboli w czasie wykonywania, zobacz dedykowaną stronę:
|
||||
|
||||
{{#ref}}
|
||||
../rop-return-oriented-programing/ret2dlresolve.md
|
||||
{{#endref}}
|
||||
|
||||
### Kolejność inicjalizacji
|
||||
|
||||
1. Program jest ładowany do pamięci, statyczne zmienne globalne są inicjalizowane w **`.data`** a niezainicjowane są zerowane w **`.bss`**.
|
||||
2. Wszystkie **zależności** dla programu lub bibliotek są **inicjowane** i wykonywane jest **dynamiczne linkowanie**.
|
||||
2. Wszystkie **zależności** dla programu lub bibliotek są **inicjowane** i wykonywane jest **dynamiczne wiązanie**.
|
||||
3. Funkcje **`PREINIT_ARRAY`** są wykonywane.
|
||||
4. Funkcje **`INIT_ARRAY`** są wykonywane.
|
||||
5. Jeśli istnieje wpis **`INIT`**, jest wywoływany.
|
||||
6. Jeśli jest to biblioteka, dlopen kończy się tutaj, jeśli program, nadszedł czas na wywołanie **prawdziwego punktu wejścia** (funkcja `main`).
|
||||
5. Jeśli istnieje wpis **`INIT`**, jest on wywoływany.
|
||||
6. Jeśli jest to biblioteka, dlopen kończy się tutaj, jeśli program, nadszedł czas na wywołanie **rzeczywistego punktu wejścia** (funkcja `main`).
|
||||
|
||||
## Pamięć lokalna dla wątków (TLS)
|
||||
|
||||
Są definiowane za pomocą słowa kluczowego **`__thread_local`** w C++ lub rozszerzenia GNU **`__thread`**.
|
||||
Są one definiowane za pomocą słowa kluczowego **`__thread_local`** w C++ lub rozszerzenia GNU **`__thread`**.
|
||||
|
||||
Każdy wątek będzie utrzymywał unikalną lokalizację dla tej zmiennej, więc tylko wątek może uzyskać dostęp do swojej zmiennej.
|
||||
|
||||
Gdy to jest używane, sekcje **`.tdata`** i **`.tbss`** są używane w ELF. Które są podobne do `.data` (zainicjowane) i `.bss` (niezainicjowane), ale dla TLS.
|
||||
Gdy to jest używane, sekcje **`.tdata`** i **`.tbss`** są używane w ELF. Są one podobne do `.data` (zainicjowane) i `.bss` (niezainicjowane), ale dla TLS.
|
||||
|
||||
Każda zmienna będzie miała wpis w nagłówku TLS określający rozmiar i offset TLS, który jest offsetem, który będzie używany w lokalnym obszarze danych wątku.
|
||||
Każda zmienna będzie miała wpis w nagłówku TLS określający rozmiar i offset TLS, który jest offsetem, którego użyje w lokalnym obszarze danych wątku.
|
||||
|
||||
Symbol `__TLS_MODULE_BASE` jest używany do odniesienia się do adresu bazowego pamięci lokalnej wątku i wskazuje na obszar w pamięci, który zawiera wszystkie dane lokalne wątku modułu.
|
||||
`__TLS_MODULE_BASE` to symbol używany do odniesienia się do adresu bazowego pamięci lokalnej wątku i wskazuje na obszar w pamięci, który zawiera wszystkie dane lokalne wątku modułu.
|
||||
|
||||
## Wektor pomocniczy (auxv) i vDSO
|
||||
|
||||
Jądro Linuxa przekazuje wektor pomocniczy do procesów zawierający użyteczne adresy i flagi dla czasu wykonywania:
|
||||
|
||||
- `AT_RANDOM`: wskazuje na 16 losowych bajtów używanych przez glibc do canary stosu i innych nasion PRNG.
|
||||
- `AT_SYSINFO_EHDR`: adres bazowy mapowania vDSO (przydatne do znajdowania wywołań syscalls `__kernel_*` i gadżetów).
|
||||
- `AT_EXECFN`, `AT_BASE`, `AT_PAGESZ` itd.
|
||||
|
||||
Jako atakujący, jeśli możesz czytać pamięć lub pliki w `/proc`, często możesz wyciekować te informacje bez infoleaku w docelowym procesie:
|
||||
```bash
|
||||
# Show the auxv of a running process
|
||||
cat /proc/$(pidof target)/auxv | xxd
|
||||
|
||||
# From your own process (helper snippet)
|
||||
#include <sys/auxv.h>
|
||||
#include <stdio.h>
|
||||
int main(){
|
||||
printf("AT_RANDOM=%p\n", (void*)getauxval(AT_RANDOM));
|
||||
printf("AT_SYSINFO_EHDR=%p\n", (void*)getauxval(AT_SYSINFO_EHDR));
|
||||
}
|
||||
```
|
||||
Wyciekanie `AT_RANDOM` daje ci wartość canary, jeśli możesz zdereferencjonować ten wskaźnik; `AT_SYSINFO_EHDR` daje ci bazę vDSO do wydobywania gadgetów lub do bezpośredniego wywoływania szybkich syscalls.
|
||||
|
||||
## References
|
||||
|
||||
- ld.so(8) – Dynamic Loader search order, RPATH/RUNPATH, secure-execution rules (AT_SECURE): https://man7.org/linux/man-pages/man8/ld.so.8.html
|
||||
- getauxval(3) – Auxiliary vector and AT_* constants: https://man7.org/linux/man-pages/man3/getauxval.3.html
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user