Hace algunas semanas estuvimos analizando la importancia de conocer aquellas strings que se encuentran cifradas en un archivo malicioso. Esto es particularmente necesario en muestras de tipo TrojanDownloader donde la URL de descarga no es observable a simple vista. Sin embargo, el método que utilizamos en aquella oportunidad requería la intervención manual para ir descifrando cada string. Es por ello que en esta entrega estaremos analizando una forma automatizada de extraer las strings de Python e Immunity Debugger.
La muestra que analizamos en su momento era un archivo CPL. Si recordamos lo visto en esa oportunidad, el ejecutable contenía varias strings cifradas, entre ellas dos URL para descargar otras aplicaciones maliciosas, que eran decodificadas mediante la ejecución de una misma rutina de descifrado. Luego, si ejecutábamos un par de instrucciones alrededor de cada llamada a esa rutina, íbamos descifrando cada una de las strings:
Ahora bien, el mecanismo es exactamente el mismo para cada string, por lo que nos preguntamos: ¿cómo podemos programar este proceso para que se realice en cada una de las strings cifradas de manera automática? La respuesta recae en el hecho de que Immunity Debugger incorpora una API para Python, immlib, que permite gran flexibilidad en el manejo de las tareas de debugging. Así, mediante la ejecución de un script a la medida de nuestras necesidades, podremos automatizar el descifrado de las strings. Para ello, el script deberá realizar las siguientes tareas:
- Recuperar las direcciones de memoria desde donde se llama a la rutina de descifrado
- Buscar hacia atrás (desde la dirección de la llamada) la instrucción que hace el MOV de la string cifrada
- Guardar esa string y la dirección donde está almacenada
- Guardar en EIP la dirección de la rutina de descifrado y asignar valores a los registros utilizados en la llamada
- Ejecutar la instrucción del CALL
- Recuperar el resultado de la ejecución y agregarlo a una tabla que será mostrada por pantalla
En cuanto al punto 4, podemos observar en el código que en EAX se carga la dirección de la string cifrada y en EDX un puntero a un buffer donde se almacenará el texto plano, descifrado. Hemos decidido utilizar EBP-0x10 para almacenar el resultado, pero podría utilizarse cualquier otra dirección de memoria. Sin embargo, hay que tener cuidado de no pisar ningún otro dato:
Al ejecutar el script, se obtiene una ventana de Immunity Debugger con los datos que hemos especificado en nuestra tabla. Ahora bien, los más atentos habrán observado que en la primer imagen de nuestro post la dirección de la rutina de descifrado es 0x35E5A0, en el paso 1 de nuestro script es 0x15E5A0 y en la imagen que se muestra a continuación es 0x38E5A0. Esta incongruencia se debe a que he realizado las pruebas en una máquina virtual con Windows 7, y las capturas de pantalla no se corresponden a una misma ejecución continua. Debido a la presencia de ASLR en esta versión del sistema operativo de Microsoft, hay que prestar especial atención a que la dirección que ponemos en nuestro script se corresponda con la dirección de la rutina de descifrado al momento de correr el script:
En resumen, hemos logrado descifrar todas las strings sin siquiera conocer los detalles de funcionamiento de la rutina de cifrado. Simplemente conociendo cómo la función recibe sus parámetros de entrada y dónde coloca el resultado, nos alcanza para modificar el script y poder aplicarlo a otros ejecutables.
SHA-1 de la muestra analizada
7fad3b1bb3d6263a3eabe21b68a8db792eeffc71 – Intimacao.cpl