miércoles, abril 20, 2016

ROPInjector: Evasión de motores antimalware usando ROP

En la pasada Black Hat USA de 2015 se presentó una charla denominada ROPInjector: Using Return-Oriented Programming for Polymorphism and AV Evasion en la que sus investigadores comentaban como utilizar ROP para mejorar los ratios de evasión en la detección de binarios maliciosos. ROP es utilizado, generalmente, para hacer un bypass de DEP, Data Execution Prevention. Es decir, cuando se detecta una vulnerabilidad en un software, el cual se ejecuta en un escenario con DEP como medida de protección, se puede utilizar ROP como vía para hacer el bypass a DEP. En la charla los investigadores proponían un uso diferente de ROP, proponiendo utilizarlo para lograr mejorar la evasión de antivirus y una vía alternativa al polimorfismo.

Figura 1: ROPInjector: Evasión de motores antimalware usando ROP

La idea principal es utilizar ROP para no levantar sospechas en la parte del antivirus. ROP puede ser utilizado para transformar cualquier shellcode proporcionada a un esquema ROP-based equivalente. En este vídeo puedes ver la conferencia.


Figura 2: ROPInjector: Using Return-Oriented Programming for Polymorphism and AV Evasion

En otras palabras, el objetivo de la investigación era conseguir un binario que reduzca la detección de los AV. Los investigadores enumeraron algunos desafíos para la creación de ROPInjector:
• El nuevo fichero PE debería ser eficiente en la evasión de AV. Es decir, bajar el ratio de detección frente a otras técnicas de evasión, como las que pueden ser utilizadas por Veil-Evasion, Shellter o Payday. 
• El fichero PE benigno dónde se realizará la inyección no debe estar corrupto. 
• La herramienta ROPInjector fue planteada como genérica. Es decir, otros podrán añadir shellcodes.
Figura 3: Esquema de funcionamiento
ROPInjector tiene una serie de etapas que deben ser validadas para generar el binario malicioso. Las etapas que utiliza la herramienta para su funcionamiento fueron enumeradas en la charla y son las siguientes:
• Análisis de la shellcode. Ésta debe ser para arquitecturas x86.
• Encontrar ROP gadgets en el fichero PE.
• Transformar la shellcode en un ROP chain equivalente.
• Inyectar en el fichero PE los ROP gadgets, si son requeridos.
• Ensamblar ROP chain en el fichero PE.

• Generar el fichero final (PE Patching).
En la siguiente imagen se muestra cómo queda la estructura, antes y después de la inyección de ROP y el parcheo del binario final.

Figura 4: Estructura del binario antes y después de la manipulación

Durante la presentación de la charla los investigadores mostraron una evaluación que hicieron de su herramienta a través de la manipulación de 9 binarios legítimos. Los binarios utilizados fueron Firefox.exe, java.exe, AcroRd32.exe, cmd.exe, notepad++.exe, etcétera. Como se ve binarios conocidos y utilizados en el día a día. El estudio y evaluación utilizaba varias técnicas y combinaciones:
• Sin parchear, es decir, fichero original.
• ROP’ed shellcode & run last.
• ROP’ed shellcode & delayed execution (20 segundos de delay).
• Shellcode sin alterar.
Utilizaron Virus Total para comprobar el ratio de detección y los resultados pueden ser vistos en la siguiente gráfica. La shellcode que utilizaron fue un Reverse TCP Shell:

Figura 5: Evasiones obtenidas con cada método en cada binario de muestra

Figura 6: Estadísticas generales de evasión por cada prueba

PoC: Probando ROPInjector

Decidí probar la herramienta, la cual se puede obtener desde Github y solo se necesita compilar. El objetivo era probar qué resultados obtendría y si conseguiríamos obtener un ratio de detección bajo o aceptable. Una vez compilada la herramienta se puede lanzar de manera sencilla a través de la siguiente instrucción:
ropinjector.exe [fichero PE benigno] [shellcode a inyectar]
        [fichero PE malicioso a generar] [opciones*]
