Ofuscación de malware
Ofuscar es hacer algo difícil de entender o interpretar. Se suele utilizar para proteger propiedad intelectual o secretos comerciales y también para evitar que un adversario realice ingeniería inversa de una aplicación de software propietario o viceversa.
Una forma de ofuscación es cifrar parte o la totalidad del código de un programa, por tanto; un “ofuscador” es una herramienta que, por ejemplo; es capaz de convertir código fuente simple en un programa difícil de leer y entender. También, vale decir que los autores de malware a menudo usan técnicas de empaquetamiento u ofuscación para hacer que sus cargas útiles sean más difíciles de detectar o analizar.
La ofuscación de malware es una técnica utilizada para crear datos textuales y binarios difíciles de interpretar y que ayudan a los adversarios a ocultar cadenas críticas en un programa, porque revelan patrones del comportamiento del malware. Las cadenas serían, por ejemplo; claves de registro, dirección IP de origen o URL infectadas.
El uso de ofuscadores por parte de adversarios busca empaquetar mediante un subconjunto de programas ofuscados el código malicioso, en el cual esta comprimido para que no se pueda analizar. De forma que las técnicas de empaquetado y ofuscación limitarán los intentos de analizar estáticamente el malware.
Notaran que los programas no maliciosos siempre incluyen muchas cadenas, en contraposición del malware empaquetado u ofuscado, el cual contiene muy pocas cadenas. Si estamos frente a un programa que tiene solo unas pocas cadenas, es muy probable que esté ofuscado o empaquetado. Con este vector, ya tenemos una pista de que algún programa puede ser malicioso.
Los creadores de malware emplean con frecuencia técnicas de ofuscación para evadir mecanismos de detección como: soluciones de protección transversal para usuario final, IDS, IPS, correlacionadores o analizadores de amenazas basados en IA, Sanbox, etc.
En este breve artículo expondremos a muy a alto vuelo, algunas de las técnicas de ofuscación más usadas para empaquetar cadenas maliciosas:
Base64: Se trata de una técnica de ofuscación muy conocida y que es ampliamente empleada por adversarios maliciosos.
Base64 se ensambla como un esquema de codificación de 64 caracteres, siendo el carácter de relleno el signo = (igual). Así pues, el alfabeto también incluye las letras a-z, A-Z, + y /, y 0–9 caracteres.
La codificación funciona encadenando 3 caracteres para generar una cadena de 24 bits (1 carácter equivale a 8 bits), que luego se divide en 4 fragmentos de 6 bits, cada uno de los cuales se traduce a uno de los caracteres Base64.
XOR: Es sin duda un método popular de ofuscación que oculta los datos para que no puedan analizarse. La instrucción XOR deriva la lógica o exclusiva sobre el valor en la fuente A por el bit con el valor de la fuente B y la lógica de salida almacenada en el destino. Ampliemos, XOR realiza una operación OR exclusiva bit a bit en el operando de destino (primero) y origen (segundo), almacenando el resultado en la ubicación del operando de destino.
El operando origen puede ser un lugar inmediato, de registro o de memoria; el operando de destino puede ser un registro o una ubicación de memoria. Así que XOR hace un intercambio del contenido de dos variables dentro del código, por ejemplo: XOR EBX, EAX o XOR EAX, EBX o bien, XOR EBX, EAX.
Dicho simple; hace un cambio de posición en la memoria en tiempo de ejecución.
Inserción de código muerto: Una inserción de código muerto es un enfoque simple para cambiar la apariencia de un programa mientras mantiene su funcionalidad.
NOP es un ejemplo de tal comando. El código original se ofusca fácilmente insertando instrucciones NOP. Para aclarar, NOP, no-op o NOOP trata de una instrucción de lenguaje de máquina y su mnemónico de lenguaje ensamblador, declaración de lenguaje de programación o comando de protocolo de computadora que no hace nada.
Los escáneres antimalware basados en firmas, por otro lado, pueden resistir esta estrategia simplemente eliminando las instrucciones fallidas antes de analizarlas. Recordar que la instrucción NOP no hace nada. La ejecución continúa con la siguiente instrucción. Esta instrucción no afecta a los registros ni a las banderas.
NOP se usa típicamente para generar un retraso en la ejecución o para reservar espacio en la memoria del código.
Transposición de código: La transposición de código reordena la secuencia de instrucciones de un código original, sin afectar el comportamiento del código.
Este procedimiento se puede realizar de dos formas:
1. Mezclar las instrucciones al azar, luego insertar ramas o saltos incondicionales para restaurar el orden de ejecución original. No es difícil vencer este método porque el programa original se puede restaurar fácilmente eliminando las ramas o saltos incondicionales.
2. Crear nuevas generaciones eligiendo y reordenando las instrucciones independientes que no tienen impacto entre sí. Debido a que es un problema complejo encontrar las instrucciones independientes, este método es difícil de implementar, pero puede hacer que el costo de detección sea alto.
Reasignación de registros: La reasignación de registros es otra técnica simple que cambia los registros de generación en generación, mientras mantiene el código del programa y su comportamiento igual. Debemos tener en cuenta que la búsqueda con comodines puede hacer que esta técnica sea inútil.
Reordenamiento de subrutinas: El reordenamiento de subrutinas ofusca un código original al reorganizar aleatoriamente sus subrutinas. Este método puede generar “N” diferentes variaciones, donde “N” denota el número de subrutinas.
Sustitución de instrucciones: La sustitución de instrucciones evoluciona desde un código original, reemplazando algunas instrucciones con otras equivalentes. Esta técnica puede cambiar efectivamente el código con una biblioteca de instrucciones equivalentes.
Integración de código: La integración de código se detectó por primera vez en un virus llamado Zmist/Win95 (cc Zmist), e instruye al código malicioso para que se una al código del programa de destino. Así dicho, el malware descompila el programa en bits manejables, se inserta entre ellos y luego vuelve a ensamblar el código inyectado en una nueva variante para usar la técnica.
Sustitución de instrucciones: La sustitución de instrucciones evoluciona desde un código original, reemplazando algunas instrucciones con otras equivalentes. Esta técnica puede cambiar efectivamente el código con una biblioteca de instrucciones equivalentes.
Empacadores: En algunas situaciones, todo el programa se ofusca para evitar que se detecte o se haga ingeniería inversa al código de malware, hasta que se coloca en la memoria.
Esta técnica se logra con la ayuda de software para comprimir ejecutables para hacerlo más pequeño. El ejecutable comprimido se empaqueta dentro del código necesario para descomprimirse durante el tiempo de ejecución. En cierre el procedimiento de descompresión asegura que el archivo malicioso no luzca como en su estado original.
En resumen, vemos una evolución en las técnicas de ofuscación a partir del ataque a SolarWinds en el que los atacantes instalaron una puerta trasera que integraba capacidades de ofuscación, aprendizaje automático e inteligencia artificial, para ocultar sus actividades, eludir las defensas, manipular los registros de auditoría, eliminar archivos y programas después de su uso y falsificar la actividad de red para que pareciera que se trataba de aplicaciones legítimas.
La ofuscación de malware es una técnica que los adversarios maliciosos utilizan y que es altamente confiable. Entender los TTPs, los IoCs y los IoAs es por consecuencia mandatorio para los equipos de respuesta y para los fabricantes.