sábado, 28 de noviembre de 2015

Antivirus K.O. Ordinal Numbers vs API Names

Como mola poner un título en inglés, y luego redactar el artículo en español. Sobre todo en estos tiempos en los que se puso tanto de moda el vender humo, ya hasta el que usa la palabra “postureo”, me incita a pensar que se junta con gente muy cool… ¡No lo soporto! ¡Dudo hasta de entrecomillar esas mierdas! ¡Puta invasión Hipster!

Hoy quería hablaros sobre un sapo que me he comprado, bueno, ya me pongo serio.

Existen varios métodos para evitar el tener que declarar un API en la Import Table de un binario, y sin embargo llegar a utilizarla. Métodos como Call API By Name, Call API By Hash, embeber una Shellcode suelen ser los más habituales. En el caso que expongo, el API se encuentra declarada, pero no con el nombre de la misma.

La idea que se me había ocurrido, trata de probar a llamar a las funciones que exportan las librerías, utilizando los números ordinales que las referencian, en lugar de a sus nombres. Este método por cuestiones de compatibilidad suele ser desaconsejado, ya que es posible que dependiendo del sistema operativo donde el binario se ejecute, pueda llegar a no funcionar. Esto existe sencillamente porque se encuentran multitud de funciones sin nombre, y esta sería la única forma de poder llamarlas. No obstante, podemos utilizar mi anterior método DAF para embeber las librerías que necesitemos en el sistema a modo Dropper, antes de ejecutar el malware en cuestión.

Para la prueba de concepto quería empezar con algo sencillo, aunque posiblemente muy detectado. Con lo que se me ocurrió generar el “stage 1”, la primera etapa de conexión del payload de Metasploit “reverse_tcp”.

Para la ejecución de la ShellCode, he compilado un binario desarrollado… ¿cómo no? en Visual Basic 6, para no perder la costumbre, mediante el uso de CallWindowProcA.

La herramienta Pestudio, abrirá el camino para identificar de forma rápida el número ordinal que utiliza en mi sistema la función CallWindowProcA de la librería user32.dll. La siguiente imagen muestra las APIs que esta librería exporta.

El número ordinal 1531 nos dará acceso a invocarla, con lo que realizaré los cambios en el código anteriormente utilizado para llamarla.

Tras comprobar ambos binarios, se muestra como se realiza la llamada en este caso. Algo físicamente más complejo de detectar que mi anterior publicación del Método Mmove, en el que se migraban los nombres de las funciones, a otros huecos.
Sencillamente declaramos la función con el número ordinal que hace referencia a la API en decimal.

Comprobando con Metasploit, si este último binario realmente funciona.

Ahora solo queda enviar las muestras a un Scanner Online.

¡Esto funciona muñeca! Como es lógico, algún antivirus debía de detectar la muestra, más que nada porque se encuentra la ristra de opcodes que forman el payload embebido sin ningún tipo de codificación o cifrado. Para evitar estas detecciones, lo más seguro es que bastase con darle uso a una herramienta como Abronsius Code Ofuscator, que utilicé anteriormente en la creación de 4n4lCrypter.

No podía dejar escapar esta oportunidad, para añadir una detección que saldrá en la próxima versión de 4n4lDetector, sobre este tipo de binarios compilados en Visual Basic x, que utilicen la invocación de las APIs mediante sus números ordinales.

¡Hasta aquí todo chahi piruleta! Pero realmente lo divertido, sería modificar un binario ya detectado del cual no tenemos acceso a sus fuentes, para llevar a cabo un limpiado de detecciones como venía haciendo tiempo atrás.

Así que como Visual Basic 6, internamente es un poco tedioso a la hora de hacer las llamadas a las APIs, ya que las carga de forma dinámica a través de otra función llamada DllFunctionCall. Me he pasado “temporalmente” a un lenguaje, el cual deja de lado las marranadas en su Import Table, Assembler.

Algo muy sencillo, un Downloader que utilizará tres APIs. La muy quemada URLDownloadToFile, ShellExecute y ExitProcess. ¡El trío de las blacklist!
Para el POC, he subido una calculadora de Windows a Google Drive.

Es salir de Visual Basic, y asombra lo maravilloso que es compilar binarios de 2KB… jajajaa

He vuelto a utilizar Pestudio para leer los ordinales de estas nuevas funciones, las cuales proceden de librerías diferentes.


