11 julio 2013

Análisis Forense en Linux: Analizando la memoria con Volatility



Como indicaba en un post anterior, una de las cosas que conté en el curso de Análisis Forense que dictamos Conexión Inversa  y Securízame, cuya experiencia relató genialmente Pedro Sánchez, fue el análisis de la memoria de un sistema Linux. Para ello, primero adquiríamos una imagen de la misma, sin alterar la evidencia, con LIME, en RAW. 

Ahora es cuando toca, con ayuda del cincel y el martillo extraer una bonita estatua del bloque de piedra de la sucesión de 1s y 0s que es la memoria en crudo.

La ventaja de trabajar directamente contra la memoria es que es independiente de los rootkits que puede tener la máquina. Me explico: Si nos conectamos por consola al equipo comprometido y ejecutamos un ps o un netstat, si el sistema operativo ha pasado por hábiles manos, puede que veamos todo, excepto lo que el atacante quiera (ocultación de procesos o de sockets abiertos mediante rootkits). Sin embargo, si le extraemos el cerebro completo, es decir la memoria, leeremos directamente de éste lo que la máquina sabe, pero no nos quiere contar por interfaz de comandos.

Para ello, una de las mejores herramientas que hay es Volatility, que además de estar disponible tanto para Windows como para Linux, nos permite realizar montones de operaciones sobre la memoria adquirida. Entre otras, puedes extraer la tabla de conexiones, entradas ARP, ficheros abiertos, módulos cargados, procesos existentes, etc,…. que había en el momento del volcado de memoria.

Los parámetros que tenemos que pasar a Volatility son, obviamente, la imagen de memoria sobre la que vamos a trabajar, la operación a realizar (ver conexiones, procesos, etc,…) y un perfil que contiene el formato o la estructura de memoria del sistema operativo del que tenemos la imagen de la memoria. Y aquí,… con el clero hemos topado! Cuando hablamos de una imagen de memoria de un sistema operativo Windows, no hay ningún problema, puesto que Volatility trae incorporados los perfiles para Windows, dependiendo de la versión del mismo, el Service Pack aplicado, si es de 32 o 64 bits, etc,… Pero en el caso de Linux, donde cada distribución añade el kernel que quiere, lo compila con los módulos que quiere y versiona como quiere,… es imposible que Volatility disponga de todos ellos.

Así pues, nos tocará crear un perfil basado en la estructura de memoria del sistema objetivo. Para contaminar lo mínimo posible la evidencia (en este caso nada), aprovecharemos la máquina que hemos instalado anteriormente para crear el módulo de LIME, y que tiene el mismo kernel que la que queremos analizar, y crearemos el perfil Volatility aquí. Para ello:

1.-) Instalaremos paquetes con dependencias que sean necesarias. En el caso de CentOS, tuve que instalar kernel-devel, make, gcc, gcc-c++,….

2.-) Descargamos libdwarf, y compilamos a mano e instalamos “warfdump”

3.-) Descargamos Volatility for Linux con "svn checkout http://volatility.googlecode.com/svn/trunk/tools/linux volatility-linux-profile"

4.-) Al ejecutar un make, nos generará un fichero llamado "module.dwarf"

5.-) Para generar el perfil (que no es más que un zip), ejecutamos "zip module.dwarf /boot/System.map-`uname-r`", conteniendo las estructuras del kernel y los mapas de símbolos necesarios para entender correctamente la estructura de la ristra de 1s y 0s que hay en el fichero de la memoria.

6.-) En la máquina en la que vayamos a hacer el análisis forense y tengamos Volatility, copiaremos este fichero .zip a /usr/local/lib/python2.7/dist-packages/volatility/plugins/overlays/linux/

7.-) Ejecutamos "vol.py --info | grep -i linux" y nos aparecerá el perfil creado para Linux (y los que tuviéramos de antes) así como una lista de los comandos que podemos utilizar

Así ejecutaremos vol.py –f --profile y veremos qué secretos escondía la máquina en su memoria.
Por poner un ejemplo de la salida de uno de los comandos existentes, aquí podemos ver  la lista de sockets abiertos:

root@lawcaine:/tmp# vol.py -f mem.raw --profile CentOSx64 linux_netstat
Volatile Systems Volatility Framework 2.3_beta
UNIX /dev/log
TCP      0.0.0.0:22    0.0.0.0:0     LISTEN              sshd/940  
TCP      :::22    :::0     LISTEN              sshd/940  
TCP      0.0.0.0:0     0.0.0.0:0     CLOSE             httpd/1000 
TCP      :::80    :::0     LISTEN             httpd/1000 
TCP      0.0.0.0:0     0.0.0.0:0     CLOSE             httpd/1072 
TCP      :::80    :::0     LISTEN             httpd/1072 
TCP      0.0.0.0:0     0.0.0.0:0     CLOSE             httpd/1073 
TCP      :::80    :::0     LISTEN             httpd/1073 
TCP      0.0.0.0:0     0.0.0.0:0     CLOSE             httpd/1074 
TCP      :::80    :::0     LISTEN             httpd/1074 
TCP      0.0.0.0:0     0.0.0.0:0     CLOSE             httpd/1075 
TCP      :::80    :::0     LISTEN             httpd/1075 
TCP      0.0.0.0:0     0.0.0.0:0     CLOSE             httpd/1076 
TCP      :::80    :::0     LISTEN             httpd/1076 
TCP      0.0.0.0:0     0.0.0.0:0     CLOSE             httpd/1077 
TCP      :::80    :::0     LISTEN             httpd/1077 
TCP      0.0.0.0:0     0.0.0.0:0     CLOSE             httpd/1078 
TCP      :::80    :::0     LISTEN             httpd/1078 
TCP      0.0.0.0:0     0.0.0.0:0     CLOSE             httpd/1079 
TCP      :::80    :::0     LISTEN             httpd/1079 


Volatility en Linux dispone de un montón de comandos que permiten analizar la situación real de la máquina, en base al análisis de la memoria extraída, sin tener que confiar en una interfaz que puede haber sido preparada maliciosamente, por parte de un atacante experimentado.