AvanzadoWindowsDLL injectioninyección de códigodetecciónMITRE ATT&CK

DLL Injection en Windows: Técnicas, Variantes y Detección

Análisis técnico completo de las técnicas de inyección de DLL en Windows. Classic injection, reflective loading, DLL side-loading, DLL hollowing y las estrategias de detección para cada variante. Con pseudocódigo, mapeo ATT&CK y reglas de detección.

MalwareIntel Research··9 min lectura
Serie: Malware en Windows — Parte 2

Por qué el malware inyecta DLLs

La inyección de código es una de las técnicas más fundamentales del malware en Windows. El motivo es simple: ejecutar código dentro de un proceso legítimo proporciona tres ventajas críticas.

Evasión: un hilo de ejecución dentro de svchost.exe o explorer.exe es mucho más difícil de detectar que un proceso independiente con un nombre sospechoso. Los EDRs y los analistas SOC confían en el nombre del proceso como primer indicador; la inyección anula esta señal.

Herencia de permisos: el código inyectado hereda los permisos del proceso objetivo. Inyectar en un proceso que corre como SYSTEM obtiene privilegios de SYSTEM sin necesidad de explotar una vulnerabilidad de escalada.

Persistencia en memoria: el código inyectado vive en la memoria del proceso objetivo. No tiene un archivo propio en disco que un antivirus pueda escanear.

Técnica 1: Classic DLL Injection (T1055.001)

Flujo de ejecución

Malware (proceso atacante)                    Proceso víctima (ej. explorer.exe)
    │                                              │
    ├── OpenProcess(PROCESS_ALL_ACCESS, pid) ──────┤ Obtener handle del proceso
    │                                              │
    ├── VirtualAllocEx(hProcess, ...) ─────────────┤ Reservar memoria en el proceso
    │                                              │
    ├── WriteProcessMemory(hProcess, path_dll) ────┤ Escribir ruta de la DLL en la memoria
    │                                              │
    ├── GetProcAddress(GetModuleHandle(             │
    │     "kernel32.dll"), "LoadLibraryA") ────────┤ Obtener dirección de LoadLibrary
    │                                              │
    └── CreateRemoteThread(hProcess,               │
          LoadLibraryA, pRemotePath) ──────────────┤ Crear hilo remoto que llama LoadLibrary
                                                   │
                                                   ├── LoadLibrary("C:\evil.dll")
                                                   │     La DLL maliciosa se carga
                                                   └── DllMain() se ejecuta

Pseudocódigo

# Classic DLL Injection (pseudocodigo, NO codigo funcional)
def classic_dll_injection(target_pid, dll_path):
    # 1. Abrir el proceso objetivo
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, False, target_pid)
    
    # 2. Reservar memoria en el proceso remoto
    remote_mem = VirtualAllocEx(
        hProcess, None, len(dll_path) + 1,
        MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE
    )
    
    # 3. Escribir la ruta de la DLL en la memoria remota
    WriteProcessMemory(hProcess, remote_mem, dll_path, len(dll_path) + 1)
    
    # 4. Obtener la direccion de LoadLibraryA
    hKernel32 = GetModuleHandle("kernel32.dll")
    loadlib_addr = GetProcAddress(hKernel32, "LoadLibraryA")
    
    # 5. Crear hilo remoto que ejecuta LoadLibrary con la ruta
    hThread = CreateRemoteThread(
        hProcess, None, 0, loadlib_addr, remote_mem, 0, None
    )
    
    # 6. La DLL se carga en el proceso objetivo
    WaitForSingleObject(hThread, INFINITE)
    CloseHandle(hThread)
    CloseHandle(hProcess)

Detección

IndicadorHerramientaEvent ID
CreateRemoteThread cross-processSysmonEvent ID 8
VirtualAllocEx + WriteProcessMemory en secuenciaEDR telemetryN/A
DLL cargada desde ubicación inusualSysmonEvent ID 7 (ImageLoaded)
Proceso accediendo a otro proceso con PROCESS_ALL_ACCESSSysmonEvent ID 10 (ProcessAccess)
DLL sin firma digital cargada en proceso firmadoEDRN/A

Debilidades de esta técnica: la DLL debe existir en disco (detectable por AV), CreateRemoteThread es muy monitorizado, y la ruta de la DLL queda visible en memoria.

Técnica 2: Reflective DLL Injection

Concepto

