04 junio 2013

Reversing malware tales: Crypto-Reversing

En el capítulo anterior dejábamos el asunto en que los 'amables' secuestradores nos habían entregado una herramienta para descifrar los ficheros del rescate.

Hoy vamos a averiguar exactamente que es lo que hace esa herramienta, nuestro objetivo es averiguar todos los parámetros del cifrado (la clave, el algoritmo ...)

El programa es de muy fácil empleo y tiene una interface gráfica simple pero intuitiva


Antes que nada, y dado que el fichero es detectado como un troyano por muchos AVs, vamos a ver que opina BSA al respecto, solo nos detendremos brevemente, ahora el objetivo es otro, ya habrá tiempo de analizar las maldades.


Como se puede ver, BSA detecta cierta actividad digna de sospechar.

Vayamos hacia la parte criptográfica del asunto. En primer lugar vamos a usar OllyDbg para ver que funciones emplea para realizar el descifrado, con suerte puede que sea algo fácil de seguir.

 
¿Dije suerte? ¡ Con la CryptoAPI hemos topado ! Bienvenidos a un mundo de múltiples funciones y tipos de datos bastante esotéricos

En primer lugar, la función candidata a prestarle más atención es CryptImportKey como podemos ver en MSDN esta función hay que llamarla así:
A efectos de este análisis nos interesa -mucho- el campo *pbData ya que es lo que va a contener la clave y detalles como el algoritmo en cuestión.

Ese parámetro contendrá un 'BLOBHEADER' y el BLOB propiamente dicho. (un BLOB es, groso modo, un array de datos)

No obstante, vemos que ese BLOB puede ser de varios tipos, y algunos de ellos van cifrados, ahí entra en liza el parámetro hPubKey. Así que lo primero que nos interesa es ver como llama el programa a la función CryptImportKey, para eso vamos a usar API-MONITOR


Vemos que el parámetro no se usa (0x00000000) así que nos hemos quitado de golpe una complicación.

El segundo punto es averiguar el tipo de BLOB que le está pasando el programa a la función para poder parsearlo y extraer la información que nos interesa.

En este punto hay varios caminos a seguir, compartí el binario con Alberto Ortega y el encontró un camino diferente. Voy a explicar como lo hice yo (y si el se anima a explicar su método, le dejamos las puertas abiertas)

Para acceder a los datos de la función el camino que yo elegí fue usar API-hooking y forzar al programa a que llame a 'mi' CryptImportKey en vez de la oficial. De esa forma me enviaría a mi los datos y podría verlos en tiempo de ejecución.

Para esta labor, encontré MUY útil la herramienta WinAPIOverride, esta herramienta tiene una funcionalidad parecida a API-Monitor, pero además permite inyectar una dll en el proceso y sobre-escribir (override) cualquier función. Viene con un SDK que se integra en Visual Studio y ejemplos para hacer tu propia DLL.

Vamos a re-escribir la función CryptImportKey() haciendo que acepte el BLOBHEADER y el BLOB, abra un fichero y ponga en el la información de ese BLOB. El primer paso es analizar el BLOBHEADER

Tomando como referencia la estructura de un BLOBHEADER


Nos interesa bType (para saber el tipo de BLOB que está usando el programa) y aiKeyAlg para saber que algoritmo está usando

La nueva función CryptImportKey queda así:


Si todo va bien, cuando el programa llame a CryptImportKey, será redirigido a mCryptImportKey y esta función recibirá los datos, los analizará y volcara en el fichero dump.txt los datos del BLOB

Ejecutamos el binario desde WinAPIOverride con nuestra DLL:


Y vemos que se crea el fichero dump.txt con los siguientes datos:

Tipo de blob 0x08
Version 0x02
Algoritmo 0x00006610

Primera fase completada:

Tipo de Blob: PLAINTEXTKEYBLOB (0x08)
Algoritmo: AES (0x00006610)

Ahora que ya sabemos el tipo de BLOB que es y conocemos su estructura:


podemos analizarlo y obtener la clave. Para ello modificamos nuestra función mCryptImportKey de la siguiente forma:


Y con eso, haremos que vuelque en el fichero la longitud de la clave y la propia clave. Ejecutamos desde WinAPIOverride y obtenemos en dump.txt:

Tipo de blob 0x08
Version 0x02
Algoritmo 0x00006610
longitud de la clave 32
Datos de la clave (censurado)

Perfecto, ya sabemos el algoritmo AES, la longitud de la clave 32 bytes (que equivale a AES-256 bits) y la propia clave, solo nos queda saber el 'cipher mode' es decir, si está empleando CBC, ECB, CFB ...

Para averiguarlo, volvemos a la captura de Olly y en este caso nos interesa la función CryptSetKeyParam que es donde se determina la forma en la que se va a cifrar

De MSDN, nos quedamos con el parámetro KP_MODE del que podemos leer:


Y si vemos como se llama esta función desde API-Monitor:


Vemos que identifica el KP_MODE como 0x02 que, define el modo ECB como 'cipher mode'

Y con esto, concluye el análisis criptográfico del programa, hemos averiguado el tipo de algoritmo, la longitud de su clave, el método del cifrado y la propia clave en sí

24 comments :

