Date post: | 19-Jun-2015 |
Category: |
Technology |
Upload: | conferencias-fist |
View: | 187 times |
Download: | 0 times |
Evasión de técnicas forense(Shellcode ELF loader)
FIST BCN 2005
Albert Puigsech Galicia [email protected]én Jiménez García [email protected]
Introducción
Introducción
Sistema de explotación común:
Localización de maquina vulnerable
Generación de programa exploit
Utilización de shellcode especifica
Se inicia el proceso de post-explotación
Introducción
La shellcode es nuestra amiga:
Codigos pequeños y faciles de programar Se pueden adaptar a cualquier exploit Pueden incorporar tecnicas de antidetección Generalmente se ejecuta una shell via execve()
Pero nos puede trainicionar:
Imposibilidad de utilizar execve()!!
Introducción
Y si disponemos de execve()?
Ejecución de comandos y aplicaciones locales Descarga/compilación de programas Estamos muertos..
Que ha ocurrido?
for(;;) printf(“evidencias!!”);
Introducción
Para poder solucionar estos problemas tendremos que optar por un sistema que nos facilite la ejecución de programas y al mismo tiempo genere el menor numero posible de evidencias:
Userland execve()
Userland execve
Userland execve
El procedimiento que permite la ejecución local de un programa sin utilizar la llamada al sistema ‘execve’ recibe el nombre de ‘userland execve’.
Mecanismo que simula de forma correcta y ordenada las tareas que realiza el núcleo:
Carga de las secciones necesarias del binario Inicialización del contexto de la pila. Salto al punto de entrada.
Userland execve
El uso de ‘userland execve’ nos soluciona los problemas planteados anteriormente.
No es necesario el uso de la syscall, por lo que no es preocupante que esté denegada.
La implementación es nuestra por lo que es posible cambiar el origen del ejecutable y obtenerlo de la red, en lugar del disco duro. Así podemos ejecutar una shell pese a que no exista en el disco.
La ejecución remota nos permitirá ejecutar herramientas que no estan en el host atacado sin alterar el disco.
Userland execve
Primera versión publica de userland execve: grugq
Problemas:
poco portable exceso de código inútil orientado a la ejecución local
Solución:
Shellcode ELF Loader
Shellcode ELF loader
Shellcode ELF loader
La shellcode ELF loader es una nueva y sofisticada técnica post-explotación basada en el ‘userland execve’.
Diseñada para ser utilizada en exploits
Reduce la generación de evidencias
Posibilita la ejecución en entornos ostiles
Es fácil de programar y utilizar
Diseño e implementación
SELF esta formado por tres elementos:
Lxobject (1)
Builder (2)
Jumper (3)
Cada uno realiza una tarea especifica dentro del proceso de post-explotación
Lxobject (1)
Es un objeto ejecutable y auto-cargable utilizado para sustituir por completo un proceso original por otro.
Es la parte más compleja e importante de todo el sistema.
Se construye por el ‘builder’ en el host del atacante.
Lxobject (1)
Un lxobject esta constituido por tres partes:
Binario ELF estático
Contexto inicial de la pila
Shellcode cargadora
Binario ELF estático (1.a)
Es el binario que queremos cargar y ejecutar en la maquina remota.
El sistema sólo funciona con binarios estáticos, se ha optado por ello por varios motivos.
Facilita el diseño y la implementación
No nos preocupamos por las librerías
Reduce la complejidad de SELF
El binario lo genera el atacante. (uso de armerías)
Contexto de pila (1.b)
Todo proceso dispone de una zona de memoria llamada pila o stack usada para varios cometidos.
Variables locales.
Control del flujo de ejecución.
Copias temporales de registros.
Parámetros pasados a la aplicación por el proceso padre.
Variables de entorno.
Contexto de pila (1.b)
La pila debe tener un contexto inicial para que el proceso funcione correctamente.
Para facilitar la portabilidad y estabilidad se ha optado por pre-construir el contexto de la pila en el host atacante e incluirlo en el lxobject como de un program header más se tratara.
No es necesario incluir los vectores auxiliares utilizados para tratar con binarios dinámicos.
Shellcode cargadora (1.c)
Se trata de la parte más importante y delicada del lxobject.
Es una shellcode que simula el userland execve()
Código pequeño y fácil de entender
Se puede adaptar a cada sistema/plataforma
No construye el contexto de pila
Builder (2)
Es la aplicación encargada de ensamblar las piezas que construyen el lxobject.
Builder (2)
bash ~$ ./builder <host> <port> <exec> <argv> <envp>
Su funcionamiento es sencillo:
argv, envp: Argumentos y variables de entorno pasadas al programa.
exec: Fichero binario ELF que queremos ejecutar
host, port: dirección y puerto de la máquina atacada donde el jumper está ejecutándose y esperando.
Builder (2)
Elemplo de ejecución:
bash ~$ ./builder 172.26.0.1 2002 nmap-static “-P0;-p;23;172.26.0.30” “PATH=/bin”
Proceso de construcción
Se crea una zona de memoria lo suficientemente grande para almacenar el fichero ejecutable estátido y se copia el binario.
Se limpian aquellos campos referentes a las secciones pues no seran usadas por nuestro binario.
elf_new = (void*)malloc(elf_new_size);
ehdr_new->e_shentsize = 0;
ehdr_new->e_shoff =0;
ehdr_new->e_shnum = 0;
ehdr_new->e_shstrndx = 0;
Proceso de construcción
Se introduce el shellcode ELF loader y se guarda su offset en el campo e_ident de la cabecera del ejecutable.
El lxobject está perfectamente ensamblado y listo para ser enviado.
memcpy(elf_new + elf_new_size - PG_SIZE + LOADER_CODESZ, loader, LOADER_CODESZ);ldr_ptr = (unsigned long *)&ehdr_new->e_ident[9];*ldr_ptr = elf_new_size - PG_SIZE + LOADER_CODESZ;
connect(sfd, (struct sockaddr *)&srv, sizeof(struct sockaddr));write(sfd, elf_new, elf_new_size);
Jumper (3)
El jumper es la shellcode que deberá ser usada por el exploit en el proceso de explotación.
Su misión es activar el lxobject y para ello debe realizar, por lo menos, las siguientes acciones:
Obtener el lxobject.
Almacenarlo en la memoria.
Activarlo saltando al loader.
Obtener el lxobject
El lxobjet puede obtenerse de muchas fuentes.
Disco duro
Socket de red
...
Es recomendable usar un socket de red para reducir el riesgo de dejar evidencias.
Almacenarlo en memoria
Es necesario almacenar el lxobject en la memoria de proceso. Se plantean entonces tres posibilidades.
Almacenarlo en la heap
Almacenarlo en la pila del proceso
Almacenarlo en una nueva zona de memoria (mmap).
Almacenarlo en la heap
Para almacenar el lxobject en la heap es necesario localizar la vaddr del proceso usando brk().
Ventajas:
Es sencillo de implementar.No suele haber restricciones de copia de datos.
Desventajas:
Se puede desmapear el propio lxobject durante el proceso de carga
Almacenarlo en el stack
Si se conoce la situación de la pila es posible almacenar ahí el lxobject.
Ventajas:
Es sencillo de implementar.No suele haber restricciones de copia de datos.
Desventajas:
Se puede desmapear el propio lxobject durante el proceso de carga.
Pueden existir restricciones de ejecución en la pila, es bastante común en sistemas hostiles.
Almacenar en una nueva zona
Es posible mapear (usando la llamada al sistema mmap) una nueva zona de memoria destinada almacenar el lxobject.
Ventajas:
No existen restricciones para la copia o ejecución de datos.
No existe peligro de que el lxobject se desmapee durante el proceso de carga.
Simple stack overflow + SELF = envio y ejecución de nmap
Demostración
Demostración
Simple stack overflow + SELF = envio y ejecución de elfsh
Referencias
[+] The Design and Implementation of ul_exec - the grugqhttp://securityfocus.com/archive/1/348638/2003-12-29/2004-01-04/0
[+] Remote Exec - the grugqhttp://www.phrack.org/show.php?p=62&a=8
[+] Advanced antiforensics - Ripe & Plufhttp://www.phrack.org/show.php?p=63&a=11
[+] Forensic Shell. FSH – Parki
[+] API Proxy – ilohttp://www.reversing.org
?
Alguna preguntita?
Muchas gracias
A los organizadores de FIST BARCELONA