La reflective DLL injection (desarrollada por Stephen Fewer en 2008) resuelve la principal debilidad del classic injection: la necesidad de tener la DLL en disco. En vez de usar LoadLibrary (que requiere un archivo en disco), el malware implementa su propio loader en memoria.

Flujo de ejecución

1. Malware abre el proceso objetivo
2. Reserva memoria en el proceso con VirtualAllocEx
3. Escribe el contenido COMPLETO de la DLL (no la ruta, sino los bytes) en la memoria
4. Escribe un stub de carga (reflective loader) en la memoria
5. Ejecuta el stub, que:
   a. Parsea los PE headers de la DLL en memoria
   b. Resuelve las imports
   c. Aplica relocations
   d. Ejecuta DllMain

Por qué es más difícil de detectar

  • La DLL nunca toca el disco (no hay archivo que escanear)
  • No se llama a LoadLibrary (no aparece en logs de carga de DLLs)
  • La DLL no aparece en la lista de módulos del proceso (EnumProcessModules)
  • No genera un Sysmon Event ID 7 (ImageLoaded)

Uso real

Cobalt Strike usa reflective DLL injection como método principal de carga de su beacon. El beacon es una DLL que se inyecta reflectivamente en procesos como svchost.exe, rundll32.exe o dllhost.exe.

Metasploit incluye meterpreter como reflective DLL.

Detección

La detección de reflective injection es más difícil:

MétodoDescripción
Memory scanningBuscar PE headers (MZ/PE) en regiones de memoria que no corresponden a DLLs cargadas legítimamente
ETW (Event Tracing for Windows)Monitorizar asignaciones de memoria con permisos RWX (VirtualAllocEx con PAGE_EXECUTE_READWRITE)
EDR hooks en ntdllInterceptar llamadas a NtAllocateVirtualMemory, NtWriteVirtualMemory
Behavioral analysisDetectar el patrón: OpenProcess + VirtualAllocEx(RWX) + WriteProcessMemory + CreateRemoteThread

Técnica 3: DLL Side-Loading (T1574.002)

Concepto

DLL side-loading no inyecta en un proceso existente. En vez de eso, abusa del orden de búsqueda de DLLs de Windows: cuando un programa carga una DLL por nombre (sin ruta completa), Windows busca en este orden:

  1. Directorio de la aplicación
  2. Directorio del sistema (C:\Windows\System32)
  3. Directorio de Windows (C:\Windows)
  4. Directorio actual
  5. Directorios en PATH

Si el atacante coloca una DLL maliciosa con el nombre esperado en el directorio de la aplicación (posición 1), Windows la cargará antes que la DLL legítima del sistema.

Ejemplo práctico

Un ejecutable legítimo firmado por Microsoft (ej. OneDrive.exe) necesita cargar version.dll. Normalmente la carga de C:\Windows\System32\version.dll. Pero si el atacante coloca una version.dll maliciosa en el mismo directorio que OneDrive.exe, Windows carga la versión maliciosa.

Ventaja: el proceso que ejecuta el código malicioso es un ejecutable legítimo firmado. El EDR ve OneDrive.exe cargando una DLL, lo cual parece normal.

Binarios comúnmente abusados

Ejecutable legítimoDLL side-loadedGrupo que lo ha usado
OneDrive.exesecur32.dllAPT41, Mustang Panda
Teams.exeCRYPTBASE.dllMúltiples
vmnat.exelibvcruntime140.dllAPT29
Acrobat.exenppdf32.dllPlugX (Mustang Panda)
WinSCP.exeDragExt.dllBlackCat affiliates

Detección

MétodoDescripción
Hash comparisonComparar hash de DLLs cargadas con hashes conocidos de versiones legítimas
Path analysisAlertar cuando una DLL del sistema se carga desde un directorio no-sistema
Signature verificationDLLs del sistema deben estar firmadas por Microsoft. DLL side-loaded maliciosa no estará firmada
Sysmon Event ID 7ImageLoaded con path inusual para DLLs de sistema

Técnica 4: DLL Hollowing

Concepto

DLL hollowing combina elementos de DLL injection y process hollowing:

  1. Cargar una DLL legítima en el proceso objetivo (usando LoadLibrary normal)
  2. Vaciar el contenido de la DLL en memoria (NtUnmapViewOfSection o sobrescribir con VirtualProtect + memset)
  3. Escribir código malicioso en el espacio que ocupaba la DLL
  4. Ejecutar el código malicioso

