Donut Loader

Donut Loader es una herramienta de código abierto que permite la ejecución en memoria de múltiples formatos de archivo, incluyendo VBScript, JScript, EXE, DLL y ensamblados .NET, transformándolos en shellcode independiente de la posición. Desarrollado bajo licencia BSD de 3 cláusulas, este framework ofrece capacidades avanzadas de evasión como cifrado simétrico Chaskey de 128 bits, compresión con múltiples algoritmos (aPLib, LZNT1, Xpress), y parcheo de mecanismos de seguridad como AMSI, WLDP y ETW. Su diseño permite que los módulos se sirvan desde servidores HTTP o se incrusten directamente en el cargador, eliminando las referencias originales tras la ejecución para dificultar el análisis forense de memoria.

En la reciente campaña ClickFix analizada por Swiss Post Cybersecurity, Donut Loader (versión 0.9.3) actuó como componente crítico en una cadena de infección multietapa totalmente basada en memoria. Tras un engaño de CAPTCHA falso que ejecutaba PowerShell, un dropper .NET llamado "believemesh" descifraba mediante RC4 y LZMA un blob de Donut de 1.7 MB incrustado como cadena hexadecimal. El cargador implementaba llamadas directas al sistema (syscalls) mediante stubs personalizados para evadir ganchos de EDR en modo usuario, reconstruía manualmente el binario final sin usar LoadLibrary ni CreateProcess, y ejecutaba el ladrón de información directamente en memoria del proceso PowerShell sin tocar disco.

La sofisticación de Donut Loader radica en su arquitectura modular que combina cargadores específicos por tipo de archivo: para .NET utiliza la API de alojamiento CLR no administrado con AppDomains desechables, para scripts emplea IActiveScript, y para binarios nativos incorpora un cargador PE personalizado con soporte para importaciones retardadas y TLS. Esta versatilidad, junto con su capacidad para parchear líneas de comando y sobrescribir encabezados PE mediante módulos señuelo, lo ha convertido en una herramienta prevalente en operaciones de equipo rojo que buscan emular adversarios con técnicas de ejecución sigilosa y persistencia mínima, demostrando que las defensas tradicionales basadas en indicadores de archivo resultan insuficientes frente a amenazas que operan exclusivamente en memoria volátil.

Funcionamiento

1. Arquitectura General y Filosofía de Diseño

Donut Loader es un framework de generación de shellcode que implementa un sistema de carga y ejecución en memoria completamente independiente del disco. Su arquitectura se divide en dos componentes principales: el generador (donut.exe) que produce el shellcode, y el cargador (loader.bin) que se inyecta en el proceso objetivo. El sistema está diseñado alrededor del concepto de "position-independent code" (PIC), lo que significa que todo el shellcode generado puede ejecutarse desde cualquier dirección de memoria sin necesidad de reubicaciones.

El generador acepta archivos de entrada de cinco tipos distintos: ensamblados .NET (EXE/DLL), ejecutables nativos de Windows (EXE/DLL), bibliotecas de enlace dinámico no administradas, scripts VBScript y JScript. Para cada tipo, Donut implementa un cargador especializado optimizado para las características específicas de ejecución de ese formato.

2. Proceso de Generación del Shellcode

2.1 Transformación de la Carga Útil

El proceso comienza cuando el generador recibe un archivo de entrada. La primera fase consiste en el análisis estructural del binario:

Para archivos PE nativos:

  • Parseo completo de la estructura IMAGE_DOS_HEADER e IMAGE_NT_HEADERS
  • Extracción de secciones y sus características de protección de página
  • Análisis de la tabla de importaciones (IAT) y exportaciones
  • Procesamiento de la tabla de direccionamiento de importaciones retardadas (Delay-Load Import Descriptor)
  • Extracción de la tabla de Thread Local Storage (TLS) si existe
  • Verificación de la presencia de información de reubicación base (base relocations)

Para ensamblados .NET:

  • Parseo del formato de archivo PE con componente CLI
  • Extracción del encabezado COR20
  • Localización de la tabla de metadatos y firmas de métodos
  • Análisis de la estructura del manifiesto del ensamblado
  • Verificación de compatibilidad (no ensamblados mixtos)

Para scripts:

  • Detección del tipo de motor de scripting necesario (VBScript vs JScript)
  • Codificación del script en formato UTF-16LE para compatibilidad con IActiveScript

2.2 Compresión y Cifrado

Una vez analizada la carga útil, Donut aplica transformaciones opcionales configurables por el usuario:

Compresión:

