Cómo la ingeniería inversa (y los fallos de los cibercriminales) puede ayudarte si has sido víctima de un ransomware
Un ransomware (del inglés ransom, «rescate», y ware, acortamiento de software) es un tipo de programa dañino que restringe el acceso a determinadas partes o archivos del sistema infectado pidiendo un rescate a cambio de eliminar esta restricción. En los últimos dos años, los ataques de este tipo de malware han aumentado exponencialmente, ya que se trata de un código dañino muy efectivo y que no requiere de grandes conocimientos para llevarlo a cabo.
Acceder al código fuente de un malware de este tipo es relativamente sencillo, dado que hay gran cantidad de pruebas de concepto (POC) disponibles en Internet[1][2] e, incluso, han surgido a lo largo del tiempo diferentes plataformas, conocidas como Ransomware as a Service (Raas), que ofrecen ese tipo de servicios como, por ejemplo, Gandcrab. Este es un modelo de suscripción donde los cibercriminales que se suscriben obtienen las herramientas necesarias para llevar a cabo un ataque de este tipo sin necesidad de preocuparse por la programación del mismo.
Cabe mencionar que estos ataques, como ya sucedió con los recordados Petya y Wannacry, han causado estragos en todo el mundo. Sin embargo, los desarrolladores de estos códigos maliciosos no siempre son tan de profesionales y, en algunos casos, pueden cometer algún fallo que permite la recuperación de los ficheros secuestrados sin necesidad de pagar el rescate solicitado a las víctimas.
Eso mismo es lo ocurrido con el ransomware Whiterose. Este ransomware fue descubierto por los investigadores de la cuenta de Twitter @MalwareHunterTeam el día 3 de abril de 2018 y era propagado de forma manual vía Remote Deskotop (RDP) en sistemas con credenciales débiles o predecibles, centrándose principalmente en sistemas españoles[3].
El binario que compartieron los investigadores venía identificado por la función hash SHA-1 0d642ea85680b932e6dd45620c9c12d1060b46fd y era un binario con formato Portable Executable (PE) para sistemas Windows de 32 bits creado con el framework Microsoft .NET. La particularidad que tienen los programas creados con este framework es que, con las herramientas adecuadas, es posible acceder al código fuente original desarrollado por el creador. Es por esto que surgen diferentes aplicaciones para intentar proteger los binarios y dificultar que se pueda acceder a su código. En este caso, el malware estaba protegido con el software Confuser[4].
No obstante, sigue siendo posible recuperar el código original. Para ello, basta con establecer un punto de ruptura en el flujo del programa en su función gchandle.Free(). Tras ejecutarlo y alcanzar este punto, aparece en la memoria del proceso el binario original.
Ilustración 1. Extracción del binario del ransomware original antes de ser protegido con Confuser.
La estructura del código fuente de este ransomware es bastante parecida a la de otras familias como InfiniteTear, BlackRuby o Zenis, reforzando la teoría de la compartición de código, en muchos casos público, en este tipo de malware.
Entre las clases del programa se encuentra una llamada Configuration con determinados aspectos de configuración, como la clave pública de los cibercriminales utilizada para cifrar con el algoritmo RSA la contraseña de cifrado de los ficheros, la extensión a añadir a los ficheros cifrados y el nombre de fichero, y texto de la nota de rescate.
La primera acción que realiza la rutina principal del malware es calcular la clave a utilizar en el proceso de cifrado de los ficheros.
Ilustración 2. Función de generación de cadenas de caracteres "aleatorias"
La peculiaridad de este código reside en que durante el proceso de cifrado de los ficheros, por cada uno de ellos, vuelve a ser utilizada esta función para generar una cadena de caracteres que utilizará para renombrar el fichero cifrado, guardando el nombre original al final del fichero, antes de que este sea cifrado, para poder restaurarlo posteriormente cuando se pague el rescate.
Ilustración 3. Generación del nuevo nombre del fichero cifrado
Prestando atención al código del método RandomString se aprecia la utilización de la función Random() de .NET. Este tipo de funciones, conocidas como PsudoRandom Number Generator (PRNG), implementan algoritmos que generan números suficientemente aleatorios basándose en tres variables principales:
- Seed: Valor inicial que determina el punto de partida del PRNG.
- Estado: Propiedades internas del PRNG que, conociendo el estado, pueden determinarse los valores previos y los siguientes.
- Periodo: Valor que determina el número de salidas del algoritmo antes de que vuelvan a repetirse las mismas salidas.
Por tanto, dos PRNG con el mismo estado interno generan la misma secuencia de números.
Ilustración 4. Programa Python donde se comprueba que la salida del PRNG, dado un mismo seed, es también la misma.
Si se revisa el código interno de la función Random() en la implementación de .NET, se puede observar que esta utiliza como seed un valor denominado Tickcount[5], el cual representa el número de segundos transcurridos desde que el Sistema Operativo se reinició por última vez. Según la propia documentación de Microsoft[6][7], el valor de esta variable itera en ciclo entre Int32.MinValue, que es un número negativo, hasta Int32.MaxValue, cada 49.8 días. No obstante, la función Random() únicamente se queda con el valor absoluto de esta variable.
El problema consiste en obtener un valor secreto generado por un PRNG (la clave de cifrado del ransomware). En este caso, debido a la peculiaridad comentada, es posible observar una salida del PRNG (nombre de fichero generado por el mismo algoritmo). Por tanto, si se averigua el estado del PRNG para ese caso, es posible predecir salidas previas o posteriores. Este problema es explicado con más detalle en un documento de Insomnia Sec[8].
La herramienta Untwister[9], desarrollada en 2014 por Bishop Fox, permite averiguar mediante “fuerza bruta” el valor de seed que ha generado una secuencia determinada. Para ello, únicamente hay que indicarle el PRNG, el intervalo de posibles salidas (la longitud del conjunto de caracteres utilizado) y la propia secuencia.
Volviendo al caso del ransomware, lo que interesa obtener es alguno de los primeros ficheros que se cifraron en el equipo (por ejemplo, el fichero más antiguo con extensión .WHITEROSE) y sustituir cada uno de los primeros 16 caracteres por su posición dentro del conjunto de caracteres de la función RandomString.
Ilustración 5. Conjunto de caracteres de la función RandomString y su posición
Si, por ejemplo, se toma el fichero j6GEP2bOoAyQyXeK_ENCRYPTED_BY.WHITEROSE se realizaría la siguiente asignación:
De tal forma que llamando al programa Untwister con estos parámetros, se obtendría el valor del tickcount en el momento en que se cifró este fichero: 679296.
Ilustración 6. Ejecución del programa Untwister.
La clave de cifrado debió ser calculada unos instantes antes, por tanto, bastaría con ir probando secuencialmente valores de tickcount superiores e inferiores a este, generar cadenas de caracteres de longitud 48 con la misma función y probar a descifrar el fichero con la función inversa a la programada por los cibercriminales en el proceso de cifrado. Para ello, hay que recordar que, en caso de que la clave sea la correcta, debería aparecer el nombre del fichero original al final del contenido del mismo.
Ilustración 7. Sustitución en la función de cifrado AES para que descifre.
Este proceso se resumiría al siguiente código .NET:
Tras, apenas un segundo, se obtiene la clave con la que se cifró el fichero:
Y, tras esto, únicamente habría que crear un programa que descifre todos los ficheros con esta clave, de igual forma que los cifró. Un software parecido a este sería el que enviarían los cibercriminales a las víctimas que pagaran el rescate.
Os dejo los enlaces de referencia para que investiguéis vosotros mismos.
[1] https://github.com/goliate/hidden-tear
[2] https://github.com/graniet/fsociety-ransomware-MrRobot
[3] https://www.bleepingcomputer.com/news/security/the-whiterose-ransomware-is-decryptable-and-tells-a-strange-story/
[4] https://archive.codeplex.com/?p=confuser
[5] https://referencesource.microsoft.com/#mscorlib/system/random.cs,52
[6] https://referencesource.microsoft.com/#mscorlib/system/environment.cs,265
[7] https://docs.microsoft.com/es-es/dotnet/api/system.environment.tickcount?view=netframework-4.7.2
[8] https://www.insomniasec.com/downloads/publications/Not So Random - Exploiting Unsafe Random Number Generator Use.pdf
[9] https://github.com/hyprwired/untwister