Análisis de malware
Antianálisis de malware y elusión de sus técnicas
11 de mayo de por Ninja de seguridad
Continuando con el artículo anterior sobre cómo el malware puede evadir las detecciones normales y cómo los analistas pueden eludir esas técnicas, veamos ahora algunas detecciones aún más complejas e inteligentes empleadas por el malware en estos días.
Comencemos con la muestra de malware (text.exe) infectando nuestra máquina de prueba con él y notemos algunos de los artefactos que genera.
En la captura de pantalla anterior, podemos ver que el proceso genera un proceso hijo con el mismo nombre.
Desde arriba, podemos ver que la muestra de malware está intentando resolver un nombre DNS. (Tenga en cuenta que esto es en la otra máquina donde se enruta todo el tráfico de la máquina infectada)
Pero tan pronto como lanzamos herramientas como Wireshark en las máquinas infectadas; Podemos ver que los procesos maliciosos comienzan a salir (captura de pantalla de arriba), lo que da una indicación de que el código dentro de la muestra sale si encuentra que algunas herramientas de análisis conocidas están presentes en la máquina. ¡Inteligente!
Sin embargo, profundicemos en esta funcionalidad del código malicioso. Cargue esta muestra dentro de IDA pro y, como se indicó en el artículo anterior, vaya a la ventana de nombres para ver si hay cadenas. Podemos ver que muchas cadenas corresponden a herramientas de analistas conocidas como Wireshark, Sandbox, VirtualBox, etc. Antes de idear una técnica para evitar estos mecanismos de detección, primero veamos el código que detecta estas herramientas.
Comencemos con la detección de Wireshark. Haga doble clic en la cadena Wireshark.exe para buscar referencias
y luego haga doble clic en sub_408B1D para saltar a la ubicación de la función donde está incrustada la cadena.
Justo debajo de la cadena Wireshark, podemos ver que se realiza una llamada de función a sub_408A28. Saltemos a este código de función y veamos qué hay dentro de él.
Podemos ver que el código ha realizado llamadas a CreateToolhelp32shnapshot, Process32First, Process32Next. Según MSDN, CreateToolhelp32shnapshot se usa para capturar todos los procesos en ejecución, subprocesos en el sistema y Process32First se usa para analizar el primer proceso enumerado en CreateToolhelp32shnapshot y Process32Next se usa para analizar el siguiente proceso en la lista. En otras palabras, este código enumera los procesos en ejecución en el sistema.
Ahora el código debe comparar los nombres de los procesos que recupera del sistema con las cadenas que vimos anteriormente, lo que significa que se utilizará la función strcmp. En 408A95 podemos ver una llamada a la función strcmp y compara cadenas con lo que se pasa como argumento. Recuerde que cuando se llama a esta función justo encima se usó una instrucción mov para colocar la cadena ‘Wireshark.exe’ que luego se usa como argumento.
El Apéndice 1 confirma este entendimiento al ejecutar el ejemplar en OllyDBG.
Siempre es mejor cambiar el nombre de la función cuya funcionalidad se descubre, así que nombremos la función en sub-408A28 como «CheckProcessPresence».
Recuerde que el análisis anterior es solo para la cadena ‘wireshark.exe’, pero lo más probable es que el espécimen deba estar llamando a la misma función para verificar también otros procesos. También cambiemos el nombre de todas las funciones que hacen referencia a «CheckProcessPresence».
Ahora que hemos cambiado el nombre de las funciones, veamos la función que llama a todas estas funciones. En este código de función, puede ver varias referencias a otras funciones a las que acabamos de cambiar el nombre. Cambiemos el nombre de esta función a «AnalysisToolsPresence».
Para resumir lo que hicimos hasta ahora, visualicémoslo a través de Graph en IDAPro.
Dado que estamos retrocediendo en las llamadas a funciones, naveguemos hasta la función que llama a «AnalysisToolsPresence». A continuación se muestra el código para esta función.
En el código, podemos ver la referencia a AnalysisToolsPresence, y luego vemos que el código está comparando el valor de retorno y si al es cero, se ejecuta una instrucción jz para cambiar la ejecución a 408CE3 (esto significa que el código de las herramientas de análisis está buscando for no está presente) de lo contrario, si el valor de retorno no es cero, se llama a la función TerminateProcess, cuya función se explica por sí misma.
Ahora bien, cuando se trata de eludir este mecanismo de detección, puede haber muchas formas de hacerlo:
- Cambie las cadenas codificadas para que no coincidan con las herramientas presentes en el sistema
- Cambiar la instrucción JZ a una instrucción no condicional como JMP, para que nunca se llame a TerminateProcess.
Pero hay otra manera de eludir este código. Si ha estado prestando atención desde el principio, es posible que se haya dado cuenta de que este espécimen sigue verificando los procesos en ejecución en el sistema y solo detiene la ejecución si encuentra algunas cadenas conocidas. Esto significa que el espécimen está usando algún otro hilo para verificar las herramientas de análisis en el sistema. Averigüemos si nuestra suposición es correcta.
Naveguemos hasta la función que llama a la función en 408926.
Podemos ver una llamada a CreateThread después de llamar a 408CB4 (stub donde se realizan todas las llamadas a funciones), lo que significa que nuestra suposición es correcta. Si podemos evitar que se cree este hilo, no se comprobará la presencia de las herramientas de análisis. Carguemos este código en OllyDBG.
Coloque un punto de interrupción en 408955 y ejecute la muestra. Podemos deshabilitar la ejecución de CreateThread parcheando esta instrucción con NOP (como se hizo en el artículo anterior).
Tenga en cuenta que este espécimen está parcheado únicamente en la memoria. Para guardar este parche en el ejecutable en el disco, copie todas las modificaciones al ejecutable y guarde el archivo.
Después de ejecutar este código parcheado, ahora incluso después de ejecutar herramientas como Wireshark, el ejemplar continúa su ejecución.
Apéndice 1
Verificar la suposición de la función cmp, colocar un punto de interrupción en 408A95 y luego ejecutar la muestra
A continuación se muestra el contenido de la pila y podemos ver que el código coincide con las cadenas ‘Proceso del sistema’ (uno de los procesos enumerados por el código) con ‘joeboxserver.exe’ (una de las cadenas codificadas que el código está verificando).
¡Conviértete en un ingeniero inverso certificado!
Obtenga capacitación práctica en vivo sobre análisis de malware desde cualquier lugar y conviértase en un analista certificado de ingeniería inversa. Comienza a aprender
Tenga en cuenta que el código se ejecutará varias veces para hacer coincidir todos los procesos enumerados desde un sistema con algunos codificados.