Continúo poniendo las soluciones de un sitio que he encontrado para aprender ROP, ‘Return Oriented Programming’ (en español, Programación Orientada al Retorno), a través de una serie de desafíos diseñados para enseñar diversas técnicas.
Como siempre utilizo la versión de 64 bits del desafío.
En este post la solución al reto que lleva por título "split", y que, en mi opinión, presenta un nivel de dificultad medio (★★★☆☆).
- Enunciado:
- Solución:
2.- Compruebo los mecanismos de seguridad del binario utilizando ‘checksec’ y veo que ‘NX’ está habilitado, lo que significa que la pila es no ejecutable:
3.- Decompilo el binario usando ‘Ghidra’ y veo que en la función main() se realiza una llamada a la función pwnme():Al contrario que en el reto anterior, "ret2win", no veo que el binario tenga una función que muestre la flag, sin embargo veo que la cadena “/bin/cat flag.txt” se encuentra en la dirección ‘0x601060’:
Ademas, veo que la función usefulFunction() pasa “/bin/ls” como argumento a system(), y puedo hacer que en su lugar pase “/bin/cat flag.txt” y muestre la flag:
4.- El plan de ataque consiste en sobrescribir la dirección de retorno de la función pwnme() con la de inicio de una cadena ROP (en inglés, 'ROP chain') que ejecute system() con “/bin/cat flag.txt” como parámetro, lo que mostrará la flag.
5.- Creo el 'exploit' mediante un pequeño 'script' en python y lo ejecuto:
Antes de crear el 'exploit', conviene recordar que. al contrario que en los binarios de 32 bits en los que los argumentos se pasan a las funciones a través de la pila, en los de 64 bits los 6 primeros argumentos se pasan a las funciones a través de registros. En concreto, el primer argumento se pasa a través del registro RDI.
Port tanto, para construir la cadena ROP necesito:
a) La cadena “/bin/cat flag.txt”. Ya he visto antes que esta cadena se encuentra en la dirección ‘0x601060’, pero dejaré que el 'exploit' obtenga esa dirección automáticamente por mí.
b) Un 'gadget' que incluya la dirección de la cadena anterior en el registro RDI. Para buscar un 'gadget' que nos sirva para ello utilizaré la herramienta 'ROPgadget'.
c) La dirección de system(). Aunque se puede obtener fácilmente desensamblando el binario, por ejemplo utilizando 'gdb', también dejaré que el 'exploit' lo haga de forma automática por mí.
Para localizar en el propio binario un 'gadget' que incluya la dirección de la cadena “/bin/cat flag.txt”, que introduciré en la pila, en el registro RDI actúo de la siguiente manera y veo que en la dirección '0x00000000004007c3' existe un 'gadget' que nos puede servir perfectamente para ello:
A partir de aquí, creo un pequeño 'script' en python y lo ejecuto:
from pwn import *
# Indicar a pwntools el binario objetivo
elf = context.binary = ELF('split')
# Relleno hasta la dirección de retorno de pwnme()
offset_padding = b'A'*40
# Dirección del gadget: pop rdi ; ret
info('0x4007c3 pop rdi; ret ')
gadget = p64(0x00000000004007c3)
# Dirección de la cadena "/bin/cat flag.txt"
info('%#x /bin/cat flag.txt', elf.symbols.usefulString)
bin_cat_flag = p64(elf.symbols.usefulString)
# Dirección de system()
info('%#x system', elf.symbols.system)
system = p64(elf.symbols.system)
# Enviar
p = process(elf.path)
payload = offset_padding+gadget+bin_cat_flag+system
p.sendline(payload)
# Recibir e imprimir
print(p.recvall())
Comentarios
Publicar un comentario