Bypass de Antivirus: El arte oscuro de la evasión

Excelente articulo que he extraido y adaptado de http://www.securitybydefault.com 

"Para evadir la detección de malware por parte de los programas Antivirus, en adelante AVs, se utilizan diferentes técnicas, una de ellas es el uso de 'crypters'. Éstos permiten cifrar cualquier archivo binario para hacerlo 'invisible' a los AVs.
Los 'crypters' son usados por los delincuentes para evitar la detección de los AVs e infectar los ordenadores, llevando a cabo todo tipo de tropelías, pero también pueden ser utilizados, entre otros casos, en el contexto de una auditoría de seguridad.
En definitiva, si queremos asegurarnos de volver 'indetectable' un determinado binario que es detectado por multiples AVs, necesitamos un 'crypter' indetectado o FUD (Full UnDetectable).

Hay que puntualizar que en algunos entornos se habla indistintamente de 'crypters' y 'packers', pero en realidad son cosas distintas. El objetivo de un packer es 'empaquetar' o 'comprimir' el archivo ejecutable. Sería como usar un ZIP pero sin perder la estructura de un archivo ejecutable PE (Portable Executable). El objetivo del 'crypter' es 'cifrar' el ejecutable. Sería como usar PGP o TrueCrypt, pero sin perder la estructura PE.

En lo que sigue vamos a centrarnos en el explicar qué son y cómo funcionan los 'crypters', pero antes debemos entender de forma básica cómo funcionan los AVs. Éstos, son cada vez más sofisticados y utilizan todo tipo de técnicas para identificar el malware, entre estas técnicas destacan dos: las firmas binarias y las firmas heurísticas.

Las primeras buscan secuencias de bits características del malware previamente identificado. Es decir, buscan secuencias de bits, a modo de patrón, de aquel malware que haya pasado por el laboratorio de la empresa de AVs. Es decir, que en algún momento del tiempo, en la empresa de AV han recibido una muestra del malware para analizarlo y una vez identificado como malicioso han fijado o definido un patrón característico que constituye la firma binaria del mismo. 

En definitiva, un malware totalmente nuevo, recién 'codeado', difícilmente será detectado por este tipo de firmas. Para poder anticiparse y detectar malware que no haya sido analizado previamente, existen las denominadas firmas heurísticas. Básicamente lo que hacen es detectar elementos que típicamente forman parte de los programas maliciosos, como el uso de determinadas funciones, algoritmos de cifrado, etc. Mediante estás técnicas, es posible detectar de forma anticipada malware 'nuevo', pero, además de ser más compleja su implementación y consumir más recursos del sistema que las firmas convencionales, también implican un mayor nivel de riesgo debido a la detección de falsos positivos.
Las tareas de análisis o escaneo de los archivos binarios son realizadas por los AVs a nivel de disco, no en la memoria RAM. Cuando un AV nos indica que está escaneando la memoria, lo que está haciendo realmente es buscar el binario en disco que arrancó un determinado proceso que en ese momento está ejecutándose en la memoria RAM y una vez ha localizado el mismo, escanea dicho binario (en el disco) en busca de firmas de malware. Así es como funcionan los AVs, escanean los archivos en el disco y los 'crypters' basan su existencia en este principio básico.
 
Un 'crypter' es un conjunto compuesto por un elemento habitualmente denominado también 'crypter', aunque sería más correcto designar como 'builder' y otro elemento conocido como 'stub'. El 'builder' es una parte del código relativamente sencilla, pues se encarga de conformar un ejecutable compuesto por el 'stub' y el 'malware cifrado'. El 'stub' es algo más complejo, pues se encarga de descifrar el 'malware cifrado' y, sin tocar el disco, arrancar el 'malware descifrado' directamente en memoria.

¿Cómo consigue el 'stub' arrancar el 'malware cifrado' directamente en memoria sin que este toque el disco?. Para ello, el 'stub' utiliza una técnica o procedimiento llamada 'Dynamic Forking' o 'RunPE'. Está técnica es muy antigua, pero sigue siendo totalmente válida y funcional a día de hoy.


Uno de los objetivos que me marqué al comenzar a escribir los artículos de esta serie sobre 'crypters' era que fuesen sencillos de entender por todos los lectores y no solo por aquellos que tienen conocimientos avanzados de malware y reversing. Por ello, voy a explicar los aspectos más importantes de la técnica 'Dynamic Forking' o 'RunPE' de forma sencilla, sin abusar de tecnicismos. Si alguno quiere profundizar en ella solo tiene googlear un poco y encontrará múltiples descripciones técnicas de la misma. En la imagen que he preparado con los pasos del proceso puede verse un mayor nivel de detalle.
Una vez el 'stub' se ha ejecutado, lo primero que suele hacer es localizar dentro del binario el 'malware cifrado', a continuación localiza la clave de 'cifrado/descifrado' e inicia el proceso de descifrado del 'malware' en memoria. Acto seguido, el stub arranca un segundo proceso, de si mismo o de un ejecutable cualquiera del sistema, es indiferente. Pero lo hace invocándolo con una propiedad denominada CREATE_SUSPENDED. Con ello lo que se consigue es cargar en memoria dicho ejecutable y los datos  de contexto necesarios para su ejecución, pero no llega a arrancarlo, está 'suspendido'. A continuación, a partir de la dirección de memoria donde se encuentra la cabecera y secciones del proceso suspendido, sobrescribe éstas con las del ejecutable malicioso ya descifrado que tiene en memoria. A partir de ahí, obtiene los datos de contexto del archivo suspendido y los sustituye por los datos del nuevo ejecutable, el malware. Estos datos son básicamente la dirección base y el punto de entrada del nuevo ejecutable (EP: Entry Point). Por último, relanza el proceso suspendido, consiguiendo que se ejecute el archivo malicioso en lugar del ejecutable suspendido invocado inicialmente. Así de simple y así de elegante.

