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.
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
| Indicador | Herramienta | Event ID |
|---|---|---|
CreateRemoteThread cross-process | Sysmon | Event ID 8 |
VirtualAllocEx + WriteProcessMemory en secuencia | EDR telemetry | N/A |
| DLL cargada desde ubicación inusual | Sysmon | Event ID 7 (ImageLoaded) |
Proceso accediendo a otro proceso con PROCESS_ALL_ACCESS | Sysmon | Event ID 10 (ProcessAccess) |
| DLL sin firma digital cargada en proceso firmado | EDR | N/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étodo | Descripción |
|---|---|
| Memory scanning | Buscar 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 ntdll | Interceptar llamadas a NtAllocateVirtualMemory, NtWriteVirtualMemory |
| Behavioral analysis | Detectar 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:
- Directorio de la aplicación
- Directorio del sistema (C:\Windows\System32)
- Directorio de Windows (C:\Windows)
- Directorio actual
- 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ítimo | DLL side-loaded | Grupo que lo ha usado |
|---|---|---|
| OneDrive.exe | secur32.dll | APT41, Mustang Panda |
| Teams.exe | CRYPTBASE.dll | Múltiples |
| vmnat.exe | libvcruntime140.dll | APT29 |
| Acrobat.exe | nppdf32.dll | PlugX (Mustang Panda) |
| WinSCP.exe | DragExt.dll | BlackCat affiliates |
Detección
| Método | Descripción |
|---|---|
| Hash comparison | Comparar hash de DLLs cargadas con hashes conocidos de versiones legítimas |
| Path analysis | Alertar cuando una DLL del sistema se carga desde un directorio no-sistema |
| Signature verification | DLLs del sistema deben estar firmadas por Microsoft. DLL side-loaded maliciosa no estará firmada |
| Sysmon Event ID 7 | ImageLoaded con path inusual para DLLs de sistema |
Técnica 4: DLL Hollowing
Concepto
DLL hollowing combina elementos de DLL injection y process hollowing:
- Cargar una DLL legítima en el proceso objetivo (usando
LoadLibrarynormal) - Vaciar el contenido de la DLL en memoria (NtUnmapViewOfSection o sobrescribir con VirtualProtect + memset)
- Escribir código malicioso en el espacio que ocupaba la DLL
- 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:
- Escribir shellcode o DLL en memoria del proceso objetivo
- Usar
QueueUserAPCpara encolar una función que ejecuta el código inyectado - 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):
- Crear un proceso en estado suspendido (
CreateProcessconCREATE_SUSPENDED) - Escribir shellcode en la memoria del proceso
- Usar
QueueUserAPCen el hilo principal suspendido - Resumir el proceso (
ResumeThread) - 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
| Indicador | Herramienta |
|---|---|
QueueUserAPC cross-process | EDR, ETW |
| Proceso creado suspendido + APC + Resume | Sysmon Event ID 1 + 8 |
| Escritura en memoria de proceso suspendido | EDR |
Mapeo MITRE ATT&CK
| Técnica | ID | Sub-técnica |
|---|---|---|
| Process Injection | T1055 | Técnica padre |
| DLL Injection | T1055.001 | Classic injection con LoadLibrary |
| PE Injection | T1055.002 | Inyección de PE completo en memoria |
| Thread Execution Hijacking | T1055.003 | Secuestrar hilo existente |
| APC Injection | T1055.004 | Asynchronous Procedure Call |
| Thread Local Storage | T1055.005 | Callback TLS |
| Process Hollowing | T1055.012 | Vaciado y reemplazo de proceso |
| DLL Search Order Hijacking | T1574.001 | Abuso del orden de búsqueda |
| DLL Side-Loading | T1574.002 | DLL maliciosa con nombre legítimo |
Resumen: comparativa de técnicas
| Técnica | DLL en disco | Detección por AV | Detección por EDR | Complejidad | Uso en malware |
|---|---|---|---|---|---|
| Classic DLL Injection | Sí | Alta | Alta | Baja | Commodity malware |
| Reflective DLL Injection | No | Baja | Media | Alta | Cobalt Strike, APTs |
| DLL Side-Loading | Sí (junto a exe legítimo) | Media | Media | Baja | APTs, espionaje |
| DLL Hollowing | No (reemplaza en memoria) | Baja | Media-Alta | Alta | APTs avanzados |
| APC Injection | No | Baja | Media | Media | APTs, loaders |
| Early Bird | No | Baja | Baja-Media | Media | Evasió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
Libros recomendados
Artículos relacionados
Anatomía de un PE: Entendiendo los Ejecutables de Windows para Análisis de Malware
Process Hollowing y Process Doppelgänging: Técnicas de Suplantación de Procesos
Windows API Calls Más Usadas por Malware: Guía de Referencia para Analistas
De Alerta EDR a Informe Ejecutivo: Caso End-to-End Completo
ANY.RUN: Triaje de Fichero Sospechoso a IOCs en 5 Minutos
BlackCat/ALPHV: Doble Extorsión y Data Leak Investigation
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.