Longinos Recuero Bustos dijo...

Uff Me tienes enganchadito Yago. La primera entrada estuvo bien, pero esta esta bien-bien. Esperando la próxima.

Saludos.

María García dijo...

Jolín. Me ha recordado aquel episodio en el que Sheldon da clases de física a Penny...
En el primer "palabro" (ollydbg) ya me he atascado y he tenido que recurrir a Google.
A ver si lo leo más despacito, cuando tenga un rato, para asimilarlo todo bien.
Muchas gracias por el post.

SiD dijo...

Mira que te lo pasas bien tú con estas cosas :-P

Didáctico análisis.

Alejandro Ramos dijo...

Enhorabuena, el articulo es genial

Yago Jesus dijo...

Buena suerte ! en el fondo como bien dices es cosa de tener tiempo para verlo

Yago Jesus dijo...

Tiene pinta de que usan http://msdn.microsoft.com/en-us/library/windows/desktop/aa379941%28v=vs.85%29.aspx para generarla, así que, ¿imposible?

Yago Jesus dijo...

Muchas gracias amigo ! El 'problema' de estos posts es que consumen una cantidad ingente de tiempo para prepararlos y al final resultan los menos vistos / comentados en favor de otros temas / conceptos :/

David dijo...

Mmm me parece muy raro. Como he visto el CryptImportKey me he imaginado que importaria una llave publica, que seria usada para genenrar llaves AES para los ficheros. De esta manera el caco solo neceista guardar su clave privada. No se requiere comunicación trojan - caco.
Oye si te animas cuelga el file y le echamos un vistazo!

David dijo...

Me respondo a mi mismo. Esto es exactamente lo que tenía en mente: http://www.cryptovirology.com/cryptovfiles/newbook/Chapter2.pdf
Como indica, el trojan lleva como payload la clave publica, con la que encripta claves random para el cipher simetrico (en el paper hablan de triple DES, en tu caso AES256).
Un saludo!

Yago Jesus dijo...

Es un poco lo que comentaba en el primer post, la clave se genera en el pc infectado, se cifra con la public RSA y va al fichero how to decrypt.txt de ahí extraen la master-key y generan el 'descifrador'.


Por motivos de privacidad no puedo facilitar el programa :(

Napaboy dijo...

Me quedó la duda sobre lo de Keylogger, y las otras maldades que posiblemente haga. Es decir ¿aún pagando y desencriptando la información seguirán atacando y robando las contraseñas con el Keylogger?

Uat dijo...

Supongo que estos posts son los menos leídos por ser los más técnicos, pero desde luego a mi me resultan los más interesantes.
Muchas gracias y enhorabuena por este post.

Fernando Núñez dijo...

¡Sois unos malditos genios!

ping dijo...

Pues que pena (que sean menos vistos y/o comentados) porque este post es excelente.

Yago Jesus dijo...

Tiene pinta de que el programa no es confiable. Es lo que tiene tratar con gente en la que no se puede confiar

Yago Jesus dijo...

Muchas gracias, al final es una cuestión de tiempo, hacer la investigación y documentarla consume bastante y si encima no genera mucha respuesta, terminas por desalentarte un poco

Yago Jesus dijo...

Muchas gracias !, supongo que sí, al final hay que digerirlos lentamente y con tiempo, lo que a no todo el mundo le apetece

María García dijo...

Claro, es cuestión de tiempo. Cada uno a su ritmo. Como dijo Sheldon a Penny: "No hay por qué frustrarse, la gente aprende a velocidades diferentes. A diferencia de los cuerpos cayendo en el vacío".
Una vez leído despacito, se entiende bien. Pero no me pidan que lo repita yo.

Pues ya ves que has generado bastante respuesta y que no tienes motivo para desalentarte. :-)

Alberto dijo...

Juer que jaleo para simplemente ver que parámetros se pasan a la función!!


No hubiese sido inmediato poner un BP justo cuando se llama a esa función y ver todos los parámetros en claro en la pila??? El tiempo de hacer eso son 5 segundos (poner el BP y dar a F9).


Me estoy perdiendo algo?
Un saludo

Yago Jesus dijo...

Yo creo que si, los parámetros no son tipos de datos 'fáciles', de hecho lo que tendrías es un BLOB + BLOGHEADER (si pones el bp en cryptimportkey) y de ahí tendrías que buscarte la vida para deducir que es cada cosa.



Las siguientes partes, se ha hecho como dices, pero con API Monitor para capturar las llamadas

Denis dijo...

Me saco el sombrero ante Usted señor.

alberto dijo...

Distintas formas de hacer lo mismo ;) Es lo bonito de la informática
Un saludo

h0f dijo...

Muy muy bueno. Malware avanzado, esto me recuerda al reto de Ripe de romper un binario cifrado con RSA que si no me equivoco nadie fue capaz de romperlo.

Antonio Rodríguez dijo...

Buena entrada Yago. Se que consume mucho tiempo escribir este tipo de cosas, pero a la larga son las más interesantes y útiles. No hay que pensar mucho en que sean poco vistos, ya que quedan "ahí en internet" como referencias para el futuro; mientras que otras entradas más generales tienen un interés más inmediato, pero son mucho más efímeras.
Enhorabuena.