Ya vimos en este blog qué son los archivos CPL maliciosos y por qué no debemos hacer clic en ellos. Sin embargo, en aquella oportunidad no mencionamos que el debugging de este tipo de archivos es un poco más complicado de lo normal, con lo cual debemos tener ciertas consideraciones. Hoy nos ocuparemos del análisis de estas particularidades.
De la misma forma que una DLL no puede ejecutarse por sí sola (requiere de un EXE que invoque alguno de los exports de la DLL, por ejemplo, rundll32.exe ruta_DLL, export_a_ejecutar), un CPL también requiere que alguien llame a CPlApplet. Sin embargo, dado que CPlApplet recibe diversos mensajes específicos, la ejecución directa con rundll32.exe no será adecuada en tanto esos mensajes no sean enviados.
La clave está entonces en observar que cada vez que se hace doble clic en un CPL se ejecutará control.exe, quien llamará a rundll32.exe con los parámetros adecuados. Luego, control.exe es un buen punto de partida para empezar nuestra sesión de debugging.
En la imagen anterior vemos cómo empezaremos a debuggear control.exe con la ruta hasta el CPL como argumento (esto puede configurarse desde el menú “File > Set New Arguments…”, recordando que hay que presionar Ctrl+F2 para que se tomen los cambios). Luego, vamos a comprobar los nombres referenciados por control.exe, donde se destaca ShellExecuteEx, dado que es el único import que vemos que podría ejecutar rundll32.exe.
Si buscamos en qué partes del código de control.exe se referencia a ShellExecute, encontraremos que esto sucede en un único punto. Así, colocamos un breakpoint en esa instrucción y continuamos la ejecución hasta obtener lo que vemos en la próxima imagen.
Allí, puede apreciarse que rundll32.exe va a ser llamado con los argumentos: “Shell32.dll,Control_RunDLL <ruta_CPL>”. Esto nos da un indicio de por qué no es correcto ejecutar directamente rundll32.exe con el CPL como argumento: es el código contenido en Control_RunDLL, de la librería Shell32.dll, el que sabe cómo pasar los mensajes a CPlApplet.
Asimismo, es importante notar que, la próxima vez que tengamos que debuggear un CPL, podemos empezar por rundll32.exe con estos argumentos que hemos encontrado, sin necesidad de debuggear control.exe antes.
Una vez que estamos detenidos en rundll32.exe, debemos buscar la llamada a Control_RunDLL. Una forma de hacer esto es buscar las referencias a GetProcAddress hasta encontrar aquella que trata de resolver la ubicación del import que buscamos. Así, colocamos breakpoints en todas las llamadas hasta obtener la dirección de Control_RunDLL en Shell32.dll.
Podemos colocar un breakpoint allí y continuar la ejecución. En este momento nos encontramos dentro del código de Control_RunDLL, con lo cual podemos buscar nuevamente las referencias a GetProcAddress para la resolución de CPlApplet.
Sin embargo, queremos capturar el momento en que el CPL se carga en memoria y se ejecuta el entry point (DllMain), ya que allí podría haber algún que otro truquito anti-VM (como ya vimos en el post “¿Cómo realizar un análisis de malware que evita la virtualización?”), o incluso el mismo payload malicioso. Entonces, sería conveniente buscar en qué parte del código se llama a LoadLibrary para nuestro CPL.
Como se observa en la imagen, obtendremos muchos puntos del código de Shell32.dll desde donde se llama a LoadLibraryA o LoadLibraryW. A pesar de esto, si luego de colocar todos los breakpoints continuamos la ejecución, el primer LoadLibrary que se ejecutará es el de nuestro CPL. Para que la ejecución quede detenida en la primera instrucción de DllMain, una de las opciones es configurar Olly para que se detenga al cargar el CPL en memoria:
Ahora bien, si volvemos al punto posterior de la llamada a LoadLibrary, encontraremos la referencia a CPlApplet a unas pocas instrucciones de distancia. Eso sí, una vez que estemos en el código de CPlApplet, tenemos que prestar atención a los mensajes que se pasan como argumentos: sólo nos interesa el mensaje CPL_DBLCLK.
Si bien los pasos seguidos en este análisis son interesantes para comprender la ejecución de los archivos CPL, podemos formular un método más práctico para debuggear este tipo de amenazas. Para ello, podemos apoyarnos en la utilización de algún desensamblador como IDA Pro, con el cual podamos identificar la dirección del entry point y de CPlApplet.
Una vez conocidas estas direcciones, podemos abrir directamente el CPL en Olly (haciéndole creer que es un archivo de tipo EXE, como describimos en el post “Debuggeando archivos DLL empaquetados”) y setear los breakpoints en esas direcciones. Luego, si cerramos esa instancia de Olly y abrimos una nueva para debuggear rundll32.exe, tal como hemos descripto, Olly “recordará” esos breakpoints establecidos en el CPL.
En resumen, para debuggear un CPL en forma rápida, sugiero:
- Observar la dirección de DllMain y de CPlApplet, por ejemplo con IDA Pro.
- Abrir el CPL con Olly y setear los breakpoints donde nos interese. Cerrar OllyDbg.
- Abrir rundll32.exe con Olly, e ingresar “Shell32.dll,Control_RunDLL <ruta_CPL>” en los argumentos.
- Ejecutar hasta que se alcance el primer breakpoint en el CPL.
SHA-1 de la muestra analizada
7fad3b1bb3d6263a3eabe21b68a8db792eeffc71 - Intimacao.cpl