29 julio 2013

Funcionamiento de los 'crypters'



Tal y como avanzamos en el anterior post de esta serie sobre 'crypters', los Antivirus, en adelante AVs, escanean los archivos en el disco del ordenador y no en la memoria RAM y este comportamiento es el que aprovechan los 'crypters' para evadir la detección de los AVs. Veamos como lo hacen.

Cifrado

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'.

Cifrando malware

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'.

'Crypter' y 'stub'

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.


Crypter (malware) = Stub + [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. Trataremos este punto en detalle en el siguiente artículo de la serie.

Artículo cortesía de Abraham Pasamar

18 comments :

Galaxy dijo...

El 'crypter' es el conjunto de lo que se llama 'builder' (parte que lee /abre el malware, lo cifra, y lo une con el stub) y el 'stub'. Es un punto tonto, pero erróneo a mi vista

María García dijo...

Como se nota que es verano. Después de algunos artículos traumáticos, como el de Reversing Malware, por fin uno que puedo seguir sin tener que leerlo dos veces, je, je.
Me está gustando mucho la serie. Gracias por la contribución. :-)

Abraham Pasamar dijo...

Cierto, es más preciso que llamar 'crypter' al conjunto de builder y stub, lo que ocurre es que la costumbre es ponerle a los 'builders' (a las ventanas del programa, etc) 'crypter' tal o 'crypter' cual, y uno acaba llamando 'crypter' al builder. Pero técnicamente es más preciso lo que tú indicas.

Abraham Pasamar dijo...

Gracias, ese era uno de los objetivos de estos artículos, que se pudiesen entender sin abusar de tecnicismos y sin dar demasiadas cosas por sabidas.

goatsecloud dijo...

typedef LONG (WINAPI *MY_NtUnmapViewOfSection)(HANDLE ,PVOID ); //NtUnmapViewOfSection ntdll.dll

typedef LPVOID (WINAPI *MY_VirtualAllocEx)(HANDLE,LPVOID,SIZE_T,DWORD,DWORD ); // VirtualAllocEx
typedef BOOL (WINAPI *MY_WriteProcessMemory)(HANDLE,LPVOID,LPCVOID,SIZE_T,SIZE_T);// WriteProcessMemory
typedef BOOL (WINAPI *MY_GetThreadContext)(HANDLE,LPCONTEXT);//GetThreadContext
typedef BOOL (WINAPI *MY_SetThreadContext)(HANDLE,CONTEXT*); // SetThreadContext
typedef BOOL (WINAPI *MY_CreateProcess)(LPCTSTR ,LPTSTR ,LPSECURITY_ATTRIBUTES ,LPSECURITY_ATTRIBUTES ,
BOOL ,DWORD ,LPVOID ,LPCTSTR , LPSTARTUPINFO ,LPPROCESS_INFORMATION); // CreateProcess
typedef DWORD (WINAPI *MY_ResumeThread)(HANDLE); // ResumeThread

Gracias :D

iter dijo...

Buen articulo, bastante interesante, pero me surge una duda, si un crypter descifra y ejecuta el malware en memoria, el antivirus podría detectar el malware descifrado al revisar la memoria?

Juancho dijo...

Eso es detectable, al menos para el Eset :P

Pediculosysadmin dijo...

Consulta: entonces en memoria queda el malware cifrado y descifrado? o sólo es descifrado cuando al momento de la ejecución? Muchas gracias!

Abraham Pasamar dijo...

como comenté en el 1er. Post y he seguido insistiendo en este 2º, los AVs no escanean la memoria y en eso se basan los crypters. Si un AV dice: "escaseando memoria"...en realidad lo que quiere decir es: "mirando los procesos de la memoria, localizando los binarios que han arrancado esos procesos, escaneando los binaros EN EL DISCO"...y ya está,,,no hay más. Si esta descifrado en memoria y cifrado en disco....no es detectable (siempre que el stub esté "limpio").

Abraham Pasamar dijo...

el malware en memoria está descifrado, solo está cifrado en disco. Si por ejemplo la maquina reinicia, y el malware tiene persistencia mediante la correspondiente clave de registro / servicio, al arrancar el binario en disco (al que apunta la clave de registro) el stub hace su función, copia a memoria el malware cifrado, lo descifra y lo arranca SIN tocar el disco ... y ya está allí otra vez, en memoria y descifrado y sin que el AV lo haya localizado (repito, si el stub está "limpio").

