Análisis avanzado de memoria de sistemas Microsoft Windows con Volatility

Buenas,

Hacia tiempo que tenia ganas de escribir sobre análisis forense de memoria un poco más en profundidad de lo que he publicado en otras ocasiones, así que aprovechando un rato libre os presento este caso práctico.

Requisitos

  • Instalación funcional de Volatility 2.0. Se aconseja seguir las instrucciones disponibles en http://code.google.com/p/volatility/wiki/FullInstallation
  • Una captura de memoria (en este caso, de una plataforma Microsoft Windows). En este ejemplo se trata del fichero memoria-shernando.mem
  • Posibilidad de ejecutar scripts bash, con lo que se aconseja instalar Volatility en Linux, aunque esto es perfectamente realizable en Windows, y siempre te puedes hacer tus scripts en cualquier otro lenguaje
  • Lectura pausada de los comandos principales de Volatility

Identificando la captura de memoria

Volatility tiene tres comandos asociados a la identificación de volcados de memoria: imageinfo, kdbgscan y kprcscan. Nosotros vamos a usar imageinfo como punto de partida. En esta fase pretendemos confirmar cual es el perfil recomendado para el análisis (Suggested Profile). En primera instancia, el comando imageinfo efectuara una búsqueda basada en estructuras de depuración del núcleo (KDBG) para determinar el perfil, aunque es igualmente posible identificar el sistema examinando los valores de Kernel Processor Control Region (KPCR). El núcleo de Windows emplea KPCR para almacenar información de cada procesador, y se puede localizar en la dirección de memoria virtual 0xffdff000 (ver captura), siendo otra fuente más para identificar el sistema.

python vol.py -f /home/shernando/memoria-shernando.mem imageinfo

volatility forensics

Tomamos nota de los perfiles sugeridos, y escogemos el que nos parezca más adecuado. En este caso, WinXPSP3x86, un XP Service Pack 3 corriendo en una arquitectura convencional de 32 bits con 4 procesadores.

Se pueden consultar los perfiles KDBG y KPCR mediante los siguientes comandos:

python vol.py -f /home/shernando/memoria-shernando.mem kdbgscan

python vol.py -f /home/shernando/memoria-shernando.mem kpcrscan

Enumeración de procesos en ejecución

Quizás lo mas inmediato y típico al evaluar una imagen de memoria sea conocer que procesos estaban en ejecución en el momento de efectuar la captura. Emplearemos pslist especificando el perfil que hayamos identificado en el paso anterior:

python vol.py --profile=WinXPSP3x86 -f /home/shernando/memoria-shernando.mem pslist

Para cada proceso se obtiene un offset de memoria, el nombre del proceso, el identificador de proceso (PID) y el identificador del proceso del proceso padre (PPID), el número de hilos, número de handles y fecha/hora en la que el proceso se inició. El offset que se obtiene por defecto es el virtual, si se quiere obtener el offset físico hay que emplear el operador -P, tal y como se explica en la documentación de Volatility. La información se presenta de una manera legible:

volatility forensics

Para ilustrar nuestro ejemplo seleccionamos, dentro de la lista de procesos, el correspondiente a la ejecución de Mozilla Firefox. Escogemos este ejemplo ya que en los navegadores es frecuente que exista uso de contraseñas, con lo que trataremos de localizar alguna en la memoria para ilustrar las capacidades de Volatility.

volatility forensics

En este caso, el navegador se ejecuta con PID 4128, con PID padre 1668 (algo normal, ya que pende de explorer.exe)

volatility forensics

Para quien esté interesado, el comando pstree muestra los procesos ordenados en árbol, con lo que es fácil deducir las dependencias para cada caso. El comando a ejecutar sería:

python vol.py --profile=WinXPSP3x86 -f /home/shernando/memoria-shernando.mem pstree

volatility forensics

A modo de ejemplo, en este caso se observa como services.exe pende de winlogon.exe y smss.exe, lo que viene siendo algo normal en una plataforma Windows. Como es lógico, la gestión de servicios (services.exe) depende del gestor de sesiones, que a su vez pende del subsistema de gestión de sesiones (smss.exe). Todos pertenecen al grupo de procesos SYSTEM. En rojo, las relaciones entre PIDs padre e hijo a título informativo.

