Todavía quedan muchos misterios alrededor de Gauss y Flame. ¿Cómo se infecta la gente con este malware? ¿Cuál es el propósito de la fuente “Palida Narrow” que Gauss instala en los equipos infectados?
Pero tal vez uno de los misterios más interesantes es la “carga útil” codificada de Gauss. Gauss contiene un módulo llamado “Godel” con una “carga útil” codificada. El malware trata de decodificar esta carga usando muchas cadenas de caracteres del sistema y, cuando lo logra, la ejecuta. Aunque nos esforzamos, no pudimos romper su codificación. Por eso hoy presentamos toda la información disponible sobre la “carga útil”, con la esperanza de que alguien más pueda encontrar una solución y liberar sus secretos. Pedimos a las personas interesadas en criptografía y matemáticas que se unan para resolver el misterio y extraer la “carga útil” escondida.
Los contenedores
Los dispositivos USB tienen dos archivos con muchas secciones codificadas. Se llaman “System32.dat” y “System32.bin” y son las versiones de 32-bit y 64-bit del mismo código. Estos archivos se cargan desde discos infectados usando el conocido exploit LNK que introdujo Stuxnet. Su meta principal es extraer mucha información sobre el sistema de la víctima y escribirla en un archivo que se guarda en un disco llamado “.thumbs.db”. Muchas versiones conocidas de estos archivos contienen tres secciones codificadas (una sección de códigos y dos de datos).
La llave de decodificación de estas secciones se genera de forma dinámica y depende de las características del sistema de la víctima, para que nadie, excepto los objetivos designados, extraiga los contenidos de las secciones.
Por cierto, a la versión de 64 bits del módulo le queda algo de información de depuración. El módulo contiene cadenas de caracteres de afirmación de depuración y nombres de los módulos:
.loader.cpp
NULL != encSection
Path
NULL != pathVar && curPos < pathVarSize
NULL != progFilesDirs && curPos < progFilesDirsSize
NULL != isExpected
NULL != key
(NULL != result) && (NULL !=str1) && (NULL != str2)
.encryption_funcs.cpp
Los datos
Los misteriosos datos codificados se guardan en tres secciones:
Los archivos también contienen el recurso codificado “100”, que parece ser la “carga útil” en sí, a juzgar por el tamaño relativamente pequeño de las secciones codificadas. Lo más probable es que la sección “.exsdat” contenga el código para decodificar el recurso y ejecutar sus contenidos.
El algoritmo
El código que decodifica las secciones es muy complejo comparado con las rutinas regulares que solemos encontrar en los programas maliciosos. Esta es una descripción breve del algoritmo:
Validación
1. Realiza una lista de todas las entradas desde GetEnvironmentPathW(“Path”), divididas por un separador “;”
2. Anexa la lista con todas las entradas que devuelve FindFirstFileW / FindNextFileW según la máscara “%PROGRAMFILES%*”, donde cFileName[0] > 0x007A (UNICODE ‘z’)
Nota: en esencia, esto significa que el programa específico que se instala en “%PROGRAMFILES%” tiene un nombre que comienza con un carácter especial como “~”, como en nuestro ejemplo, o utiliza una tabla de caracteres especiales UNICODE, como árabe o hebreo, donde todos los caracteres son mayores que 0x007A.
3. Realiza todos los pares posibles con las entradas de la lista resultante.
4. para cada par,anexa la primera sal de 16 bytes en el código fuente (hardcoded) y calcula el hash MD5.
5. Calcula el MD5 desde el hash (es decir, hash = md5(hash) ), 10.000 veces.
6. Compara si el hash MD5 coincide con el valor hard-coded. Si no, se retira.
Decodificación
Las secciones se decodifican en el siguiente orden: .exsdat, .exrdat, .exdat
1. Utiliza el par PATH/PROGRAMFILES que se usó para generar el hash MD5 previsto en la validación del código de arriba.
2. Anexa el par con la segunda sal hard-coded de 16 bytes y los bytes 0x15 y 0x00
3. Calcula el hash MD5 desde el búfer resultante.
4. Calcula el hash MD5 desde el hash (es decir, hash = md5(hash) ), 10.000 veces.
5. Deriva la llave RC4 del hash resultante usando el CryptDeriveKey de WinAPI (hProv, CALG_RC4, hBaseData, 0, &hKey).
6. Decodifica la sección (RC4), tratando su primer DWORD como la longitud del búfer a decodificar y el búfer codificado que comienza en offset 4 de la sección.
7. Compara DWORDs en el búfer decodificado en posiciones 0 o 7 con el valor mágico “0x20332137”. Continúan sólo si alguna de las DWORDs coincide.
8. Aumenta 1 a la última WORD en el búfer par+sal (el que al principio se fijó en 0x0015).
9. Decodifica otra sección, ve a 3.
Después de que se decodifican todas las secciones : llama a la función al principio de la sección exsdat.
Datos de muestra para validar el algoritmo:
El par de cadenas de caracteres se crea entrelazando las secuencias. Las secuencias y el búfer sal no están separados por ningún carácter.
Cadena de caracteres de muestra, Unicode (sin comillas):
- “C:Documents and SettingsjohnLocal SettingsApplication DataGoogleChromeApplication”
- “~dir1”
Primera sal, volcado hexadecimal: 97 48 6C AA 22 5F E8 77 C0 35 CC 03 73 23 6D 51
MD5 en el paso 6 de validación: 76405ce7f4e75e352c1cd4d9aeb6be41
Segunda sal, volcado hexadecimal: BB 49 4E 77 F9 25 EE C0 3B 89 FC ED C2 22 4A 21
MD5 en el paso 5 de la decodificación: 00916031b3e9513044436ee42b6aa273
¡Únete a la misión!
Hemos probado millones de combinaciones de nombres conocidos en %PROGRAMFILES% y Path, pero sin éxito. La revisión del primer carácter de la carpeta en %PROGRAMFILES% indica que los atacantes buscan un programa muy específico con el nombre escrito con caracteres extendidos, como árabe o hebreo, o alguno que comience con un símbolo especial como “~”.
Por supuesto, es obvio que no es posible romper la codificación con un simple ataque de fuerza bruta. Pedimos a todos los interesados en romper el código y descubrir la misteriosa “carga útil” que se unan a nosotros.
La sección de recursos es bastante grande como para contener un código de ataque dirigido SCADA como el de Stuxnet, y todas las precauciones que tomaron los autores indican que el objetivo de los ataques es muy importante.
Ofrecemos los primeros 32 bytes de datos codificados y hashes de variantes conocidas de los módulos. Si eres un criptógrafo reconocido mundialmente o puedes ayudarnos a decodificarlos, por favor escríbenos a: theflame@kaspersky.com.
Datos de la fuente
Entregamos hasta 32 bytes del principio de cada sección codificada, excepto el DWORD que contiene la longitud del búfer codificado. Por favor escríbenos a theflame@kaspersky.com si necesitas más datos codificados.
Muestra | 56e4fb972828fafbbdc11158a1b5fa72 |
Salt 1 | 97 48 6C AA 22 5F E8 77 C0 35 CC 03 73 23 6D 51 |
Reference MD5 | 758EA09A147DCBCAD6BD558BE30774DE |
Salt 2 | BB 49 4E 77 F9 25 EE C0 3B 89 FC ED C2 22 4A 21 |
Exsdat | 4C CC BA E2 E0 BA 2E 44 C7 60 17 9A 72 F4 2F 27 DD FD DB 11 03 94 E3 4B 0A 16 66 F3 36 97 6C D8 |
Exdat | B8 EB 6D 61 2B 4F 70 65 75 A2 1C 03 1C DF 26 2F |
Muestra | 695056ffacef1fdaa326d7c8bb0f88ba |
Salt 1 | 6E E3 47 2C 06 A5 C8 59 BD 16 42 D1 D4 F5 BB 3E |
Reference MD5 | EB2F172398261ED94C8D05216650919B |
Salt 2 | 8F 42 B5 87 E8 9A B2 32 C8 1C 1A EC B5 2D 55 19 |
Exsdat | CE 31 D0 5D 7D CB 57 9A 83 06 09 8D 42 2B 44 34 24 13 B2 39 22 48 8F F3 76 E5 9C DA 87 8F BC 42 |
Exdat | 9D 5B B8 3B B2 17 00 DC 76 81 1D 4E 54 80 9B 31 |
Muestra | 089d45e4c3bb60388211aa669deab26a |
Salt 1 | 0E A5 01 D1 24 71 CD CD 0E 9E AC 6E 48 5A F9 32 |
Reference MD5 | 52DD4D6B792D84C422E6A08E4272ACB8 |
Salt 2 | 38 F9 A6 5B 82 08 E7 61 1D 10 73 53 50 BC B4 F0 |
Exsdat | D3 CA 9D 9F 87 FB 25 43 7E C6 57 7C D9 06 10 8D D2 5B B2 88 18 6E FD B4 C4 30 12 2E 1E EC E0 64 |
Exdat | F6 C9 81 C9 86 27 16 0C B7 33 93 AB 3E 71 5B E2 |
Muestra | 8d90e3c68030fbb91ad5b920d5e17b32 |
Salt 1 | C3 23 4D 51 5D 52 A5 8E 81 46 FA 8A 6D 93 DF 7D |
Reference MD5 | 53B3FAEA53CC1B90AA2C5FCF831EF9E2 |
Salt 2 | 21 9D 04 35 7B 96 74 53 B0 9C CD 7F 2F E6 63 AA |
Exsdat | AB 01 6A 8E 42 F0 F2 92 1D F1 4A 42 01 63 72 78 D6 F7 A5 0C 54 37 21 2C B8 59 6A D0 7E 68 19 2D |
Exdat | 55 A7 F3 93 E0 AF 5B 7E 17 22 7E 82 8A 6F 25 21 3D 64 D7 E8 |
El misterio de la “carga útil” codificada de Gauss