Juancho dijo...

¿Cómo es esto posible? ¿No puede el AV leer el contenido del proceso? O sea, un OpenProcess y un ReadProcessMemory... por mi parte no lo veo muy complejo, aunque quizás ineficiente. ¿A qué se debe esto?

JesusDF dijo...

La ejecución de un programa cualquiera abarca varios pasos, hay una parte oculta para el usuario que es el traspaso del ejecutable desde el disco duro hasta la memoria RAM y el funcionamiento del loader de ejecutables PE que tiene Windows. En concreto se recorre la tabla IAT (Import Address Table) de la cabecera PE (Portable Executable) para cargar los módulos requeridos y rellenar los valores de las APIs que va a utilizar la aplicación y una serie de ajustes a mayores, además el sistema operativo define una región donde almacena información sobre los módulos que están cargados en memoria en dicho proceso, si está en depuración y demás.
Una vez el programa está listo para ser ejecutado, el loader inicaliza los valores de los registros de la CPU y pasa la ejecución al punto de entrada del ejecutable (EP - Entry Point), una vez ahí el programa toma el control y utilizando diversas APIs del sistema realiza su funcionamiento normal.
Un crypter/packer/loquesea lo que hace es introducir un trozo de código que modifica la memoria del ejecutable (no afecta a la copia que está en disco), actúa como un segundo loader preparando el código para que pueda ser ejecutado con normalidad. Por tanto, si el ejecutable tenía encriptada la sección de código (generalmente la sección .text), este código inyectado (en el artículo se refieren a él como STUB) desencriptará esta sección y acto seguido pasará el control de ejecución como si nada hubiera pasado.
El código que se ejecuta luego es lógicamente distinto del que está en disco, y a menos que haya sido ejecutado o que un antivirus haya reinterpretado el código como si estuviera en ejecución (o lo ejecute dentro de una sandbox o similar...) no se detectará como malware.
Este mismo código puede utilizar esa copia que está en memoria para reinsertarla en otro ejecutable, añadir el STUB y cambiar la clave de encriptación. Algunos incluso cambian el algoritmo en sí dinámicamente (lo que se conoce como polimorfismo).
No es que tenga mucha ciencia en sí, la verdad...

JesusDF dijo...

Sí, sí que puede leer la memoria del proceso y buscar mediante patrones, cadenas y referencias. Además los antivirus se ejecutan siempre en ring0 (mediante un driver del sistema se ejecutan con privilegios máximos) con lo cual pueden acceder a cualquier región de memoria.

Abraham Pasamar dijo...

Hola, gracias por los aportes, poder pueden acceder a memoria por supuesto, pero dime uno que lo haga, porque te aseguro que no he visto ninguno que detecte el malware en memoria si el crypter está limpio.

goatsecloud dijo...

seguro??? ^^

María García dijo...

Curioso. Si técnicamente es posible ¿por qué no lo hacen? ¿Algún problema de rendimiento, quizá?

Carlos dijo...

Yo me planteo la duda siguiente: si existen stubs populares que se suelan usar, los AV podrán detectarlos igualmente como código malicioso, aunque no se sepa cual es su payload, si esto es así, cómo se evita ?

Abraham Pasamar dijo...

Cuando un empresa de AV detecta o recibe una muestra de un potencial malware, tras realizar un examen del mismo y constatar que se encuentra ante un nuevo stub, busca partes características del mismo para establecer las denominadas "firmas" y así ese malware pasa a estar detectado por dicho AV. Cuando otros AV reciban muestras de este nuevo malware irán creando sus propias "firmas". Lo que se hace para para poder seguir utilizando dicho malware es sustituirlo el stub por otro indetectable, FUD. ¿Cómo se hace eso? pues hay dos vías básicamente, limpiándolo desde el código fuente y/o desde el binario. Un stub detectado ha de limpiarse y si se cuenta con el código fuente puede hacerse, parte del trabajo, desde allí, pero si solo se cuenta con el binario, debe hacerse la limpieza desde el mismo. Este proceso de eliminar las firmas del stub recibe el nombre de "modding" o "modeo" y hay un montón de técnicas que se pueden aplicar para eliminar diferentes firmas, pero me estoy adelantando y todo esto lo iremos viendo en los siguientes posts de la serie.