flagPIE TIME PicoCTF (Easy)

Contexto de la maquina

Trayectoria PIE TIME

Descripción

PIE TIME es un reto de ingeniería inversa y explotación binaria centrado en la manipulación del flujo de ejecución de un programa compilado con PIE (Position Independent Executable). El binario permite al usuario introducir una dirección de memoria arbitraria que posteriormente es ejecutada como puntero a función, lo que conduce a una ejecución de código arbitraria.

Objetivo del reto

Forzar el flujo de ejecución del programa para saltar a una función interna (win()), la cual imprime el contenido del archivo flag.txt.

Tipo de reto

  • Binary Exploitation

  • Ingeniería inversa

  • Control Flow Hijacking

  • PIE bypass lógico (sin ASLR brute-force)

Habilidades y técnicas evaluadas

  • Análisis de código fuente en C

  • Comprensión de punteros a funciones

  • Control Flow Hijacking

  • Cálculo de offsets en binarios PIE

  • Uso de gdb

  • Explotación remota vía netcat

Análisis de vulnerabilidades

Despliegue del CTF

En la propia pagina buscaremos el CTF, dentro veremos un boton llamado Launch Instance, una ves desplegado nos aparecera here donde se encuentra el dominio junto con el puerto asociado al mismo.

El objetivo de estos CTFs es encontrar la flag final.

Ingeniería Inversa

El reto nos proporciona directamente el binario y su código fuente, los cuales podemos descargar mediante wget una vez generada la URL del desafío.

Una vez descargados los archivos, procedemos a analizar el código fuente vuln.c.

Análisis del código:

  1. main():

    • Registra un manejador para SIGSEGV (segmentation fault).

    • Muestra la dirección de memoria de main (esto es una pista importante).

    • Pide al usuario que introduzca una dirección hexadecimal.

    • Convierte esa dirección en un puntero a función y la ejecuta.

  2. win():

    • Función que abre y lee flag.txt.

    • Nunca es llamada directamente por el flujo normal del programa.

  3. segfault_handler():

    • Solo imprime un mensaje y sale si ocurre un segfault.

Vulnerabilidad:

El programa permite al usuario introducir una dirección arbitraria que será ejecutada sin ningún tipo de validación:

Esto implica que cualquier dirección válida dentro del binario puede ser ejecutada, permitiendo redirigir el flujo de ejecución hacia funciones internas como win().

Control Flow Hijack (Binary)

Dado que el binario está compilado con PIE, las direcciones de memoria cambian en cada ejecución. Sin embargo, el offset entre funciones permanece constante.

El propio programa nos proporciona la dirección de main(), por lo que el siguiente paso es calcular el offset entre main y win.

Abrimos el binario con gdb:

Dentro de gdb, imprimimos las direcciones de ambas funciones:

Resultado:

Calculamos el offset:

Creamos un pequeño one-liner en Python para calcular dinámicamente la dirección de win() a partir de la dirección filtrada de main():

Resultado:

Para validar que el cálculo del offset es correcto, realizamos una comprobación rápida en entorno local. Dado que el binario está compilado con PIE, la dirección base cambia en cada ejecución, por lo que el cálculo debe hacerse en tiempo de ejecución. La idea es ejecutar el binario, capturar la dirección de main() que se muestra, y en una segunda terminal calcular dinámicamente la dirección de win() aplicando el offset previamente obtenido.

Comprobación en local

Antes de proceder con la explotación, creamos un archivo flag.txt para verificar que la ejecución de win() funciona correctamente en local.

Con esto preparado, procedemos a ejecutar el binario vulnerable:

Resultado:

En otra terminal, utilizamos el one-liner en Python para calcular la dirección de win() a partir de la dirección filtrada de main():

Resultado:

Una vez obtenida la dirección correcta (0x56032f4ce2a7), la introducimos en el programa:

Esto confirma que la explotación funciona correctamente en entorno local y que el cálculo del offset es válido. Sin embargo, este paso solo sirve como prueba, ya que el objetivo final es explotar el servicio remoto proporcionado por el reto.

Explotación binario del reto

El propio desafío nos indica lo siguiente:

Al conectarnos mediante netcat, el binario remoto se ejecuta automáticamente, por lo que repetimos el mismo procedimiento para obtener la flag real.

Arbitrary Code Execution via Function Pointer Overwrite

Nos conectamos al servicio remoto:

Resultado:

De nuevo, calculamos dinámicamente la dirección de win() utilizando el mismo one-liner:

Resultado:

Introducimos la dirección calculada (0x5cabb53472a7) en el binario remoto:

Con esto confirmamos que la explotación funciona correctamente también en remoto y obtenemos la flag final.

flag.txt

Last updated