Donut soporta cinco algoritmos de compresión, cada uno con características específicas:

  1. aPLib: Algoritmo de compresión rápido basado en LZ77 con tasa de compresión moderada (~40-50%). Implementación completamente en software, funcionando en cualquier sistema operativo.
  2. LZNT1: Algoritmo nativo de Windows NT. Donut utiliza RtlCompressBuffer de ntdll.dll para implementar este formato. Ofrece buen equilibrio entre velocidad y tasa de compresión.
  3. Xpress (LZ77+Huffman): Algoritmo de compresión de Microsoft con ventana deslizante de 4KB más codificación Huffman post-LZ. Proporciona tasas superiores pero mayor consumo de CPU.
  4. Xpress Huffman: Variante mejorada con compresión puramente basada en Huffman, óptima para ciertos tipos de datos binarios.

Cifrado:

Donut emplea el cifrado de bloques Chaskey, un algoritmo de cifrado ligero basado en redes ARX (Add-Rotate-XOR) de 128 bits. Características técnicas:

  • Operación en modo CTR (Counter) para convertir el cifrado de bloque en flujo
  • Clave de 128 bits generada criptográficamente aleatoria por instancia
  • Vector de inicialización único por módulo
  • La clave se incrusta en el shellcode generado, no en el módulo cifrado

El proceso criptográfico completo:

c

// Pseudocódigo del proceso de cifrado
chaskey_key = random_bytes(16);
iv = random_bytes(16);
encrypted_payload = chaskey_ctr_encrypt(compressed_payload, chaskey_key, iv);
final_module = iv + chaskey_key + encrypted_payload;

2.3 Generación de Entropía

Donut implementa un sistema completo de generación de entropía para dificultar el análisis basado en firmas:

Hashing de API:

  • Implementación de algoritmo DJB2 modificado para generar hashes de 32 bits
  • Los nombres de APIs y DLLs se almacenan como hashes, no como cadenas planas
  • El cargador recalcula el hash en tiempo de ejecución y busca en PEB/LDR

Generación de nombres aleatorios:

  • Nombres de AppDomain generados mediante selección de diccionario
  • Nombres de módulo HTTP generados aleatoriamente
  • Identificadores de clase y método ofuscados

3. El Cargador en Memoria

3.1 Inicialización y Análisis del Entorno

Cuando el shellcode Donut comienza la ejecución en un proceso objetivo, realiza una serie de operaciones de reconocimiento:

Detección de arquitectura:

  • Verificación del valor del registro GS (x64) vs FS (x86)
  • Ajuste de offsets de estructuras según la arquitectura
  • Selección del conjunto de syscalls apropiado para la versión de Windows

Localización del PEB (Process Environment Block):

assembly

; x64 example
xor eax, eax
mov rax, gs:[0x60]  ; PEB en x64
mov ebx, [rax+0x18]  ; ImageBaseAddress offset

Enumeración de módulos cargados:

  • Navegación de la lista LDR_DATA_TABLE_ENTRY en PEB->Ldr
  • Cálculo de hashes para módulos conocidos (kernel32, ntdll, etc.)
  • Localización de direcciones de exportación mediante hash walking

3.2 Sistema de Syscalls Directas

Donut implementa un mecanismo sofisticado para evitar hooks de EDR en userland:

Detección de versión de Windows:

c

// Consulta RtlGetVersion para obtener el número de compilación
// Mapeo de compilaciones a versiones:
// 19045 -> Windows 10 22H2
// 22621 -> Windows 11 22H2
// 22631 -> Windows 11 23H2

Resolución de Service Numbers:

Para cada versión de Windows, los números de syscall cambian. Donut mantiene diccionarios anidados que mapean nombres de API a sus números de syscall específicos por compilación. El proceso:

  1. Identificación de la versión del sistema mediante RtlGetVersion
  2. Selección del diccionario correcto basado en el token de compilación
  3. Búsqueda del syscall number para la API requerida
  4. Generación de stub de ensamblado con el número inyectado

Stub de syscall x64:

assembly

mov r11, rcx        ; 4C 8B D9 - preservar contexto
mov eax, SYSCALL_NUMBER ; B8 [?? 00 00 00]
syscall             ; 0F 05
ret                 ; C3

3.3 Cargador PE para Binarios Nativos

El cargador de PE nativo de Donut implementa un linker en tiempo de ejecución completo:

Mapeo de secciones:

  1. Reserva de memoria mediante NtAllocateVirtualMemory con PAGE_READWRITE
  2. Cálculo del tamaño de imagen basado en SizeOfImage del NT headers
  3. Copia de encabezados a la dirección base
  4. Mapeo de cada sección con sus características de protección originales:
    • PAGE_READONLY para .rdata
    • PAGE_READWRITE para .data
    • PAGE_EXECUTE_READ para .text
    • PAGE_WRITECOPY para secciones compartidas

Procesamiento de importaciones:

  • Parseo de IMAGE_IMPORT_DESCRIPTOR para cada DLL
  • Resolución de direcciones de funciones mediante GetModuleHandle/LoadLibrary simulados
  • Parcheo de la IAT (Import Address Table) con direcciones resueltas
  • Manejo especial para importaciones retardadas (delay-load)