Cuando bajamos ROPInjector vienen tres shellcodes dentro de la carpeta con mismo nombre. Añadir shellcodes es sencillo y para el tercer ejemplo que mostraré a continuación añadí una shellcode que se puede obtener de exploit-db.

Figura 7: Inyectando OpenCalc.bin

Caso 1: Shellcode opencalc.bin

Dentro de la carpeta shellcodes encontramos un fichero denominado opencalc.bin. Generamos un fichero PE malicioso con ROPInjector, el cual haya insertado dicha shellcode en el binario resultante.

Figura 8: Solo 4 de 56 motores detectaron la shellcode

Al subirlo a Virus Total se obtiene un resultado bastante interesante 4 de 56 motores antimalware han detectado el fichero como malicioso.

Caso 2: shell inversa TCP

Dentro de la carpeta shellcodes se encuentra el fichero revshell.txt, el cual contiene una shellcode que ejecutará una shell y se conectará de forma inversa a nosotros, cuando el binario sea ejecutado.

Figura 9: 17 de 56 motores detectaron reverse shell

Tras crear el binario con ROPInjector y subirlo a Virus Total observamos un resultado de 17 de 56 motores AV detectándolo. No es el mejor resultado, pero viendo el listado de AV que lo detectan se echa en falta algunos de los principales del mercado.

Caso 3: shellcode importada

Para el último caso, importamos en un fichero TXT una shellcode y la utilizamos para generar un fichero malicioso con ROPInjector. El resultado que hemos obtenido es de 2 de 56 motores AV, lo cual es un resultado muy prometedor, y prácticamente indetectable.

Figura 10: Solo 2 motores detectaron este último cambio

Interesante herramienta que ofrece un punto de vista distinto a la hora de generar binarios maliciosos. Los resultados, aunque no se haya alcanzado el 0 de 56, se pueden entender como satisfactorios, ya que en 2 de los 3 casos probados, el código malicioso era detectado por menos del 10% de los AV.

Autor: Pablo González Pérez (@pablogonzalezpe)
Escritor de los libros "Metasploit para Pentesters", "Ethical Hacking" y “Pentesting con Powershell

1 comentario:

Regnad Danger dijo...

Antes que nada muchísimas gracias por la información, es realmente interesante y me cae muy bien para el análisis de programas dañinos, antivirus y demás.
Actualmente, por razones académicas realizo análisis de testeo mediante maquinas virtuales, cuckoo 2.0 y otras herramientas relacionadas con el tema. Entiendo algo de programación, mayormente en python. Pero de c++ mis conocimientos son casi nulos.
Bien, al grano, descargue el código fuente, intente compilar desde GNU/Linux con el comando “i586-mingw32msvc-g++ -o ROPInjector.exe *.cpp “que para hyperion me funciono sin problemas pero en este caso fallo, no pude compilar ni con Dev C++, SharpDevelop 4.1, o el Visual Estudio 2010, me dan los siguientes errores:
'inicializando' : no se puede realizar la conversión de 'BYTE [1]' a 'char *' (C2440)
1741 : char *name = ((IMAGE_IMPORT_BY_NAME *)RVA_TO_PTR(thunk->u1.AddressOfData))->Name;

'strlen' : no se puede convertir el parámetro 1 de 'BYTE [1]' a 'const char *' (C2664)
1912: maxNameRVA += sizeof(WORD) + strlen(((PIMAGE_IMPORT_BY_NAME)RVA_TO_PTR(maxNameRVA))->Name); // include null terminator

'strncpy' : no se puede convertir el parámetro 1 de 'BYTE [1]' a 'char *' (C2664)
2067: strncpy(funcImpByName->Name, funcName, funcNameLen + 1);

Todos en: Patcher.cpp

De antemano muchas gracias si me pueden indicar la forma de corregir dicho error. Y felicitaciones por su excelente trabajo.

Entrada destacada

Infraestructuras Críticas y Sistemas Industriales: Auditorías de Seguridad y Fortificación de @0xWord

Desde hoy está disponible a la venta un nuevo libro de 0xWord centrado en la seguridad de los Sistemas Industriales y las Infraestructuras...

Entradas populares