Empiezan los problemas
Viendo el diseño de la sandbox, podemos empezar a advertir los primeros problemas:
- Los ficheros resultantes de los análisis se almacenan en la propia
máquina guest por lo que es posible que sufran alteraciones por parte de
la muestra.
- La comunicación entre la DLL y el analizador no lleva ningún tipo de
autenticación, así que es posible inyectar datos falsos dentro del
análisis (limitados).
- Del mismo modo, el agente que se ejecuta en la máquina también carece de autenticación.
- No todas las APIs están hookeadas por lo que se pierde información para generar firmas más específicas.
- En tanto que las APIs están hookeadas en espacio de usuario, su detección es sencilla.
Detección de hooks
Como comentaba anteriormente, no todas las apis están monitorizadas,
pero existe un número interesante de ellas. Para hacer esto, el
analizador inyecta la dll una vez que el proceso está lanzado en estado
suspendido. Cuando se ha asegurado de que la dll se ha inyectado
correctamente, cambia el estado y empieza la fiesta.
Para hacer el hook de las APIS, Cuckoo tiene 5 métodos de los cuales usa 1:
Figura 2: Extracto de código en cuckoomon.c definiendo el método de interceptación
Como curiosidad, el proyecto malwr.com usa otro distinto. La forma que
tiene de hookear las APIS es mediante la inserción de un salto absoluto a
otra dirección dentro de la propia DLL que hará las veces de función
remplazada. Esto se hace en el punto de entrada de cada API. Como
ejemplo, las imágenes muestran dos funciones antes y después de la carga
de la DLL:
|
Figura 3: La función DeleteFileW antes y después de haber sido hookeada |
|
Figura 4: La función ZwCreateProcess antes y después de haber sido hookeada |
Fijaos que la instrucción “MOV EDI,EDI” en DeleteFileW ha sido
remplazada por un “JMP”, así como las siguientes instrucciones para
acomodar el cambio. Muchas de las APIs de Windows tienen como prólogo de
las funciones ese “MOV EDI,EDI”. Esto es intencionado, Microsoft lo
hizo así para permitir el parcheado en caliente. Raymond Chen en su
artículo
http://blogs.msdn.com/b/oldnewthing/archive/2011/09/21/10214405.aspx
lo explica un poco más en detalle. Aunque no todas las llamadas tienen
el mismo aspecto y dependerá de cada una de ellas. En el caso de
ZwCreateProcess, la instrucción empieza asignando a EAX el valor de la
llamada y el hook lo reemplaza por un salto a la dll.
La detección de estos hooks se puede realizar comparando los opcodes
originales con los que la muestra puede leer durante su ejecución.
Aunque el propio código de Cuckoo nos propone una alternativa:
|
Figura 5: El código de cuckoomon nos da pistas sobre cómo detectarlo |
Directorios
Otra de los métodos de detección de Cuckoo es a través de la búsqueda
del directorio donde se alojan los ficheros de log que registra la DLL
inyectada. Esta ruta está incluida en el código de la DLL por lo que a
menos que se haya modificado, siempre estará en c:\cuckoo.
Usando esta función, podemos detectar la presencia de un directorio y de ahí determinar si al menos el directorio existe:
|
Figura 6: Función para conocer si el directorio existe |
Named Pipes
Cuando se lanza el proceso a través del analizador, se crea un pipe al
que acceden ambos para comunicarse eventos relevantes (nuevos procesos y
ficheros creados). Este pipe, que siempre tiene el mismo nombre, es
accesible desde \\.\pipe\cuckoo. Su detección puede darse o bien
abriendo el pipe o a través del listado de los pipes existentes con la
siguiente función:
|
Figura 7: La función de la imagen se puede utilizar para detectar el pipe de cuckoo |
En este caso opté por listar el contenido y buscar “cuckoo”. El motivo
principal fue que en las pruebas encontré firmas que detectaban el
acceso a ciertas partes de cuckoo.
El principal problema de esto, no es sólo el hecho de ser fácilmente
detectable. Dado que cualquier proceso puede escribir en ese pipe, el
malware puede enviar información errónea al proceso de análisis y
alterar el resultado del mismo.
Detección del agente
El agente de Cuckoo es una novedad en la versión 0.4. Anteriormente, la
muestra de malware se dejaba en un directorio compartido entre la
máquina host y la guest. Dado que ahora las máquinas virtuales no tienen
por qué estar alojadas bajo Virtualbox, se ha optado por instalar un
agente que permite comunicarse con el host para ejecutar acciones como
subir la muestra u obtener el análisis, haciéndolo independiente del
sistema de virtualización. La contrapartida es que ese agente es visible
en un simple listado de procesos, que el puerto también está codificado
en el código fuente y que carece de autenticación, al igual que el
pipe, por lo que la interacción con el agente es libre.
Bypass de la sandbox
Como punto final al análisis me dediqué a hacer pruebas de concepto con
todo lo expuesto además de poder comprobar no solo que la detección es
posible y trivial, sino que además podría ejecutar un binario sin el
conocimiento de la sandbox.
Como comentaba antes, la inyección de la DLL se realiza al lanzar la
aplicación en estado suspendido. Durante este proceso, la DLL se carga
en el espacio de memoria del proceso y modifica las llamadas a las apis
introduciendo saltos hacia las funciones suplantadas. Cuando termina, el
proceso recibe la orden de empezar a ejecutarse y el resto ya lo
conocéis.
Sin embargo, durante la ejecución, el proceso tiene control casi
absoluto sobre sí mismo. En tanto que conocemos algunas de las apis que
intercepta y su forma original, es posible volver a revertir los hooks
que realiza la sandbox.
El proceso es simple y se resume en este gráfico:
|
Figura 8: Proceso para revertir el hook de Cuckoo |
Para poder hacer el bypass de la dll, primero se tiene que restaurar las
funciones ZwCreateProcess, ZwCreateProcessEx y CreateProcessInternalW:
|
Figura 9: La función VirtualProtect habilita la escritura de los bytes en la API hookeada |
Después de obtener la dirección de las tres funciones, alteramos su
punto de entrada con los bytes originales. En este caso son para un
Windows XP EN SP3, no he tenido la oportunidad de tener acceso a otro
sistema para comprobarlo en otras versiones ? Después de estos cambios,
las funciones que notifican a Cuckoo que existe un nuevo proceso, quedan
en sus estado original por lo que la sandbox es incapaz de inyectar la
dll en el proceso nuevo que se ejecutará sin restricciones:
|
Figura 10: ¿Dónde está la calculadora? |
A pesar de que el proceso lanza una calculadora, no aparece en el
listado de procesos (Process Tree). El hecho de poder acceder a la
dirección de las funciones interceptadas y poder restaurar los bytes
originales, provocan que la sandbox pierda el conocimiento de las
acciones que se realizan a partir de ese mismo momento.
Dado que Cuckoo es un proyecto de código abierto, implementar algunas
medidas para entorpecer su detección son, en algunos casos, igual de
triviales. Desde modificar las rutas de los directorios, pasando por
cambiar la forma en la que se comunican cada uno de los componentes.
Por el contrario, implementar un método para evitar restaurar las
funciones interceptadas se complica un poco, aunque sería posible
modificar el comportamiento de VirtualProtect para evitar que el proceso
pueda modificar los permisos de ciertas zonas que pudieran contener las
funciones que nos interesan. En cualquier caso, esperamos que este
proyecto siga adelante porque tiene muchas cosas que aportar y aún le
queda por sorprendernos.
No hay comentarios:
Publicar un comentario