Aplicación de reubicaciones:

  • Si la dirección base preferida no está disponible, procesa IMAGE_BASE_RELOCATION
  • Aplicación de parches de desplazamiento absoluto de 64/32 bits
  • Corrección de punteros relativos

Inicialización de TLS:

  • Localización de la tabla de callbacks TLS
  • Ejecución secuencial de funciones de inicialización TLS
  • Configuración del array TLS para acceso por hilo

3.4 Cargador .NET mediante CLR Hosting

Donut implementa un host CLR no administrado completo para cargar ensamblados .NET:

Inicialización del runtime:

c

// 1. Obtener puntero a CorBindToRuntimeEx
pCorBindToRuntimeEx = GetProcAddress(hMSCorEE, "CorBindToRuntimeEx");

// 2. Crear instancia de ICLRRuntimeHost
pCorBindToRuntimeEx(
    L"v4.0.30319",      // Versión solicitada
    L"wks",             // Workstation garbage collection
    STARTUP_LOADER_OPTIMIZATION_MULTI_DOMAIN | 
    STARTUP_CONCURRENT_GC, // Flags de inicio
    CLSID_CLRRuntimeHost,
    IID_ICLRRuntimeHost,
    (IUnknown**)&pClrHost
);

// 3. Iniciar el runtime
pClrHost->Start();

Creación de AppDomain:

  • Creación de AppDomain desechable mediante CreateDomainEx
  • Configuración de políticas de seguridad (caseras)
  • Asignación de nombre aleatorio para evasión

Carga del ensamblado:

  • Obtención de puntero a mscorlib's AppDomain.Load_3 mediante reflection
  • Invocación del método con el array de bytes del ensamblado
  • El ensamblado se carga completamente en memoria sin respaldo en disco

Invocación de entry point:

c

// Para EXE .NET
pEntryPoint = assembly->GetEntryPoint();
pEntryPoint->Invoke(objNull, pParams);

// Para DLL .NET
pType = assembly->GetType(className);
pMethod = pType->GetMethod(methodName);
pMethod->Invoke(objNull, pParams);

3.5 Cargador de Scripts con IActiveScript

El subsistema de scripting utiliza la interfaz COM IActiveScript:

Inicialización COM:

  • CoInitializeEx con COINIT_APARTMENTTHREADED
  • Creación de instancia de CLSID_VBScript o CLSID_JScript

Configuración del sitio de scripting:

  • Implementación de IActiveScriptSite personalizado
  • Manejo de errores de scripting
  • Redirección de salida estándar

Ejecución:

  • Parsing del script mediante ParseScriptText
  • Adición de objetos named items para funcionalidad extendida
  • Ejecución mediante SetScriptState(SCRIPTSTATE_STARTED)

4. Mecanismos de Evasión Avanzados

4.1 Parcheo de AMSI (Antimalware Scan Interface)

Donut implementa múltiples técnicas para deshabilitar AMSI:

Parcheo de AmsiScanBuffer:

c

// Localización de amsi.dll en el proceso
HMODULE hAmsi = GetModuleHandle("amsi.dll");
FARPROC pAmsiScanBuffer = GetProcAddress(hAmsi, "AmsiScanBuffer");

// Parche: retornar E_INVALIDARG (0x80070057) inmediatamente
BYTE patch[] = { 
    0xB8, 0x57, 0x00, 0x07, 0x80,  // mov eax, 0x80070057
    0xC3                           // ret
};

WriteProcessMemory(GetCurrentProcess(), pAmsiScanBuffer, patch, sizeof(patch));

Técnica alternativa: Parcheo de la función AmsiScanString

Segunda alternativa: Sobrescritura de la dirección de retorno en el stack frame

4.2 Parcheo de WLDP (Windows Lockdown Policy)

Deshabilitación de la política de bloqueo para permitir código dinámico .NET:

Parcheo de WldpIsDynamicCodePolicyEnabled:

  • Localización de wldp.dll
  • Parche para retornar FALSE siempre
  • Evita la restricción de código generado dinámicamente

4.3 Parcheo de ETW (Event Tracing for Windows)

Donut neutraliza ETW para evitar telemetría:

Parcheo de ntdll!EtwEventWrite:

c

// Stub que retorna inmediatamente
BYTE patch[] = { 
    0xC3,           // ret 
    0xCC, 0xCC, 0xCC // int 3 padding
};

WriteProcessMemory(GetCurrentProcess(), pEtwEventWrite, patch, 1, NULL);

4.4 Sobrescritura de Encabezados PE

Funcionamiento normal:

  • Los encabezados PE desde ImageBase hasta SizeOfHeaders se sobrescriben con ceros
  • Impide herramientas que comparan memoria con archivo en disco

Con módulo señuelo:

  • Se carga un PE legítimo (por ejemplo, cmd.exe) en memoria
  • Sus encabezados se copian sobre la región del módulo malicioso
  • La memoria parece contener un binario firmado legítimo