La idea básica que subyace en el concepto de 'crypter' es la siguiente: si se cifra un archivo malicioso, éste será transformado en un archivo 'ininteligible' para el AV y por tanto no será detectado. Lo cual es cierto, pero claro, existe un pequeño problema, y es que el archivo malicioso cifrado no funciona, no puede ejecutarse, así que es necesario encontrar una solución, una técnica que se encargue de descifrar y ejecutar el archivo malicioso. Esta pieza de software se denomina 'stub'.

Los 'crypters' utilizan técnicas de 'cifrado' para ocultar los archivos maliciosos. Repasemos rápidamente en qué consiste un cifrado. Un cifrado es un procedimiento que utiliza un algoritmo y una clave para transformar un mensaje legible en otro indescifrable.

Veámoslo con un ejemplo: vamos a 'cifrar' el mensaje "HOLA" con el algoritmo de cifrado ROT  (también conocido como cifrado César) y la clave de cifrado será "1". Este algoritmo lo que hace es, para cada caracter del alfabeto, avanza tantas posiciones como el valor de la clave de cifrado establecida, en este caso "1". Así pues, tras aplicar el algoritmo, la letra "A" se transforma en la "B", la "B" en
la "C" y así sucesivamente. Por tanto el mensaje "HOLA" se transforma en "IPMB". De este modo hemos ocultado nuestro mensaje y para que alguien pueda descifrarlo, necesitará conocer tanto el algoritmo empleado (ROT) como la clave de cifrado (1). Obviamente este es un algoritmo muy sencillo y una clave igualmente sencilla, lo cual permitiría llevar a cabo ataques con el propósito de deducir el algoritmo y la clave, sin embargo, existen infinidad de algoritmos de cifrado enormemente complejos que pueden utilizarse y son utilizados para cifrar 'malware'.


Por regla general un 'crypter' consiste en dos elementos: el 'crypter' y el 'stub'. Esta última es la pieza más importante del conjunto.  

El 'crypter' consiste generalmente en un programa que permite buscar y seleccionar en el sistema de archivos del ordenador el ejecutable a cifrar (generalmente un archivo malicioso, pero es posible cifrar cualquier archivo que se desee). Algunos, permiten adicionalmente introducir la contraseña de cifrado de forma manual o generarla aleatoriamente. Y en ocasiones, algunos permite activar cierta medidas anti-forenses, pero esto es otra historia que trataremos más adelante.

Una vez seleccionado el archivo a cifrar y pulsado el botón de 'cifrar' (Build en el ejemplo de la imagen) nos generará un 'nuevo ejecutable', el cual en realidad consiste en una composición del 'stub' y un 'payload', que no es más que el malware cifrado.


Como puede observarse, 'crypter' y 'stub' están relacionados, ya que el 'crypter' se encarga de ejecutar el algoritmo de 'cifrado' y el 'stub' se encarga de ejecutar el algoritmo de 'descifrado'. Para que el 'stub' pueda descifrar el malware necesita conocer la clave utilizada en el proceso de cifrado. En algunos casos, el programador del 'crypter' no da opción al usuario a elegir una clave, sino que la ha definido de antemano en su código, y en otras sí permite elegirla o generarla aleatoriamente, en cualquier caso, al generar el 'nuevo ejecutable' el 'crypter' ha de almacenar la clave en el algún lugar para que el 'stub' pueda encontrarla y descifrar el malware.

Si se observa en detalle este 'nuevo ejecutable', lo que vemos es una configuración bastante habitual, en la que tras el archivo ejecutable que constituye el 'stub', se añaden unos separadores de delimitan el lugar en el que se encuentra la almacenada la clave y a continuación se añade el malware cifrado. Obviamente cada programador puede organizar esta distribución como más le guste y en ocasiones, en lugar de añadir directamente el malware cifrado tras el stub, lo introducen en un recurso del ejecutable  PE.
Cuando este 'nuevo ejecutable', valga la redundancia, es ejecutado, el 'stub' se encarga de copiar a la 'memoria RAM' el malware cifrado, descifrarlo allí mismo, y a continuación ejecutar dicho 'malware' ya descifrado."


Después de leer este gran articulo de SecurityByDefault os dejo con una prueba de concepto donde se demuestra que dichas técnicas se usan y son efectivas aun a dia de hoy y para muestra este encriptador que he programado: