Leaking libc address with ROP
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Trova l'offset di overflow
Trova il gadget POP_RDI
, i gadget PUTS_PLT
e MAIN
Usa i gadget precedenti per leak l'indirizzo di memoria di puts o di un'altra funzione libc e trova la versione di libc (scaricalo)
Con la libreria, calcola il ROP e sfruttalo
This tutorial is going to exploit the code/binary proposed in this tutorial: https://tasteofsecurity.com/security/ret2libc-unknown-libc/ Another useful tutorials: https://made0x78.com/bseries-ret2libc/, https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html
Filename: vuln.c
Scarica l'exploit e posizionalo nella stessa directory del binario vulnerabile e fornisci i dati necessari allo script:
Leaking libc - templateIl template ha bisogno di un offset prima di continuare con l'exploit. Se ne viene fornito uno, eseguirà il codice necessario per trovarlo (per impostazione predefinita OFFSET = ""
):
Esegui python template.py
si aprirà una console GDB con il programma che si è bloccato. All'interno di quella console GDB esegui x/wx $rsp
per ottenere i byte che stavano per sovrascrivere il RIP. Infine, ottieni il offset utilizzando una console python:
Dopo aver trovato l'offset (in questo caso 40), cambia la variabile OFFSET all'interno del template utilizzando quel valore.
OFFSET = "A" * 40
Un altro modo sarebbe usare: pattern create 1000
-- esegui fino a ret -- pattern seach $rsp
da GEF.
Ora dobbiamo trovare gadget ROP all'interno del binario. Questi gadget ROP saranno utili per chiamare puts
per trovare la libc in uso, e successivamente per lanciare l'exploit finale.
Il PUTS_PLT
è necessario per chiamare la funzione puts.
Il MAIN_PLT
è necessario per chiamare di nuovo la funzione main dopo un'interazione per sfruttare nuovamente il overflow (giri infiniti di sfruttamento). Viene utilizzato alla fine di ogni ROP per richiamare nuovamente il programma.
Il POP_RDI è necessario per passare un parametro alla funzione chiamata.
In questo passaggio non è necessario eseguire nulla poiché tutto sarà trovato da pwntools durante l'esecuzione.
Ora è il momento di scoprire quale versione della libreria libc viene utilizzata. Per farlo, andremo a leak l'indirizzo in memoria della funzione puts
e poi andremo a cercare in quale versione della libreria si trova la versione di puts in quell'indirizzo.
Per fare ciò, la linea più importante del codice eseguito è:
Questo invierà alcuni byte fino a quando sovrascrivere il RIP è possibile: OFFSET
.
Poi, imposterà l'indirizzo del gadget POP_RDI
in modo che il prossimo indirizzo (FUNC_GOT
) sarà salvato nel registro RDI. Questo perché vogliamo chiamare puts passandogli l'indirizzo di PUTS_GOT
poiché l'indirizzo in memoria della funzione puts è salvato nell'indirizzo puntato da PUTS_GOT
.
Dopo di che, verrà chiamato PUTS_PLT
(con PUTS_GOT
all'interno del RDI) in modo che puts legga il contenuto all'interno di PUTS_GOT
(l'indirizzo della funzione puts in memoria) e lo stampi.
Infine, la funzione main viene chiamata di nuovo così possiamo sfruttare di nuovo il buffer overflow.
In questo modo abbiamo ingannato la funzione puts per stampare l'indirizzo in memoria della funzione puts (che si trova all'interno della libreria libc). Ora che abbiamo quell'indirizzo possiamo cercare quale versione di libc viene utilizzata.
Poiché stiamo sfruttando un binario locale, non è necessario scoprire quale versione di libc viene utilizzata (basta trovare la libreria in /lib/x86_64-linux-gnu/libc.so.6
).
Ma, in un caso di exploit remoto, spiegherò qui come puoi trovarlo:
Puoi cercare quale libreria viene utilizzata nella pagina web: https://libc.blukat.me/ Ti permetterà anche di scaricare la versione di libc scoperta.
Puoi anche fare:
$ git clone https://github.com/niklasb/libc-database.git
$ cd libc-database
$ ./get
Questo richiederà del tempo, sii paziente. Per farlo funzionare abbiamo bisogno di:
Nome del simbolo libc: puts
Indirizzo libc leakato: 0x7ff629878690
Possiamo capire quale libc è molto probabilmente utilizzata.
Otteniamo 2 corrispondenze (dovresti provare la seconda se la prima non funziona). Scarica la prima:
Copia la libc da libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so
nella nostra directory di lavoro.
A questo punto dovremmo conoscere la libreria libc utilizzata. Poiché stiamo sfruttando un binario locale, userò solo: /lib/x86_64-linux-gnu/libc.so.6
Quindi, all'inizio di template.py
, cambia la variabile libc in: libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Imposta il percorso della libreria quando lo conosci
Fornendo il percorso alla libreria libc, il resto dell'exploit verrà calcolato automaticamente.
All'interno della funzione get_addr
, verrà calcolato il l'indirizzo base di libc:
Nota che l'indirizzo finale della base libc deve terminare in 00. Se non è il tuo caso, potresti aver leakato una libreria errata.
Quindi, l'indirizzo della funzione system
e l'indirizzo della stringa "/bin/sh" verranno calcolati dalla base address della libc e forniti alla libreria libc.
Infine, l'exploit per l'esecuzione di /bin/sh verrà preparato e inviato:
Let's explain this final ROP.
L'ultimo ROP (rop1
) ha terminato chiamando di nuovo la funzione main, quindi possiamo sfruttare di nuovo il overflow (ecco perché l'OFFSET
è qui di nuovo). Poi, vogliamo chiamare POP_RDI
puntando all'indirizzo di "/bin/sh" (BINSH
) e chiamare la funzione system (SYSTEM
) perché l'indirizzo di "/bin/sh" sarà passato come parametro.
Infine, l'indirizzo della funzione exit è chiamato in modo che il processo esca in modo ordinato e non venga generato alcun avviso.
In questo modo l'exploit eseguirà una _/bin/sh_** shell.**
Potresti anche usare ONE_GADGET per ottenere una shell invece di usare system e "/bin/sh". ONE_GADGET troverà all'interno della libreria libc qualche modo per ottenere una shell usando solo un indirizzo ROP.
Tuttavia, normalmente ci sono alcune restrizioni, le più comuni e facili da evitare sono come [rsp+0x30] == NULL
. Poiché controlli i valori all'interno del RSP, devi solo inviare alcuni valori NULL in più in modo che la restrizione venga evitata.
Puoi trovare un modello per sfruttare questa vulnerabilità qui:
Leaking libc - templateSe il simbolo "main" non esiste. Allora puoi trovare dove si trova il codice principale:
e impostare l'indirizzo manualmente:
Se il binario non utilizza Puts, dovresti controllare se sta usando
sh: 1: %s%s%s%s%s%s%s%s: non trovato
Se trovi questo errore dopo aver creato tutti gli exploit: sh: 1: %s%s%s%s%s%s%s%s: non trovato
Prova a sottrarre 64 byte all'indirizzo di "/bin/sh":
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)