5. Sistema de Comunicación HTTP

Cuando se configura el modo de servidor HTTP:

Estructura del módulo de red:

  • El shellcode contiene solo un stub mínimo
  • El stub realiza una petición HTTP GET al servidor configurado
  • El servidor responde con el módulo completo cifrado
  • Recepción, descifrado y ejecución en memoria

Soporte de credenciales:

  • URLs con formato: https://username:password@hostname/
  • Autenticación básica HTTP
  • Soporte para HTTPS mediante WinHTTP

6. Formatos de Salida y Generación de Stubs

Donut genera el shellcode final en múltiples formatos:

Binario plano:

  • Raw shellcode listo para inyección
  • Formato por defecto

Codificaciones:

  • Base64: Para incrustación en scripts PowerShell/Python
  • Hexadecimal: Para inserción en código C/C++
  • UUID: Cada 16 bytes se convierten en formato UUID
  • C-array: unsigned char buf[] = { 0x90, 0x90, ... };

Lenguajes de scripting:

  • PowerShell: Script que contiene el shellcode y lo inyecta
  • Python: Módulo con shellcode y cargador
  • Ruby: Script equivalente
  • C#: Clase con array de bytes y método de ejecución

7. Gestión de Memoria y Limpieza

Políticas de salida configurables:

  1. ExitThread: Finaliza solo el hilo del cargador (por defecto)
  2. ExitProcess: Termina todo el proceso host
  3. Infinite hang: El hilo entra en Sleep(INFINITE)

Limpieza de evidencias:

  • Zeroing de buffers sensibles mediante RtlSecureZeroMemory
  • Liberación de memoria no utilizada
  • Destrucción de AppDomains .NET
  • Terminación limpia del scripting engine

8. Limitaciones Técnicas y Consideraciones

Binarios nativos:

  • Requieren información de reubicación
  • No soporte para binarios compilados con Cygwin
  • Limitaciones con TLS dinámico complejo

.NET:

  • No soporte para ensamblados mixtos (managed/unmanaged)
  • Requiere métodos públicos estáticos
  • Parámetros limitados a strings o ninguno

Scripts:

  • Soporte limitado de WSH (WScript/Cscript)
  • No todas las funcionalidades COM disponibles

9. Integración y Extensibilidad

Donut proporciona bibliotecas para integración:

Windows:

  • donut.dll: Biblioteca dinámica
  • donut.lib: Biblioteca estática
  • Headers C completos

Linux:

  • donut.so: Objeto compartido
  • donut.a: Biblioteca estática
  • Misma API que Windows

Python:

  • Módulo nativo via PyPI
  • Wrapper completo de funcionalidad Donut

Esta arquitectura técnica convierte a Donut Loader en una de las herramientas más completas y sofisticadas para generación de shellcode y ejecución en memoria, implementando técnicas avanzadas de evasión que operan en múltiples capas del sistema operativo Windows.

Impacto y consecuencias

1. Transformación del Panorama de Amenazas

1.1 Democratización de Técnicas Avanzadas

Donut Loader ha provocado una democratización sin precedentes de capacidades ofensivas que antes estaban limitadas a actores con recursos significativos. El impacto más profundo reside en cómo ha reducido drásticamente la barrera de entrada para ejecutar cargas útiles complejas en memoria:

Antes de Donut (2018 y anteriores):

  • La ejecución en memoria de .NET requería conocimientos profundos de hosting CLR no administrado
  • Los equipos rojos necesitaban desarrollar cargadores personalizados para cada campaña
  • La evasión de AMSI/ETW era un proceso manual que requería ingeniería inversa significativa
  • La generación de shellcode para binarios nativos demandaba experiencia en formato PE y reubicaciones

Después de Donut:

  • Cualquier operador con conocimientos básicos puede transformar un ensamblado .NET complejo en shellcode funcional con un solo comando
  • La evasión de múltiples controles de seguridad se automatiza completamente
  • El tiempo de desarrollo de cargas útiles se reduce de semanas a minutos

Esta democratización ha tenido un efecto multiplicador en el ecosistema de amenazas. Frameworks C2 comerciales y de código abierto como Cobalt Strike, Sliver, Covenant y Brute Ratel han integrado Donut directamente o mediante implementaciones derivadas. Esta integración ha creado un efecto de estandarización donde la técnica de ejecución en memoria mediante Donut se ha convertido en el mecanismo predeterminado para la entrega de cargas útiles de post-explotación.

1.2 Evolución del Ciclo de Vida del Malware

Donut ha modificado fundamentalmente el ciclo de vida tradicional del malware:

Fase de entrega tradicional:

  • Archivo malicioso en disco → Análisis AV → Ejecución → Persistencia

Fase de entrega post-Donut:

  • Dropper mínimo → Ejecución en memoria → Carga útil Donut → Operaciones post-explotación → Sin artefactos en disco

Esta evolución ha forzado una transformación completa en las estrategias de defensa. Los indicadores de compromiso (IOC) tradicionales basados en hashes de archivos, rutas de instalación o claves de registro se han vuelto prácticamente irrelevantes para las campañas que utilizan Donut. Los equipos de respuesta a incidentes ahora enfrentan infecciones que no dejan archivos, no modifican el registro y no establecen persistencia tradicional, lo que complica enormemente la determinación del alcance de un compromiso.

2. Impacto en la Industria de Seguridad

2.1 Obsolescencia de Controles Tradicionales

Productos antivirus basados en firmas:

Donut ha contribuido significativamente a la obsolescencia de los productos AV tradicionales. Cada ejecución de una carga útil Donut puede ser única debido a:

  • Claves de cifrado Chaskey generadas aleatoriamente por instancia
  • Nombres de AppDomain y módulos generados con entropía
  • Parámetros de compresión variables
  • Formatos de salida múltiples

Un mismo ensamblado .NET procesado por Donut en diez ocasiones produce diez binarios de shellcode completamente diferentes a nivel de bytes. Esto ha invalidado las bases de datos de firmas hash que constituían el núcleo de la detección tradicional.

EDR de primera generación:

Los sistemas EDR basados exclusivamente en hooks de API en userland han demostrado ser ineficaces contra Donut debido a su implementación de syscalls directas. Cuando Donut ejecuta:

text

NtAllocateVirtualMemory(syscall) → Sin hook → Sin detección
NtWriteVirtualMemory(syscall) → Sin hook → Sin detección
NtCreateThreadEx(syscall) → Sin hook → Sin detección

El EDR nunca observa estas operaciones porque ocurren por debajo de su capa de instrumentación. Esto ha obligado a los proveedores de EDR a invertir millones en desarrollar nuevas capacidades de detección basadas en:

  • Kernel callbacks (ObRegisterCallbacks, PsSetCreateProcessNotifyRoutine)
  • ETW de kernel (Microsoft-Windows-Threat-Intelligence)
  • Monitoreo de Page Tables y Memory Type Range Registers
  • Virtualization-based security (VBS) enclaves

2.2 Cambio de Paradigma en Detección y Respuesta

De indicadores estáticos a comportamiento:

La industria ha experimentado una transformación forzosa desde IoCs (Indicators of Compromise) hacia IoAs (Indicators of Attack). Con Donut, los defensores ya no pueden preguntar "¿Hay algún archivo malicioso en este sistema?" sino que deben preguntar "¿Observamos comportamientos compatibles con la ejecución de shellcode en memoria?".

Esta transición ha requerido:

  1. Reentrenamiento masivo de analistas SOC: Los analistas formados en búsqueda de hashes y firmas deben ahora comprender conceptos como asignaciones de memoria con PAGE_EXECUTE_READWRITE, llamadas a sistema directas y secuencias de carga de CLR no estándar.
  2. Desarrollo de nuevas fuentes de telemetría: Microsoft ha respondido a amenazas como Donut mejorando significativamente ETW, particularmente con:
    • Microsoft-Windows-Kernel-Memory
    • Microsoft-Windows-Threat-Intelligence
    • Event ID 13 (mapa de memoria) y Event ID 25 (protección de página virtual)
  3. Inversión en análisis de comportamiento: Los productos de seguridad han migrado de motores de firmas a modelos de machine learning entrenados para detectar secuencias de comportamiento anómalas en lugar de bytes específicos.

2.3 Respuesta de Microsoft y el Ecosistema Windows

Donut ha expuesto vulnerabilidades fundamentales en el modelo de seguridad de Windows que Microsoft ha tenido que abordar:

Mejoras en AMSI:

Originalmente, AMSI podía deshabilitarse con parches de 6 bytes. Microsoft ha respondido:

  • Implementación de AMSI en múltiples capas
  • Protección de la función AmsiScanBuffer mediante integridad de código
  • Monitoreo de integridad de las propias funciones de AMSI
  • AMSI para Office 365 y otras superficies de ataque

Refuerzo de ETW:

La capacidad de Donut para parchear ntdll!EtwEventWrite provocó:

  • Implementación de ETW protegido (P-ETW) en Windows 10 1903+
  • Separación de estructuras de ETW en memoria de solo lectura
  • Monitoreo de integridad de proveedores ETW

Control de integridad de código (CI) y HVCI:

La respuesta más significativa de Microsoft ha sido la promoción de Hypervisor-Protected Code Integrity (HVCI), que:

  • Ejecuta el kernel de integridad de código en un entorno virtualizado aislado
  • Verifica la integridad de todas las imágenes ejecutables antes de su ejecución
  • Previene la modificación de código del kernel y controladores
  • Dificulta enormemente las syscalls directas desde user mode

