En ocasiones, el análisis de malware requiere del desarrollo rápido de nuevas herramientas que nos permitan interactuar a bajo nivel con los binarios bajo estudio. Con el objeto de proporcionar una API sencilla para este propósito es que nace Pin: un entorno de trabajo que nos permite escribir código a ejecutarse entre cada instrucción, o bloque de instrucciones.
A continuación, repasaremos sus principales características, mientras vemos algunos casos prácticos de aplicación.
¿Por qué utilizar Pin?
Ideada por Intel hace algunos años ya, Pin continúa vigente al momento de insertar código C o C++ entre instrucciones para alterar el funcionamiento de ejecutables en arquitecturas IA-32 y x86-64. Las herramientas creadas con este framework, denominadas Pintools, nos permiten ganar un completo control sobre la ejecución de un binario, tanto en plataformas Windows como en sistemas Unix.
Contar con un entorno de trabajo de este estilo resulta de especial importancia en situaciones en las que no contamos con el código fuente de la aplicación. Así, es posible monitorear y/o interceptar llamadas al sistema ocurridas en tiempo de ejecución, y consecuentemente, realizar acciones sobre la memoria o los procesos que nos permitan desempaquetar un binario, modificar el flujo de ejecución, realizar taint analysis, y mucho más.
Es por todo esto que Pin actúa como un gran aliado frente al análisis de malware, especialmente cuando nos encontramos con muestras que no pueden ser analizadas a través de los métodos habituales por exhibir características peculiares, como por ejemplo, estar empaquetadas con un packer fuera de lo común. Entonces, podemos crear nuestras propias herramientas para abordar la problemática desde una perspectiva personalizada que nos permita resolver de manera eficiente el análisis.
Automatizando la inspección de códigos maliciosos
La generación y utilización de Pintools nos permite mecanizar el análisis de muestras y ahorrar tiempo en el procesamiento de malware, evitándonos la necesidad de colocar breakpoints y generar dumps de manera manual.
En primer lugar, se deberá disponer de los archivos que hacen a Pin, los cuales se pueden descargar. Luego, los desempaquetaremos en la ruta raíz de la aplicación. Tras escribir y compilar el código fuente de nuestra tool, podremos finalmente ejecutarla sobre la muestra.
Para el caso de malware del tipo RunPE, disponemos de una Pintool creada por Jurriaan Bremer que nos permite desempaquetar dinámicamente el ejecutable en algunos pocos minutos, y que a pesar de tener ya un par de años de antigüedad, continúa siendo de suma efectividad frente a este tipo de ejecutables.
Para ejemplificar la utilización de esta herramienta, tomaremos una muestra de Win32/Dorkbot empaquetada mediante el uso de un packer en Visual Basic. Podemos ver que, inicialmente, PEiD identifica la muestra como empaquetada:
Seguidamente, sobre el archivo original aplicaremos la Pintool diseñada por Bremer: con tan solo ejecutar un par de comandos desde la consola de Windows SDK podemos obtener el verdadero archivo malicioso.
Ahora, es posible constatar que PEiD no logra identificar ningún packer:
Con la verdadera rutina maliciosa en nuestras manos, pasamos a analizar la ejecución del malware, pudiendo observar a simple vista las cadenas de texto en él incluidas, intuyendo primeramente su comportamiento como comienzo de una investigación.
Examinando etapas en la ejecución
En otras ocasiones, nuestro interés recae sobre la comprensión de los diferentes pasos en la ejecución de una muestra. Este es el caso cuando encontramos custom packers, o múltiples instancias de empaquetamiento. Entonces, podemos utilizar Pintools para ayudarnos a identificar las direcciones de memoria en las cuales comienzan y terminan las rutinas de desempaquetado.
Una premisa para iniciar este tipo de análisis es suponer que todo código desempaquetado es escrito en memoria, y luego ejecutado. Bajo esta aproximación –presentada en detalle por Douglas Goddard–, se pueden interceptar las instrucciones del sistema en las cuales se escribe espacio de memoria, y generar dumps periódicos de la misma.
Para demostrar la aplicación de esquemas como esto, utilizaremos una muestra de Win32/Emotet.AB. Si realizamos algunas modificaciones al código provisto y aplicamos la herramienta sobre la muestra en cuestión, obtenemos la siguiente secuencia de archivos, de los cuales podemos identificar dos que se distinguen por su tamaño.
Luego, al examinar con IDA estos segmentos de memoria, tendremos una clara idea de cómo se instrumenta cada una de las etapas en la rutina de ejecución, lo que nos facilitará la colocación de breakpoints en las direcciones de memoria que han sido observadas y que resultan de nuestro interés.
Depurando ejecutables con IDA
Utilizando las opciones incorporadas en los últimos releases de IDA es posible utilizar Pin para realizar la depuración de ejecutables, como lo haríamos con cualquier otro debugger. Desde la versión Pro 6.6, podemos acceder a la opción pertinente desde Debugger > Run/Attach > PIN Debugger.
Será necesario disponer de la Pintool específica para IDA, la cual puede ser descargada del sitio oficial. Según la plataforma en la que nos encontremos, deberemos ingresar el comando make, o generar la .dll necesaria compilando el proyecto de Visual Studio que se incluye dentro del archivo comprimido provisto.
En este último caso, acorde a la versión de Visual Studio que estemos corriendo, tendremos que modificar la configuración para la construcción del proyecto, actualizando las librerías para que sean consecuentes con la versión del compilador en uso.
Será necesario efectuar la configuración inicial del depurador, a fin de establecer la localización de los ejecutables requeridos. Para lograr esto, deberemos dirigirnos a Debugger > Debugger Options > Set Specific Options, e ingresar la ubicación de la aplicación Pin y la Pintool correspondiente al debugger antes creada.
En adelante, estaremos en condiciones de colocar los breakpoints donde creamos necesario, y proceder con la depuración como de costumbre. Más información al respecto puede encontrarse en el manual de IDA para la depuración con Pin.
Taint tracking: siguiendo las pistas
Los entornos de instrumentación de operaciones sobre ejecutables son una valiosa opción a considerar al momento de realizar el análisis dinámico por taint tracking de aplicaciones.
Pin nos provee las funciones esenciales para marcar el área de memoria que nos interesa, y en base a ello, registrar toda operación de lectura/escritura que sobre ésta tenga lugar. También, nos permite extender el marcado a medida que los datos se propagan por nuevas direcciones de memoria, generando un listado detallado de los movimientos de información.
Basándonos en los ejemplos creados por Jonathan Salwan, podemos derivar de manera fácil y rápida variantes de código que nos permitan, por ejemplo, monitorear la memoria que un proceso localiza e inyecta dentro de otro proceso al interceptar funciones como NtOpenProcess, VirtualAllocEx, WriteProcessMemory, ReadProcessMemory, o similares.
Así, podemos codificar una Pintool que recupere el handler del proceso externo, para luego registrar las instrucciones de lectura/escritura sobre esa región de memoria mediante VirtualQueryEx. Parte de la salida obtenida puede observarse a continuación:
Pin, una opción vigente para todo entorno de análisis
A pesar del bajo perfil que mantiene en el mundo del análisis de malware, la instrumentación de código con Pin resulta de absoluta relevancia al momento de comprender en profundidad el funcionamiento de un archivo malicioso, generando nuestras propias herramientas o adaptando otras ya creadas para cada caso en particular.
Como hemos visto, mediante el uso de Pintools nos es posible hacer foco en la interacción de la muestra con la red, el sistema de archivos, los registros, las llamadas al sistema, y generar firmas para futuras detecciones y análisis masivo de datos.
Ya que conocemos los principios básicos en la aplicación de Pin en entornos tradicionales, observaremos en próximas publicaciones la incidencia de este tipo de herramientas sobre nuevas plataformas, implementando tools para el análisis de apps maliciosas en Android.