Para asegurar su permanencia en un sistema infectado, el malware puede aplicar diversas técnicas. Hoy discutiremos la utilización de AppInit_DLLs, un método que implica la modificación del registro de Windows y la inyección de código en los procesos corriendo en el equipo afectado.
Al desarrollar códigos maliciosos, los cibercriminales desean que sus amenazas persistan en los sistemas infectados, siempre con el mayor nivel de sigilo posible. Si al apagar o reiniciar el equipo el malware no fuese cargado en memoria de forma automática, los cibercriminales verían frustrados sus intentos de controlar la actividad en el sistema. A diferencia de las aplicaciones con fines legítimos, que en gran parte de los casos son iniciadas por acción del usuario, el malware puede que tenga una única oportunidad de ser corrido, por lo que debe asegurarse su ejecución continua en el sistema.
Además, si esta permanencia fuese lograda con métodos típicos de instalación, como la copia de los archivos en el mismo sitio que el resto de las aplicaciones, o la utilización de llaves típicas en el registro, el usuario podría ser alertado de la existencia del código malicioso. A continuación analizaremos uno de los métodos utilizados en los códigos maliciosos con estos fines.
Una de las formas más utilizadas para asegurar que el malware continúa en memoria consiste en la utilización de la llave Run del registro de Windows. En este sentido, la mayor parte de los archivos maliciosos que recibimos en el Laboratorio de Investigación de ESET Latinoamérica crean un valor en la llave HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run, con la ruta hasta el archivo malicioso. Luego, el sistema operativo ejecutará todos los archivos referenciados en esa llave del registro en cada inicio de sesión, sin intervención del usuario.
Sin embargo, hoy quiero mostrarles otro método que, si bien no es ampliamente utilizado por los cibercriminales, resulta muy efectivo. Si analizamos la llave de registro HKLM\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Windows, veremos que posee varios valores. Si ahora nos centramos en el valor AppInit_DLLs, es posible que observemos que no hay datos. Muchas veces así será, pero otras veces podremos encontrar un listado de archivos de tipo DLL. Así, todas las DLL especificadas en ese campo serán cargadas en el espacio de memoria de cada proceso que llame a funciones de User32.dll. Si tenemos en cuenta que todas las aplicaciones con interfaz gráfica en Windows importarán funciones de la API en User32.dll, entenderemos por qué el método resulta tan efectivo.
Para ilustrar esta situación, en la siguiente imagen se muestra el mapa de memoria de notepad.exe en una máquina no infectada:
Podemos observar que, además de las estructuras de tipo stack y heap, y las secciones propias de notepad.exe, se encuentran cargadas en memoria librerías de la API, como COMCTL32 o comdlg32. Si en algún momento posterior la máquina se infectase, se obtendría lo siguiente:
En este caso, mediante el uso de regedit puede verse que en AppInit_DLLs ya no hay datos nulos; el malware ha insertado su propia DLL maliciosa: spoolvxx32.dll. Ahora bien, esto implica dos cosas que quiero resaltar. Primero, que el malware debe haber dejado una copia de la DLL en la carpeta del sistema C:\Windows\System32. Segundo, que todas las aplicaciones que sean ejecutadas a partir de este momento, y que carguen User32.dll en memoria, también cargarán spoolvxx32.dll. Como la cantidad de aplicaciones puede ser muy grande, el código de la DLL maliciosa en DllMain incluirá las sentencias necesarias para discernir en qué proceso se está ejecutando, y así tomar acción o no.
Si ahora se depura el programa en ejecución notepad.exe, se observará que el mapa de memoria ha cambiado:
Ahora, la simple ejecución de notepad.exe ha cargado la DLL maliciosa en memoria. Si llevamos esto al plano general, entenderemos cómo este método puede utilizarse en keyloggers, malware de familias Spy, o cualquier aplicación maliciosa que pretenda alterar el comportamiento de otros procesos específicos. En otras palabras, este es un efectivo mecanismo de inyección de código. Afortunadamente, Windows 7 introdujo el soporte necesario para que las AppInit_DLLs se encuentren firmadas, con lo cual podría evitarse en gran medida la ejecución de código arbitrario.