Sin embargo, la adopción de HVCI sigue siendo limitada debido a:

  • Requisitos de hardware (VT-x, SLAT, IOMMU)
  • Incompatibilidad con controladores antiguos
  • Overhead de rendimiento en ciertas cargas de trabajo

3. Impacto en Operaciones de Equipos Rojos y Pruebas de Penetración

3.1 Profesionalización y Estandarización

Donut ha estandarizado las operaciones de equipo rojo a nivel global. Antes de Donut, existía una brecha significativa entre las capacidades de equipos rojos internos y consultores externos. Los equipos rojos de proveedores de seguridad boutique con recursos limitados simplemente no podían replicar las técnicas de ejecución en memoria .NET que los actores de amenazas avanzados utilizaban.

Donut ha eliminado esta brecha. Actualmente, cualquier equipo rojo comercial puede:

  • Ejecutar herramientas como Seatbelt, SharpView o Rubeus completamente en memoria
  • Implementar ofuscación y evasión de nivel empresarial con configuración mínima
  • Generar cargas útiles para entornos con controles de seguridad estrictos

Esto ha elevado el estándar de lo que constituye una prueba de penetración aceptable. Las organizaciones que contratan evaluaciones de seguridad ahora esperan que los equipos rojos puedan evadir AMSI, eludir EDR y operar completamente en memoria.

3.2 Creación de una Economía de Herramientas

Donut ha catalizado un ecosistema completo de herramientas derivadas y complementarias:

Generadores alternativos:

  • n1xbyte/donut-csharp: Implementación completa del generador Donut en C#
  • awgh/donut-go: Puerto a Go para integración con toolchains modernas
  • Volexity/donut-decryptor: Herramienta forense para extraer cargas útiles de muestras Donut

Integraciones C2:

  • Cobalt Strike: Implementación nativa mediante execute-assembly y técnicas Donut
  • Covenant: C2 en .NET que utiliza Donut para cargas nativas
  • Sliver: Framework Go con módulos de generación Donut
  • Brute Ratel: Implementación de técnicas similares a Donut como característica principal

Frameworks de ofuscación:

  • Herramientas que aplican capas adicionales de cifrado/polimorfismo sobre shellcode Donut
  • Generadores de loaders personalizados que integran Donut como payload final

Esta economía ha creado un efecto de red donde la mejora de una herramienta beneficia a todo el ecosistema, acelerando colectivamente la evolución de técnicas ofensivas.

4. Impacto en la Investigación y Análisis de Malware

4.1 Complejidad del Análisis Forense

Donut ha incrementado exponencialmente la complejidad del análisis de malware:

Dificultades de análisis estático:

El shellcode generado por Donut presenta características que frustran el análisis estático:

  • Sin cadenas legibles: Todos los identificadores, nombres de API y configuraciones están hasheados u ofuscados
  • Sin importaciones explícitas: Las resoluciones de API son dinámicas mediante hashing
  • Múltiples capas de cifrado: RC4, Chaskey, XOR, y compresión en secuencia
  • Código polimórfico: Cada generación produce shellcode único

Desafíos de análisis dinámico:

Los analistas que ejecutan muestras Donut en sandboxes enfrentan:

  • Detección de entornos virtualizados: El shellcode puede verificar configuraciones regionales, nombres de procesos, tamaños de disco
  • Ejecución condicional: El payload final solo se descifra/descomprime tras superar verificaciones
  • Carga diferida: Componentes descargados de servidores C2 solo bajo condiciones específicas
  • Ausencia de persistencia: Sin artefactos en disco, el análisis post-ejecución es limitado

Requisitos de memoria forense:

El análisis de infecciones Donut requiere capturas de memoria completa (full memory dumps) y herramientas especializadas:

  • Volatility plugins para extraer shellcode de regiones PAGE_EXECUTE
  • Reconstrucción manual de estructuras PE en memoria
  • Decodificación de capas de cifrado para extraer payload final

4.2 Evolución de Contramedidas Forenses

La comunidad de análisis de malware ha desarrollado herramientas específicas para Donut:

Decryptores universales:

Investigadores han publicado herramientas como donut-decryptor que automatizan la extracción de payloads de muestras Donut, pero existe una carrera armamentista continua. Cada versión de Donut modifica ligeramente los offsets y estructuras, requiriendo actualizaciones constantes.

YARA mejorado:

Las reglas YARA para detectar Donut han evolucionado de firmas byte específicas a detección de características estructurales:

  • Secuencias de syscall stubs con patrones 4C 8B D1 B8 ?? 0F 05 C3
  • Estructuras de hashing DJB2 características
  • Patrones de inicialización de AppDomain .NET
  • Secuencias de parcheo AMSI

5. Impacto en la Defensa Corporativa

5.1 Costos Operacionales Incrementados

Las organizaciones que enfrentan amenazas que utilizan Donut han visto aumentos significativos en costos de seguridad:

Inversión en herramientas de nueva generación:

