Recuperar stack strings y cadenas decodificadas del malware
Por qué el malware oculta sus cadenas, cómo funcionan las stack strings, tight strings y cadenas decodificadas, y cómo la emulación las recupera sin ejecutar nada.
En resumen. La extracción de cadenas simple solo encuentra el texto que está tal cual en el archivo. El malware suele ocultar sus cadenas interesantes — direcciones C2, nombres de mutex, comandos — construyéndolas en la pila o decodificándolas en ejecución. Emular el código que las construye recupera la mayoría sin ejecutar la muestra. El PE Parser lo hace en su pestaña Análisis de código, en la línea de FLOSS de Mandiant.
Lo que strings ve y lo que no
Una extracción de cadenas recorre el archivo buscando secuencias de caracteres imprimibles (ASCII, UTF-16). Es rápida y encuentra mucho: nombres de importaciones, mensajes de error, rutas, URL en claro. Justamente por eso los autores ocultan las cadenas que importan. Tres técnicas cubren casi todo:
- Stack strings. El código escribe los caracteres uno a uno en un búfer local:
mov byte [ebp-0x20], 'h',mov byte [ebp-0x1f], 't'… El texto solo existe en memoria, mientras dura la función. En el archivo se ve una serie de instrucciones, no una cadena. - Tight strings. Una stack string a su vez codificada y luego decodificada por un bucle corto en la misma función — normalmente un XOR con una clave constante — justo antes de usarla.
- Cadenas decodificadas. Las cadenas se guardan cifradas en la sección de datos y una función de decodificación las pasa a texto cuando hace falta. Se llama desde muchos sitios, cada vez con un bloque cifrado distinto, y devuelve o escribe el texto en claro.
Las tres burlan la extracción estática, y las tres son visibles para quien siga lo que hace el código.
Cómo las recupera la emulación
Un emulador es una CPU escrita en software: lee cada instrucción, actualiza registros y memoria simulados y pasa a la siguiente. Nada llega al procesador real ni al sistema operativo — las llamadas a funciones de Windows reciben respuestas de stubs que devuelven valores plausibles (un búfer nuevo para una reserva de memoria, un código de éxito para el resto). El análisis del PE Parser trabaja en tres pasadas:
- Encontrar las funciones. Desde el punto de entrada, las exportaciones, los callbacks TLS y cada llamada directa, sigue el código para descubrir las funciones y las llamadas entre ellas.
- Stack y tight strings. Cada función se emula desde su inicio durante un número limitado de instrucciones; se recoge el texto imprimible que aparece en su marco de pila, antes y después de cualquier bucle de decodificación.
- Cadenas decodificadas. Las funciones que parecen decodificadores — un XOR dentro de un bucle, pequeñas, llamadas desde varios sitios — se emulan desde cada punto de llamada, con los argumentos que preparó quien llama. Se recoge el texto que el decodificador escribe en memoria, junto con la dirección del decodificador.
Solo se informa del texto que una extracción simple no podía ver, así que la lista es corta y relevante.
En el PE Parser
- Abra un archivo nativo de 32 o 64 bits y vaya a la pestaña Análisis de código. El análisis corre en el navegador en unos cientos de milisegundos para la mayoría de archivos.
- Las cadenas recuperadas se listan con su tipo (decodificada, pila, bucle cerrado) y la función que las construyó. Haga clic en la dirección para abrir el desensamblado ahí.
- Las cadenas que aún parecen codificadas (sobre todo símbolos) se ocultan por defecto; una casilla las muestra.
- Los indicadores de red entre las cadenas recuperadas — URL, dominios, direcciones IP — pasan a la pestaña IOC y a sus exportaciones (exportar IOC).
- Para analizar una recolección entera, use Análisis de código en la barra de herramientas: se procesa cada archivo nativo y una columna Código muestra cuántas capacidades y cadenas tiene cada uno.
La misma pestaña lista las capacidades encontradas en el código: comprobaciones antidepuración, inyección de procesos, hashing de API, constantes criptográficas (MD5, SHA, CRC32, TEA, RC4, AES), hooks de keylogging y más, cada una asociada a MITRE ATT&CK y al Malware Behavior Catalog, con las funciones donde se encontró.
Límites
- Archivos empaquetados. Si el código está empaquetado, se emula el stub de desempaquetado, no el programa. Desempaquete primero — el PE Parser gestiona UPX por sí mismo (detectar ejecutables empaquetados).
- Cobertura de instrucciones. El emulador cubre código x86 / x64 entero corriente. Los decodificadores que usan instrucciones de coma flotante o SIMD se omiten.
- Claves externas. Un decodificador cuya clave llega de la red, del registro o de un archivo leído en ejecución no puede resolverse estáticamente.
- Presupuestos. Cada emulación está limitada para que un archivo hostil no bloquee la página; los programas muy grandes pueden analizarse parcialmente, y la pestaña lo indica.
Cuando estos límites pesan, el siguiente paso es el sandbox: ejecutar la muestra en un entorno aislado y volcar su memoria. Aun así, para la gran mayoría del malware común, la emulación recupera las cadenas necesarias en segundos — sin que la muestra llegue a ejecutarse.