Ventaja: la DLL aparece como cargada legítimamente en la lista de módulos del proceso. Su nombre y path son legítimos. Pero su contenido en memoria ha sido reemplazado.

Detección

  • Comparar el contenido en memoria de la DLL con su contenido en disco (hash mismatch)
  • Monitorizar cambios de permisos de memoria (VirtualProtect cambiando secciones de DLLs cargadas a PAGE_EXECUTE_READWRITE)

Técnica 5: APC Injection (T1055.004)

Concepto

APC (Asynchronous Procedure Call) injection usa un mecanismo legítimo de Windows para ejecutar código en otro hilo:

  1. Escribir shellcode o DLL en memoria del proceso objetivo
  2. Usar QueueUserAPC para encolar una función que ejecuta el código inyectado
  3. Cuando el hilo objetivo entra en un estado "alertable" (SleepEx, WaitForSingleObjectEx), ejecuta la APC

Variante: Early Bird injection

Early Bird injection usa APC injection en un proceso recién creado (en estado suspendido):

  1. Crear un proceso en estado suspendido (CreateProcess con CREATE_SUSPENDED)
  2. Escribir shellcode en la memoria del proceso
  3. Usar QueueUserAPC en el hilo principal suspendido
  4. Resumir el proceso (ResumeThread)
  5. El APC se ejecuta antes que el entry point del proceso

Esto es especialmente sigiloso porque el código malicioso se ejecuta muy temprano, antes de que el EDR pueda hookar las APIs del proceso.

Detección

IndicadorHerramienta
QueueUserAPC cross-processEDR, ETW
Proceso creado suspendido + APC + ResumeSysmon Event ID 1 + 8
Escritura en memoria de proceso suspendidoEDR

Mapeo MITRE ATT&CK

TécnicaIDSub-técnica
Process InjectionT1055Técnica padre
DLL InjectionT1055.001Classic injection con LoadLibrary
PE InjectionT1055.002Inyección de PE completo en memoria
Thread Execution HijackingT1055.003Secuestrar hilo existente
APC InjectionT1055.004Asynchronous Procedure Call
Thread Local StorageT1055.005Callback TLS
Process HollowingT1055.012Vaciado y reemplazo de proceso
DLL Search Order HijackingT1574.001Abuso del orden de búsqueda
DLL Side-LoadingT1574.002DLL maliciosa con nombre legítimo

Resumen: comparativa de técnicas

TécnicaDLL en discoDetección por AVDetección por EDRComplejidadUso en malware
Classic DLL InjectionAltaAltaBajaCommodity malware
Reflective DLL InjectionNoBajaMediaAltaCobalt Strike, APTs
DLL Side-LoadingSí (junto a exe legítimo)MediaMediaBajaAPTs, espionaje
DLL HollowingNo (reemplaza en memoria)BajaMedia-AltaAltaAPTs avanzados
APC InjectionNoBajaMediaMediaAPTs, loaders
Early BirdNoBajaBaja-MediaMediaEvasión de EDR

Fuentes y referencias

  • Fewer, S. "Reflective DLL Injection." 2008. https://github.com/stephenfewer/ReflectiveDLLInjection
  • Microsoft. "Dynamic-Link Library Search Order." Microsoft Docs.
  • MITRE ATT&CK. "Process Injection (T1055)." https://attack.mitre.org/techniques/T1055/
  • MITRE ATT&CK. "DLL Side-Loading (T1574.002)." https://attack.mitre.org/techniques/T1574/002/
  • Sikorski, M. & Honig, A. "Practical Malware Analysis." No Starch Press, 2012.
  • Russinovich, M. et al. "Windows Internals Part 1." Microsoft Press, 2017.
  • Elastic Security. "DLL Side-Loading Detection." Elastic SIEM Rules.
  • Red Canary. "2024 Threat Detection Report: Process Injection." Red Canary, 2024.
  • CrowdStrike. "Process Injection Techniques Used by Threat Actors." CrowdStrike, 2023.

Preguntas frecuentes

Artículos relacionados

Este contenido tiene fines exclusivamente educativos y de investigación en ciberseguridad defensiva. No se proporcionan binarios maliciosos ni payloads ejecutables. El uso indebido de esta información es responsabilidad exclusiva del usuario. Leer disclaimer completo.