Los productos AV/EDR tradicionales son insuficientes. Las organizaciones deben migrar a soluciones que ofrezcan:

  • Detección de anomalías de memoria (Memory Threat Detection)
  • Análisis de comportamiento basado en machine learning
  • Capacidades de respuesta en memoria
  • Integración con fuentes de telemetría del kernel

Entrenamiento especializado:

Los analistas SOC requieren formación continua en:

  • Técnicas de malware basado en memoria
  • Forense de memoria volátil
  • Detección de ataques fileless
  • Respuesta a incidentes sin artefactos tradicionales

Tiempo de respuesta aumentado:

Los incidentes que involucran Donut requieren significativamente más tiempo de investigación:

  • Sin archivos para analizar → mayor dependencia de logs y telemetría
  • Múltiples etapas de infección → cada etapa debe desenredarse
  • Payloads cifrados → requiere descifrado para entender el alcance

5.2 Desafíos de Cumplimiento y Regulatorios

Donut ha creado problemas complejos para organizaciones reguladas:

Auditorías y compliance:

Los marcos de cumplimiento como PCI DSS, HIPAA y SOX tradicionalmente se centraban en malware basado en archivos. Una organización puede aprobar auditorías de cumplimiento que verifican soluciones AV en endpoints mientras alberga infecciones Donut activas en memoria, sin archivos maliciosos detectables en disco.

Retención de evidencia:

Los requisitos regulatorios de retención de evidencia forense son difíciles de cumplir cuando las infecciones no dejan artefactos. Las organizaciones deben implementar:

  • Captura proactiva de memoria en puntos críticos
  • Retención de telemetría ETW a largo plazo
  • Almacenamiento de eventos de memoria y comportamiento

Notificación de brechas:

Determinar si existe obligación legal de notificar una brecha se complica cuando no hay certeza sobre qué datos fueron accedidos por payloads ejecutados exclusivamente en memoria. Los reguladores carecen de directrices claras para este escenario.

6. Impacto en el Ciclo de Vida del Desarrollo de Software

6.1 Supply Chain Security

Donut ha sido utilizado en ataques a la cadena de suministro de software:

Escenario de ataque:

  1. Compromiso de entorno de desarrollo
  2. Inyección de Donut en procesos de compilación
  3. El payload Donut extrae credenciales de firmado de código
  4. Exfiltración de certificados de firma para malware

Consecuencias:

  • Los certificados de firma robados permiten firmar malware que elude controls de integridad de código
  • Los entornos CI/CD comprometidos producen artefactos legítimos que contienen backdoors
  • Dificultad extrema en determinar el alcance del compromiso

6.2 Desarrollo Seguro

Las organizaciones de desarrollo de software han tenido que adaptar sus prácticas de DevSecOps:

Pruebas de seguridad dinámicas (DAST):

Las aplicaciones web ahora deben probarse contra ataques que entregan Donut mediante:

  • Web shells que descargan e inyectan Donut en memoria
  • Vulnerabilidades de deserialización que ejecutan cargadores Donut
  • SSRF (Server-Side Request Forgery) que recuperan módulos Donut

Protección de entornos de desarrollo:

  • Endpoint hardening específico contra ejecución en memoria
  • Monitoreo de procesos de compilación para detección de inyección
  • Aislamiento de entornos de firma de código

7. Implicaciones Legales y Éticas

7.1 Doble Uso y Responsabilidad

Donut ejemplifica el dilema del doble uso en ciberseguridad:

Argumento de defensa:

Los creadores de Donut argumentan que es una herramienta de equipo rojo para evaluar defensas. La licencia BSD de 3 cláusulas incluye un descargo de responsabilidad explícito. Sin embargo, la realidad es que Donut es utilizado extensamente por actores de amenazas con fines criminales.

Responsabilidad de los creadores:

El equipo de desarrollo de Donut ha declarado explícitamente que no actualizarán la herramienta para contrarrestar firmas o métodos de detección. Esta postura ética, aunque loable, no impide que actores maliciosos utilicen las capacidades existentes. La pregunta de responsabilidad permanece sin resolver en la comunidad de seguridad.

7.2 Marco Legal y Atribución

Donut ha complicado la atribución de ataques:

Problemas de atribución:

Debido a que Donut es público, gratuito y ampliamente disponible, la presencia de shellcode Donut en un incidente no proporciona información de atribución significativa. Tanto actores patrocinados por estados como criminales financieros y equipos rojos legítimos utilizan exactamente las mismas herramientas.

Desafíos procesales:

En procedimientos legales, los fiscales enfrentan dificultades para establecer el vínculo entre una herramienta ofensiva y un actor específico cuando la herramienta es pública y está ampliamente disponible. La defensa puede argumentar razonablemente que cualquier persona podría haber utilizado la misma herramienta.

7.3 Exportación y Control de Armas

Donut plantea preguntas sobre controles de exportación de tecnologías ofensivas:

ITAR/EAR:

