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
a07a12dee0
commit
93fecbc389
@ -1,8 +1,8 @@
|
||||
# Informazioni di base su ELF
|
||||
# ELF Informazioni di Base
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Intestazioni del programma
|
||||
## Intestazioni del Programma
|
||||
|
||||
Descrivono al loader come caricare l'**ELF** in memoria:
|
||||
```bash
|
||||
@ -37,31 +37,39 @@ Segment Sections...
|
||||
07
|
||||
08 .init_array .fini_array .dynamic .got
|
||||
```
|
||||
Il programma precedente ha **9 intestazioni di programma**, quindi, la **mappatura dei segmenti** indica in quale intestazione di programma (da 00 a 08) **si trova ciascuna sezione**.
|
||||
The previous program has **9 program headers**, then, the **segment mapping** indicates in which program header (from 00 to 08) **each section is located**.
|
||||
|
||||
### PHDR - Program HeaDeR
|
||||
|
||||
Contiene le tabelle delle intestazioni di programma e i metadati stessi.
|
||||
Contiene le tabelle degli header del programma e i metadati stessi.
|
||||
|
||||
### INTERP
|
||||
|
||||
Indica il percorso del loader da utilizzare per caricare il binario in memoria.
|
||||
|
||||
> Tip: I binari staticamente collegati o static-PIE non avranno un'entrata `INTERP`. In questi casi non è coinvolto alcun loader dinamico, il che disabilita le tecniche che si basano su di esso (ad es., `ret2dlresolve`).
|
||||
|
||||
### LOAD
|
||||
|
||||
Queste intestazioni vengono utilizzate per indicare **come caricare un binario in memoria.**\
|
||||
Ogni intestazione **LOAD** indica una regione di **memoria** (dimensione, permessi e allineamento) e indica i byte del binario ELF **da copiare lì**.
|
||||
Questi header sono utilizzati per indicare **come caricare un binario in memoria.**\
|
||||
Ogni header **LOAD** indica una regione di **memoria** (dimensione, permessi e allineamento) e indica i byte del binario ELF **da copiare lì**.
|
||||
|
||||
Ad esempio, la seconda ha una dimensione di 0x1190, dovrebbe trovarsi a 0x1fc48 con permessi di lettura e scrittura e sarà riempita con 0x528 dall'offset 0xfc48 (non riempie tutto lo spazio riservato). Questa memoria conterrà le sezioni `.init_array .fini_array .dynamic .got .data .bss`.
|
||||
Ad esempio, il secondo ha una dimensione di 0x1190, dovrebbe trovarsi a 0x1fc48 con permessi di lettura e scrittura e sarà riempito con 0x528 dall'offset 0xfc48 (non riempie tutto lo spazio riservato). Questa memoria conterrà le sezioni `.init_array .fini_array .dynamic .got .data .bss`.
|
||||
|
||||
### DYNAMIC
|
||||
|
||||
Questa intestazione aiuta a collegare i programmi alle loro dipendenze di libreria e ad applicare le rilocalizzazioni. Controlla la sezione **`.dynamic`**.
|
||||
Questo header aiuta a collegare i programmi alle loro dipendenze di libreria e ad applicare le rilocalizzazioni. Controlla la sezione **`.dynamic`**.
|
||||
|
||||
### NOTE
|
||||
|
||||
Questo memorizza informazioni sui metadati del fornitore riguardo al binario.
|
||||
|
||||
- Su x86-64, `readelf -n` mostrerà i flag `GNU_PROPERTY_X86_FEATURE_1_*` all'interno di `.note.gnu.property`. Se vedi `IBT` e/o `SHSTK`, il binario è stato costruito con CET (Indirect Branch Tracking e/o Shadow Stack). Questo impatta ROP/JOP perché i target di branch indiretti devono iniziare con un'istruzione `ENDBR64` e i ritorni sono controllati contro uno shadow stack. Vedi la pagina CET per dettagli e note di bypass.
|
||||
|
||||
{{#ref}}
|
||||
../common-binary-protections-and-bypasses/cet-and-shadow-stack.md
|
||||
{{#endref}}
|
||||
|
||||
### GNU_EH_FRAME
|
||||
|
||||
Definisce la posizione delle tabelle di unwind dello stack, utilizzate dai debugger e dalle funzioni di runtime per la gestione delle eccezioni in C++.
|
||||
@ -70,21 +78,29 @@ Definisce la posizione delle tabelle di unwind dello stack, utilizzate dai debug
|
||||
|
||||
Contiene la configurazione della difesa contro l'esecuzione dello stack. Se abilitato, il binario non sarà in grado di eseguire codice dallo stack.
|
||||
|
||||
- Controlla con `readelf -l ./bin | grep GNU_STACK`. Per forzare il toggle durante i test puoi usare `execstack -s|-c ./bin`.
|
||||
|
||||
### GNU_RELRO
|
||||
|
||||
Indica la configurazione RELRO (Relocation Read-Only) del binario. Questa protezione contrassegnerà come di sola lettura alcune sezioni della memoria (come il `GOT` o le tabelle `init` e `fini`) dopo che il programma è stato caricato e prima che inizi a essere eseguito.
|
||||
|
||||
Nell'esempio precedente sta copiando 0x3b8 byte a 0x1fc48 come di sola lettura, influenzando le sezioni `.init_array .fini_array .dynamic .got .data .bss`.
|
||||
|
||||
Nota che RELRO può essere parziale o completo, la versione parziale non protegge la sezione **`.plt.got`**, che viene utilizzata per il **lazy binding** e ha bisogno di questo spazio di memoria per avere **permessi di scrittura** per scrivere l'indirizzo delle librerie la prima volta che viene cercata la loro posizione.
|
||||
Nota che RELRO può essere parziale o completo, la versione parziale non protegge la sezione **`.plt.got`**, che è utilizzata per il **lazy binding** e ha bisogno di questo spazio di memoria per avere **permessi di scrittura** per scrivere l'indirizzo delle librerie la prima volta che la loro posizione viene cercata.
|
||||
|
||||
> Per tecniche di sfruttamento e note di bypass aggiornate, controlla la pagina dedicata:
|
||||
|
||||
{{#ref}}
|
||||
../common-binary-protections-and-bypasses/relro.md
|
||||
{{#endref}}
|
||||
|
||||
### TLS
|
||||
|
||||
Definisce una tabella di voci TLS, che memorizza informazioni sulle variabili locali al thread.
|
||||
Definisce una tabella di voci TLS, che memorizza informazioni sulle variabili locali del thread.
|
||||
|
||||
## Section Headers
|
||||
|
||||
Le intestazioni delle sezioni forniscono una visione più dettagliata del binario ELF.
|
||||
Gli header delle sezioni forniscono una vista più dettagliata del binario ELF.
|
||||
```
|
||||
objdump lnstat -h
|
||||
|
||||
@ -145,7 +161,7 @@ CONTENTS, READONLY
|
||||
25 .gnu_debuglink 00000034 0000000000000000 0000000000000000 000101bc 2**2
|
||||
CONTENTS, READONLY
|
||||
```
|
||||
Indica anche la posizione, l'offset, i permessi ma anche il **tipo di dati** che ha la sua sezione.
|
||||
It indicates anche la posizione, l'offset, i permessi ma anche il **tipo di dati** che ha la sua sezione.
|
||||
|
||||
### Sezioni Meta
|
||||
|
||||
@ -159,12 +175,12 @@ Indica anche la posizione, l'offset, i permessi ma anche il **tipo di dati** che
|
||||
- **`.data`**: Variabili globali con un valore definito nel programma.
|
||||
- **`.bss`**: Variabili globali lasciate non inizializzate (o inizializzate a zero). Le variabili qui sono automaticamente inizializzate a zero, prevenendo quindi l'aggiunta di zeri inutili al binario.
|
||||
- **`.rodata`**: Variabili globali costanti (sezione di sola lettura).
|
||||
- **`.tdata`** e **`.tbss`**: Come .data e .bss quando si utilizzano variabili locali al thread (`__thread_local` in C++ o `__thread` in C).
|
||||
- **`.tdata`** e **`.tbss`**: Come .data e .bss quando si utilizzano variabili locali per thread (`__thread_local` in C++ o `__thread` in C).
|
||||
- **`.dynamic`**: Vedi sotto.
|
||||
|
||||
## Simboli
|
||||
|
||||
I simboli sono una posizione nominata nel programma che potrebbe essere una funzione, un oggetto di dati globale, variabili locali al thread...
|
||||
I simboli sono una posizione nominata nel programma che potrebbe essere una funzione, un oggetto di dati globale, variabili locali per thread...
|
||||
```
|
||||
readelf -s lnstat
|
||||
|
||||
@ -185,15 +201,19 @@ Num: Value Size Type Bind Vis Ndx Name
|
||||
12: 0000000000000000 0 FUNC GLOBAL DEFAULT UND putc@GLIBC_2.17 (2)
|
||||
[...]
|
||||
```
|
||||
Ogni voce simbolo contiene:
|
||||
Ogni voce di simbolo contiene:
|
||||
|
||||
- **Nome**
|
||||
- **Attributi di binding** (debole, locale o globale): Un simbolo locale può essere accessibile solo dal programma stesso, mentre i simboli globali sono condivisi al di fuori del programma. Un oggetto debole è, ad esempio, una funzione che può essere sovrascritta da un'altra.
|
||||
- **Tipo**: NOTYPE (nessun tipo specificato), OBJECT (variabile di dati globale), FUNC (funzione), SECTION (sezione), FILE (file di codice sorgente per debugger), TLS (variabile locale al thread), GNU_IFUNC (funzione indiretta per rilocazione)
|
||||
- **Indice della sezione** in cui si trova
|
||||
- **Sezione** indice in cui si trova
|
||||
- **Valore** (indirizzo in memoria)
|
||||
- **Dimensione**
|
||||
|
||||
#### Versionamento dei simboli GNU (dynsym/dynstr/gnu.version)
|
||||
|
||||
La moderna glibc utilizza versioni di simbolo. Vedrai voci in `.gnu.version` e `.gnu.version_r` e nomi di simboli come `strlen@GLIBC_2.17`. Il linker dinamico può richiedere una versione specifica quando risolve un simbolo. Quando si creano rilocazioni manuali (ad es. ret2dlresolve) è necessario fornire l'indice di versione corretto, altrimenti la risoluzione fallisce.
|
||||
|
||||
## Sezione Dinamica
|
||||
```
|
||||
readelf -d lnstat
|
||||
@ -231,9 +251,26 @@ Tag Type Name/Value
|
||||
```
|
||||
La directory NEEDED indica che il programma **deve caricare la libreria menzionata** per continuare. La directory NEEDED si completa una volta che la **libreria condivisa è completamente operativa e pronta** per l'uso.
|
||||
|
||||
## Relocations
|
||||
### Ordine di ricerca del caricatore dinamico (RPATH/RUNPATH, $ORIGIN)
|
||||
|
||||
Il loader deve anche rilocare le dipendenze dopo averle caricate. Queste rilocazioni sono indicate nella tabella di rilocazione nei formati REL o RELA e il numero di rilocazioni è fornito nelle sezioni dinamiche RELSZ o RELASZ.
|
||||
Le voci `DT_RPATH` (deprecato) e/o `DT_RUNPATH` influenzano dove il caricatore dinamico cerca le dipendenze. Ordine approssimativo:
|
||||
|
||||
- `LD_LIBRARY_PATH` (ignorato per programmi setuid/sgid o altrimenti "sicuri")
|
||||
- `DT_RPATH` (solo se `DT_RUNPATH` assente)
|
||||
- `DT_RUNPATH`
|
||||
- `ld.so.cache`
|
||||
- directory predefinite come `/lib64`, `/usr/lib64`, ecc.
|
||||
|
||||
`$ORIGIN` può essere utilizzato all'interno di RPATH/RUNPATH per riferirsi alla directory dell'oggetto principale. Dal punto di vista di un attaccante, questo è importante quando controlli il layout del filesystem o l'ambiente. Per i binari rinforzati (AT_SECURE) la maggior parte delle variabili ambientali sono ignorate dal caricatore.
|
||||
|
||||
- Ispeziona con: `readelf -d ./bin | egrep -i 'r(path|unpath)'`
|
||||
- Test rapido: `LD_DEBUG=libs ./bin 2>&1 | grep -i find` (mostra le decisioni sul percorso di ricerca)
|
||||
|
||||
> Suggerimento per l'escamotage: Preferisci abusare di RUNPATH scrivibili o percorsi relativi a `$ORIGIN` mal configurati di tua proprietà. LD_PRELOAD/LD_AUDIT sono ignorati nei contesti di esecuzione sicura (setuid).
|
||||
|
||||
## Rilocazioni
|
||||
|
||||
Il caricatore deve anche rilocare le dipendenze dopo averle caricate. Queste rilocazioni sono indicate nella tabella di rilocazione nei formati REL o RELA e il numero di rilocazioni è fornito nelle sezioni dinamiche RELSZ o 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
|
||||
@ -310,7 +346,7 @@ Offset Info Type Sym. Value Sym. Name + Addend
|
||||
|
||||
Se il **programma è caricato in un luogo diverso** dall'indirizzo preferito (di solito 0x400000) perché l'indirizzo è già utilizzato o a causa di **ASLR** o per qualsiasi altro motivo, una relocazione statica **corregge i puntatori** che avevano valori che si aspettavano che il binario fosse caricato nell'indirizzo preferito.
|
||||
|
||||
Ad esempio, qualsiasi sezione di tipo `R_AARCH64_RELATIV` dovrebbe avere modificato l'indirizzo al bias di relocazione più il valore addend.
|
||||
Ad esempio, qualsiasi sezione di tipo `R_AARCH64_RELATIV` dovrebbe avere modificato l'indirizzo al bias di relocazione più il valore additivo.
|
||||
|
||||
### Dynamic Relocations and GOT
|
||||
|
||||
@ -320,11 +356,29 @@ La relocazione potrebbe anche fare riferimento a un simbolo esterno (come una fu
|
||||
|
||||
La sezione PLT consente di eseguire il lazy binding, il che significa che la risoluzione della posizione di una funzione verrà eseguita la prima volta che viene accesso.
|
||||
|
||||
Quindi, quando un programma chiama malloc, in realtà chiama la posizione corrispondente di `malloc` nel PLT (`malloc@plt`). La prima volta che viene chiamato risolve l'indirizzo di `malloc` e lo memorizza, quindi la prossima volta che viene chiamato `malloc`, quell'indirizzo viene utilizzato invece del codice PLT.
|
||||
Quindi, quando un programma chiama malloc, in realtà chiama la posizione corrispondente di `malloc` nel PLT (`malloc@plt`). La prima volta che viene chiamato, risolve l'indirizzo di `malloc` e lo memorizza, quindi la prossima volta che viene chiamato `malloc`, viene utilizzato quell'indirizzo invece del codice PLT.
|
||||
|
||||
#### Modern linking behaviors that impact exploitation
|
||||
|
||||
- `-z now` (Full RELRO) disabilita il lazy binding; le voci PLT esistono ancora ma GOT/PLT è mappato in sola lettura, quindi tecniche come **GOT overwrite** e **ret2dlresolve** non funzioneranno contro il binario principale (le librerie possono ancora essere parzialmente RELRO). Vedi:
|
||||
|
||||
{{#ref}}
|
||||
../common-binary-protections-and-bypasses/relro.md
|
||||
{{#endref}}
|
||||
|
||||
- `-fno-plt` fa sì che il compilatore chiami funzioni esterne attraverso l'**entry GOT direttamente** invece di passare attraverso il PLT stub. Vedrai sequenze di chiamate come `mov reg, [got]; call reg` invece di `call func@plt`. Questo riduce l'abuso di esecuzione speculativa e cambia leggermente la ricerca di gadget ROP attorno agli stub PLT.
|
||||
|
||||
- PIE vs static-PIE: PIE (ET_DYN con `INTERP`) necessita del loader dinamico e supporta la consueta meccanica PLT/GOT. Static-PIE (ET_DYN senza `INTERP`) ha relocazioni applicate dal kernel loader e nessun `ld.so`; aspettati nessuna risoluzione PLT a runtime.
|
||||
|
||||
> Se GOT/PLT non è un'opzione, pivotare su altri puntatori di codice scrivibili o utilizzare ROP/SROP classico in libc.
|
||||
|
||||
{{#ref}}
|
||||
../arbitrary-write-2-exec/aw2exec-got-plt.md
|
||||
{{#endref}}
|
||||
|
||||
## Program Initialization
|
||||
|
||||
Dopo che il programma è stato caricato, è tempo che venga eseguito. Tuttavia, il primo codice che viene eseguito **non è sempre la funzione `main`**. Questo perché, ad esempio, in C++ se una **variabile globale è un oggetto di una classe**, questo oggetto deve essere **inizializzato** **prima** che main venga eseguito, come in:
|
||||
Dopo che il programma è stato caricato, è tempo di farlo funzionare. Tuttavia, il primo codice che viene eseguito **non è sempre la funzione `main`**. Questo perché, ad esempio, in C++ se una **variabile globale è un oggetto di una classe**, questo oggetto deve essere **inizializzato** **prima** che main venga eseguito, come in:
|
||||
```cpp
|
||||
#include <stdio.h>
|
||||
// g++ autoinit.cpp -o autoinit
|
||||
@ -345,7 +399,7 @@ printf("Main\n");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
Nota che queste variabili globali si trovano in `.data` o `.bss`, ma nelle liste `__CTOR_LIST__` e `__DTOR_LIST__` gli oggetti da inizializzare e distruggere sono memorizzati per tenerne traccia.
|
||||
Nota che queste variabili globali si trovano in `.data` o `.bss`, ma nelle liste `__CTOR_LIST__` e `__DTOR_LIST__` gli oggetti da inizializzare e distruggere sono memorizzati in ordine per tenerne traccia.
|
||||
|
||||
Dal codice C è possibile ottenere lo stesso risultato utilizzando le estensioni GNU:
|
||||
```c
|
||||
@ -354,29 +408,66 @@ __attributte__((destructor)) //Add to the destructor list
|
||||
```
|
||||
Dal punto di vista di un compilatore, per eseguire queste azioni prima e dopo l'esecuzione della funzione `main`, è possibile creare una funzione `init` e una funzione `fini` che sarebbero referenziate nella sezione dinamica come **`INIT`** e **`FIN`**. e sono collocate nelle sezioni `init` e `fini` dell'ELF.
|
||||
|
||||
L'altra opzione, come menzionato, è riferirsi alle liste **`__CTOR_LIST__`** e **`__DTOR_LIST__`** nelle voci **`INIT_ARRAY`** e **`FINI_ARRAY`** nella sezione dinamica e la lunghezza di queste è indicata da **`INIT_ARRAYSZ`** e **`FINI_ARRAYSZ`**. Ogni voce è un puntatore a funzione che verrà chiamato senza argomenti.
|
||||
L'altra opzione, come menzionato, è fare riferimento alle liste **`__CTOR_LIST__`** e **`__DTOR_LIST__`** nelle voci **`INIT_ARRAY`** e **`FINI_ARRAY`** nella sezione dinamica e la lunghezza di queste è indicata da **`INIT_ARRAYSZ`** e **`FINI_ARRAYSZ`**. Ogni voce è un puntatore a funzione che verrà chiamato senza argomenti.
|
||||
|
||||
Inoltre, è anche possibile avere un **`PREINIT_ARRAY`** con **puntatori** che verranno eseguiti **prima** dei puntatori **`INIT_ARRAY`**.
|
||||
|
||||
#### Nota di sfruttamento
|
||||
|
||||
- Sotto Partial RELRO, questi array vivono in pagine che sono ancora scrivibili prima che `ld.so` cambi `PT_GNU_RELRO` in sola lettura. Se ottieni una scrittura arbitraria abbastanza presto o puoi mirare agli array scrivibili di una libreria, puoi dirottare il flusso di controllo sovrascrivendo un'entrata con una funzione a tua scelta. Sotto Full RELRO sono di sola lettura a runtime.
|
||||
|
||||
- Per l'abuso del lazy binding del linker dinamico per risolvere simboli arbitrari a runtime, vedere la pagina dedicata:
|
||||
|
||||
{{#ref}}
|
||||
../rop-return-oriented-programing/ret2dlresolve.md
|
||||
{{#endref}}
|
||||
|
||||
### Ordine di Inizializzazione
|
||||
|
||||
1. Il programma viene caricato in memoria, le variabili globali statiche vengono inizializzate in **`.data`** e quelle non inizializzate vengono azzerate in **`.bss`**.
|
||||
2. Tutte le **dipendenze** per il programma o le librerie vengono **inizializzate** e il **collegamento dinamico** viene eseguito.
|
||||
3. Le funzioni **`PREINIT_ARRAY`** vengono eseguite.
|
||||
4. Le funzioni **`INIT_ARRAY`** vengono eseguite.
|
||||
5. Se c'è una voce **`INIT`**, viene chiamata.
|
||||
6. Se è una libreria, dlopen termina qui, se è un programma, è il momento di chiamare il **vero punto di ingresso** (funzione `main`).
|
||||
5. Se c'è un'entrata **`INIT`**, viene chiamata.
|
||||
6. Se è una libreria, dlopen termina qui, se è un programma, è tempo di chiamare il **punto di ingresso reale** (funzione `main`).
|
||||
|
||||
## Memoria Locale per Thread (TLS)
|
||||
## Thread-Local Storage (TLS)
|
||||
|
||||
Sono definiti utilizzando la parola chiave **`__thread_local`** in C++ o l'estensione GNU **`__thread`**.
|
||||
|
||||
Ogni thread manterrà una posizione unica per questa variabile, quindi solo il thread può accedere alla sua variabile.
|
||||
Ogni thread manterrà una posizione unica per questa variabile in modo che solo il thread possa accedere alla sua variabile.
|
||||
|
||||
Quando questo viene utilizzato, le sezioni **`.tdata`** e **`.tbss`** vengono utilizzate nell'ELF. Che sono simili a `.data` (inizializzato) e `.bss` (non inizializzato) ma per TLS.
|
||||
|
||||
Ogni variabile avrà un'entrata nell'intestazione TLS che specifica la dimensione e l'offset TLS, che è l'offset che utilizzerà nell'area di dati locale del thread.
|
||||
Ogni variabile avrà un'entrata nell'intestazione TLS che specifica la dimensione e l'offset TLS, che è l'offset che utilizzerà nell'area di dati locali del thread.
|
||||
|
||||
Il `__TLS_MODULE_BASE` è un simbolo utilizzato per riferirsi all'indirizzo base della memoria locale per thread e punta all'area in memoria che contiene tutti i dati locali per thread di un modulo.
|
||||
Il `__TLS_MODULE_BASE` è un simbolo utilizzato per riferirsi all'indirizzo base della memoria locale del thread e punta all'area in memoria che contiene tutti i dati locali del thread di un modulo.
|
||||
|
||||
## Auxiliary Vector (auxv) e vDSO
|
||||
|
||||
Il kernel Linux passa un vettore ausiliario ai processi contenente indirizzi e flag utili per il runtime:
|
||||
|
||||
- `AT_RANDOM`: punta a 16 byte casuali utilizzati da glibc per il canarino dello stack e altri semi PRNG.
|
||||
- `AT_SYSINFO_EHDR`: indirizzo base della mappatura vDSO (utile per trovare syscalls e gadget `__kernel_*`).
|
||||
- `AT_EXECFN`, `AT_BASE`, `AT_PAGESZ`, ecc.
|
||||
|
||||
Come attaccante, se puoi leggere la memoria o i file sotto `/proc`, puoi spesso rivelare questi senza una infoleak nel processo target:
|
||||
```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));
|
||||
}
|
||||
```
|
||||
Leaking `AT_RANDOM` ti dà il valore del canary se riesci a dereferenziare quel puntatore; `AT_SYSINFO_EHDR` ti fornisce una base vDSO da esplorare per gadget o per chiamare syscalls veloci direttamente.
|
||||
|
||||
## References
|
||||
|
||||
- ld.so(8) – Ordine di ricerca del Dynamic Loader, RPATH/RUNPATH, regole di esecuzione sicura (AT_SECURE): https://man7.org/linux/man-pages/man8/ld.so.8.html
|
||||
- getauxval(3) – Vettore ausiliario e costanti AT_*: https://man7.org/linux/man-pages/man3/getauxval.3.html
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user