Avanzadoprocess hollowingVolatilitymemory forensicsT1055.012process injectionMITRE ATT&CKanálisis de memoria

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.

MalwareIntel Research··10 min lectura
Serie: Casos de Uso — Parte 15

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 = &sections[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:

  1. Sin parámetros -k: svchost.exe siempre se ejecuta con -k [service_group]
  2. Proceso padre incorrecto: debería ser services.exe, no invoice.exe
  3. 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ácticaTécnicaIDDetalle
Defense EvasionProcess Injection: Process HollowingT1055.012Hollowing de svchost.exe
ExecutionUser Execution: Malicious FileT1204.002Ejecución del dropper invoice.exe
Credential AccessInput Capture: KeyloggingT1056.001Captura de credenciales bancarias
CollectionScreen CaptureT1113Screenshots en páginas bancarias
ExfiltrationExfiltration Over C2 ChannelT1041Envío de credenciales al C2
Command and ControlApplication Layer Protocol: Web ProtocolsT1071.001HTTPS beacon cada 30s

Resumen de técnicas de detección

MétodoEfectividadMomentoLimitaciones
Sysmon EID 25AltaTiempo realSolo Sysmon 13.0+
Sysmon EID 1 (cmdline)MediaTiempo realNo detecta hollowing directo, solo anomalías de proceso
Volatility malfindAltaPost-incidenteRequiere volcado de memoria
Volatility hollowfindMuy altaPost-incidenteSolo Volatility 2
ETW Kernel-ProcessAltaTiempo realComplejo de implementar
EDR (behavioral)VariableTiempo realDepende 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

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.