Volcado específico del proceso en estudio (Método 1: memdump)

Con este método podemos aislar la porción de memoria en uso para un proceso determinado. Esto facilita las cosas, ya que en equipos modernos las imágenes de memoria (coincidentes con la memoria física instalada) pueden alcanzar 4, 6 u 8 GB con facilidad. Cuanto mas acotemos, menos trabajo de inspección sera necesario. No olvidemos que examinar cadenas de texto en una imagen de memoria es un ejercicio que no tiene por que traer resultados satisfactorios de vuelta, de modo que cuanto más facilitemos la labor, mejor.

Afortunadamente, memdump permite realizar el volcado de todos los segmentos de memoria asociados a un proceso. Nótese que por la dependencia de procesos en un sistema operativo, esto acarreara que además de los segmentos propios de un proceso se vuelquen todos los que por una razón u otra pudieran estar en uso como consecuencia de las dependencias entre procesos. No obstante, el tamaño de dicho volcado sera normalmente menor. Para este ejemplo, de un total de 3 GB de memoria, la ejecución sobre el PID de Firefox en estudio originó un volcado de 550.8 MB.

python vol.py --profile=WinXPSP3x86 -f /home/shernando/memoria-shernando.mem -p 4128 memdump -D volcados

Una vez obtenido el volcado, extraemos las cadenas de texto para ser inspeccionadas. A pesar de la reducción por focalización nos enfrentamos a 30.7 MB de fichero de texto como resultado.

strings volcados/4128.dmp >> volcados/4128.dmp.txt

Un simple grep sobre la cadena Passwd servirá para localizar las credenciales que buscábamos:

cat volcados/4128.dmp.txt | grep Passwd

volatility forensics

Volcado especifico del proceso en estudio (Método 2: Análisis del árbol VAD)

En el trabajo forense de imágenes de memoria de plataformas Windows es posible trabajar con el árbol de descriptores de direcciones virtuales (Virtual Address Descriptor, VAD). La idea es la siguiente: habida cuenta que las estructuras VAD proporcionan una abstracción a mas bajo nivel de la memoria, es posible emplearlas para realizar un análisis más enfocado. Técnicamente, el árbol VAD establece las relaciones de los distintos rangos de memoria empleados por un proceso determinado. A medida que el mecanismo de asignación VirtualAlloc asigna memoria en un proceso determinado, se van añadiendo entradas al arbol VAD, de modo que si obtenemos la estructura del árbol para un proceso, obtendremos todos los rangos de memoria en uso para dicho proceso.

Para trabajar con VADs, Volatility ofrece 4 comandos: vadwalk, que ofrece una visión general del árbol VAD, vadtree que muestra la información en forma de árbol propiamente dicho, vadinfo , que arroja información extendida de los nodos VAD y vaddump, que permite realizar volcados de la estructura VAD. En su mayoría admiten discriminación por PID. Los comandos a ejecutar, serian para cada caso, los siguientes:

python vol.py --profile=WinXPSP3x86 -f /home/shernando/memoria-shernando.mem -p 4128 vadwalk

python vol.py --profile=WinXPSP3x86 -f /home/shernando/memoria-shernando.mem -p 4128 vadtree

python vol.py --profile=WinXPSP3x86 -f /home/shernando/memoria-shernando.mem -p 4128 vadinfo

Para ilustrar nuestro ejemplo utilizaremos vaddump:

python vol.py --profile=WinXPSP3x86 -f /home/shernando/memoria-shernando.mem -p 4128 vaddump -D vads

Esta ejecución salvará, en el directorio vads, los distintos segmentos asociados al proceso. Aquí dejo un extracto del resultado, que en este caso contiene 346 elementos que totalizan 285.1 MB.

volatility forensics

Habida cuenta que extraer cadenas de 346 elementos es inviable si se hace a mano, podemos escribir un pequeño script que automatice la extracción para nosotros:

Page 1 of 4 | Next page