Volver a la página principal
lunes 4 noviembre 2024
8

DDexec y EverythingExec para Ejecución en Memoria

En los sistemas Linux, para ejecutar un programa es necesario que el archivo correspondiente esté disponible en algún punto del sistema de archivos. Esto permite que el sistema detecte y controle fácilmente qué se está ejecutando, ya que cualquier programa necesita tener un path o ruta específica accesible, ya sea en disco o en memoria (como en tmpfs o memfd). Esta configuración facilita la tarea de monitorización y restricción de actividades sospechosas, ya que, por ejemplo, es posible bloquear a usuarios no privilegiados de crear archivos ejecutables en lugares no autorizados del sistema.

Pero, ¿qué pasa si podemos iniciar un proceso sin necesidad de un archivo específico? Aquí es donde entra en juego DDexec, una herramienta que permite secuestrar procesos existentes para reemplazarlos con otros programas, burlando así varias protecciones comunes.

¿Qué es DDexec y Cómo Funciona?

DDexec es una herramienta que permite ejecutar programas mediante la manipulación directa de la memoria de un proceso. Esta técnica permite evitar las limitaciones habituales de permisos de ejecución, listados de control de nombres de archivos y whitelisting de hashes, entre otros. La clave de DDexec radica en la capacidad de sobreescribir procesos ya existentes en memoria y hacer que estos ejecuten otros programas.

Requisitos para Utilizar DDexec

Para que la técnica funcione, es necesario que ciertas herramientas básicas estén disponibles en el sistema objetivo, aunque la mayoría de estos comandos suelen encontrarse en cualquier distribución de Linux:

  • dd
  • Intérpretes de shell como bash, zsh, ash (en busybox)
  • head, tail, cut, grep, od, readlink, wc, tr, base64

Estas herramientas son fundamentales para manejar la memoria del sistema y realizar las modificaciones necesarias en los procesos activos.

La Técnica: Modificación de Memoria para Ejecutar Procesos

La técnica de DDexec se basa en la modificación directa de la memoria de un proceso activo. Esto se puede realizar de dos formas:

1. Syscall ptrace(): Utiliza el sistema de llamadas ptrace() (también usado por gdb) para controlar y modificar el comportamiento de un proceso. Este método requiere que el atacante tenga acceso para ejecutar syscalls o que gdb esté disponible en el sistema.

2. Escritura en /proc/$pid/mem: Este método es más interesante, ya que permite modificar directamente el espacio de direcciones de un proceso a través del archivo /proc/$pid/mem. Este archivo mapea todo el espacio de direcciones de un proceso, lo que permite leer o escribir en cualquier posición de memoria accesible.

Desafíos a Superar

Para ejecutar esta técnica, es necesario superar varios obstáculos:

  • Permisos: Solo el usuario root o el propietario del proceso puede modificar la memoria del mismo.
  • ASLR (Address Space Layout Randomization): La aleatorización de direcciones hace más difícil predecir las ubicaciones de memoria.
  • Errores de E/S: Si se intenta leer o escribir en una dirección que no está mapeada en el espacio de direcciones del proceso, se producirá un error de entrada/salida.

Soluciones a los Problemas de Implementación

Para superar estos problemas, existen soluciones que permiten que esta técnica funcione de manera relativamente sencilla:

  • Creación de Descriptores de Archivo: La mayoría de los intérpretes de shell permiten crear descriptores de archivo (fd) que los procesos hijos pueden heredar. Esto permite crear un fd que apunte a la memoria del proceso con permisos de escritura.
  • Mapeo de Direcciones: Aunque ASLR aleatoriza el espacio de direcciones, es posible verificar los archivos de mapeo de /proc para obtener información sobre la disposición de las direcciones del proceso.
  • Uso de lseek(): Para realizar desplazamientos en archivos desde la shell, se utiliza el comando dd, que permite realizar movimientos precisos en el archivo /proc/$pid/mem.

Pasos para Ejecutar un Proceso con DDexec

A continuación, se presentan los pasos principales para ejecutar un proceso mediante la técnica de DDexec:

1. Análisis del Binario y el Loader: Primero se debe analizar el binario que se quiere ejecutar para identificar los mapeos necesarios. Después, se crea un shellcode que replica los pasos que el sistema realiza con cada llamada execve().

2. Creación de Mapeos y Lectura del Binario: Se crean los mapeos de memoria necesarios, se cargan los binarios en ellos y se configuran los permisos correspondientes.

3. Inicialización de la Pila y el Vector Auxiliar: Se configura la pila con los argumentos necesarios y se coloca el vector auxiliar requerido por el cargador.

4. Sobreescritura de Memoria con Shellcode: Finalmente, se obtiene del archivo syscall la dirección a la que regresará el proceso después de la syscall y se sobreescribe ese lugar con el shellcode. Desde aquí, se pasa el programa deseado al stdin del proceso, permitiendo que el cargador ejecute el programa.

Alternativas a DD: EverythingExec

EverythingExec introduce una serie de alternativas al uso de dd para la manipulación de memoria. Por ejemplo, tail es una opción popular para realizar lseek() a través del archivo de memoria /proc/$pid/mem. Las herramientas alternativas incluyen:

  • tail
  • hexdump
  • cmp
  • xxd

Esto permite que el usuario elija entre diferentes herramientas para navegar en la memoria del proceso. Además, se puede configurar la variable SEEKER para seleccionar el buscador preferido, y SEEKER_ARGS para definir argumentos específicos según el programa que se quiera utilizar.

SEEKER=cmp bash ddexec.sh ls -l <<< $(base64 -w0 /bin/ls)

Ejemplo con xxd

En este ejemplo, se configura xxd como el buscador, especificando los argumentos necesarios para desplazarse a la posición correcta en memoria.

SEEKER=xxd SEEKER_ARGS='-s $offset' zsh ddexec.sh ls -l <<< $(base64 -w0 /bin/ls)

Conclusión

La técnica de DDexec y sus variantes, como EverythingExec, representan un avance notable en las capacidades de evasión en sistemas Linux, permitiendo a los atacantes reemplazar procesos en memoria sin necesidad de crear nuevos archivos ejecutables. Esto evade muchas de las técnicas de protección convencionales como los permisos de ejecución y los controles de integridad. Aunque es una técnica avanzada y compleja, conocer su funcionamiento y limitaciones es fundamental para aquellos en el campo de la seguridad que desean proteger sistemas críticos.

Compartir:
Creado por:
Author photo

Jorge García

Fullstack developer