La primera prueba la haré con URLDownloadToFile, así que vuelta a un editor PE. Ya saben que yo soy de utilizar LordPE, así que abriremos el binario con este, nos dirigiremos a su tabla de importaciones y le daremos a editar.


Eliminaremos los bytes del Hint y el nombre de la API, y agregaremos en ThunkValue el ordinal en hexadecimal, sumado a (0x80000000), con el cual se representa este tipo de dato.


Tras comprobar que este nuevo ejecutable funciona sin problemas, se realiza el envío de ambas muestras.

Jajajaa… a mí personalmente me hace gracia. No pude evitar ponerme algo de música, unas 10 horas de Vaina Loca, una hora por antivirus saltado con tal de evadirme.

Ya que estaba con el ritmo en las venas, decidí quitarme de encima también las declaraciones de ShellExecute y ExitProcess. Así que hice lo propio con LordPE. Una nota importante, tras revisar el binario modificado con este software, me di cuenta de que no realizaba el borrado completo del nombre de la función, sino que tan solo ponía a byte nulo el primero del nombre, evitando su lectura. No obstante, es sencillo terminar de dejarlo limpio con un editor hexadecimal.

Tras comprobar que el binario sigue cumpliendo con su función. Lo envío de vuelta al Scanner Online.


Dr. Web se baja del carro. Realmente los dos que quedan, es posible que utilicen alguna rutina de detección basada en la URL, con lo que seguro es bastante sencillo evitarles ofuscando la cadena.

Saludos 4n4les! ;)

11 comentarios:

  1. Llamar a la API por ordinal, con el nombre, con un hash del nombre o con ¿una shell? (que es eso de obtener la direccion de memoria de una funcion de una librería con una shell?) es lo mismo, solamente que se evita hardcodear los nombres de las APIs. Llamar por ejemplo a WriteProcessMemory en ejecucion termina siendo igual de detectable usando cualquier metodo.

    ResponderEliminar
    Respuestas
    1. Efectivamente, es más sencillo detectar el binario por comportamiento... pero prueba a utilizar un antivirus doméstico, no sé, Avira Antivir por ejemplo. Tiene buenas rutinas genéricas, pero en su mayoría se basa en detecciones por firmas y con poco que modifiques, se consigue evadir las condicionales. Si funcionase todo tan bien como dices, a día de hoy los trilladísimos RunPE, no tendrían nada que hacer.
      Saludos!

      Eliminar
    2. Es que ya no tienen nada que hacer. Es un método sobreexplotado en el 2006, Estamos a 2015. Si todo funcionara tan bien como decís, todo estaría super activo, pero si te fijas bien, esta todo super muerto, no sale malware nuevo, no infectan nada critico, ni siquiera copypastean zeus, etc.

      https://underc0de.org/foro/malware/los-crypters-genericos-ya-se-extinguieron/

      Eliminar
    3. Ya leí ese artículo anteriormente. Será que al ver cientos de muestras indetectables y nuevas al día, me causa estragos.

      Eliminar
  2. ta bueno hay que considerar las variaciones
    segun el sistema operativo

    ResponderEliminar
  3. Vamos por partes:

    Lo de que los crypters estan muertos..... estara muertos los tipicos en vb6 con el tipico runpe, pero hay un monton de nuevas familias de crypters y sino busca " Hallaj runpe" por poner un ejemplo.

    Y ahora mi duda existencial, lo de los ordinales no es generico, es decir en un win10 el CallWindowProcA es 1532, creo que en ejemplo es un win 7, como mejora yo le pondria una extraccion de los ordinales que se necesiten nada mas arrancar para hacerlo multi windows.

    ResponderEliminar
    Respuestas
    1. En este caso de CallWindowProcA, podríamos utilizar el ordinal 1532. Ya que en Windows 7 coincide con CallWindowProcW (su declaración en Unicode). La he comprobado y es funcional.

      http://s15.postimg.org/6lrjoyom3/image.png

      Se podría utilizar un Dropper o un Downloader, que identificase el sistema operativo antes de instalar el malware. Sería algo más sencillo.

      Saludos! :)

      Eliminar
  4. grande capo grande vomo

    ResponderEliminar
  5. Vamos Germán ánimo no dejes el blog! Ansío otro post tuyo para empaparme de sabiduría!!! Mil gracias!!!!

    ResponderEliminar