El shellcode generado por Donut constituye técnicamente un "sistema de armas" cibernético. Sin embargo, al ser código abierto y estar disponible globalmente en GitHub, los mecanismos tradicionales de control de exportaciones son ineficaces. Esta tensión entre la naturaleza global del desarrollo de software y las regulaciones nacionales de control de armas no tiene solución clara.

8. Impacto Estratégico a Largo Plazo

8.1 Transformación Permanente del Panorama

Donut no es una amenaza transitoria. Ha creado un cambio permanente en las capacidades ofensivas disponibles:

Efecto generacional:

Los profesionales de seguridad que aprenden ofensiva en 2025 aprenden con Donut como herramienta estándar. Esta normalización significa que las técnicas de ejecución en memoria ya no son "avanzadas" sino que forman parte del conocimiento básico esperado. Esta transformación cultural es irreversible.

Innovación continua:

El éxito de Donut ha validado un modelo de desarrollo donde herramientas ofensivas especializadas se liberan como código abierto, reciben contribuciones de la comunidad y evolucionan rápidamente. Este modelo se ha replicado con otras herramientas como:

  • Sliver (framework C2 alternativo)
  • NimCrypt (ofuscación de payloads)
  • ScareCrow (bypass de firma de código)

Carrera armamentista permanente:

Microsoft y otros proveedores continuarán desarrollando contramedidas. La comunidad ofensiva continuará desarrollando bypasses. Esta dinámica, catalizada por Donut, define el estado actual de la ciberseguridad y probablemente continuará indefinidamente.

8.2 Lecciones para el Futuro

Donut ofrece lecciones fundamentales sobre la naturaleza de la seguridad de plataformas:

Lección 1: Las abstracciones de seguridad tienen límites

El modelo de seguridad de Windows asumía que la instrumentación en userland era suficiente. Donut demostró que esta suposición era incorrecta. La lección para futuros sistemas operativos es que la seguridad debe implementarse en la capa más baja posible.

Lección 2: La memoria es la nueva frontera

Donut es parte de una tendencia más amplia de malware basado en memoria. Futuras amenazas llevarán esta técnica más allá, potencialmente operando completamente dentro de GPU, firmware o procesadores de red.

Lección 3: La democratización ofensiva es inevitable

Una vez que una técnica ofensiva es desarrollada, eventualmente se democratizará. Las defensas no pueden asumir que los atacantes carecerán de habilidades o recursos avanzados. Deben diseñarse para resistir a adversarios con capacidades máximas.

9. Conclusión Técnica

Donut Loader representa un punto de inflexión en la historia de la ciberseguridad. Técnicamente, es una implementación elegante y eficiente de múltiples técnicas de ejecución en memoria. Estratégicamente, ha democratizado capacidades ofensivas avanzadas y ha forzado una transformación completa en las estrategias de defensa.

Su impacto más profundo no es técnico sino sistémico: ha alterado permanentemente el equilibrio entre atacantes y defensores. Los defensores ya no pueden confiar en controles perimetrales, firmas de archivos o análisis superficial. Deben operar bajo el supuesto de que cualquier código puede ejecutarse en memoria sin dejar rastro, y construir defensas que funcionen bajo este supuesto.

Donut no es el fin de esta evolución, sino su catalizador. Las lecciones aprendidas de su diseño, implementación y consecuencias informarán tanto el desarrollo de futuras herramientas ofensivas como el diseño de sistemas operativos más resistentes. En este sentido, Donut es tanto un producto de su tiempo como un modelo para el futuro de la seguridad de plataformas.

Origen y motivación

Donut Loader fue creado por TheWover y Odzhan como una herramienta de código abierto para equipos rojos, con el objetivo técnico de demostrar y facilitar la ejecución en memoria de diversos formatos de archivo (ensamblados .NET, binarios nativos y scripts) mediante su transformación en shellcode independiente de posición, abordando la necesidad de emular adversarios sofisticados que utilizan técnicas fileless para evadir defensas tradicionales. Su motivación fundamental surge de la observación de que, aunque existían métodos para ejecutar ensamblados .NET en memoria (como el execute-assembly de Cobalt Strike) o binarios nativos mediante cargadores personalizados, no había una solución unificada, gratuita y extensible que combinara todas estas capacidades con mecanismos avanzados de evasión como parcheo de AMSI/WLDP/ETW, cifrado simétrico, compresión multi-algoritmo y resolución de API mediante hashing. Los autores buscaban proporcionar a la comunidad de seguridad ofensiva una plataforma común que elevara el estándar de las evaluaciones de penetración y permitiera a los defensores comprender estas técnicas para desarrollar mejores contramedidas, operando bajo la premisa de que la divulgación responsable de capacidades ofensivas avanzadas, aunque conlleva riesgos de uso malintencionado, beneficia netamente al ecosistema de seguridad al exponer vulnerabilidades fundamentales en los modelos de defensa establecidos.