Movimiento lateral y Amcache: pivote por ProgramId entre hosts
Cuando confirmas herramientas del atacante en un host Windows, la siguiente pregunta siempre es: ¿dónde más? La delimitación del movimiento lateral — identificar cada otro host que alcanzó el atacante — es uno de los pasos más difíciles en una investigación, y Amcache es una de las herramientas más útiles para ello.
La razón: Amcache almacena dos pivotes cross-host que casi ningún otro artefacto de Windows almacena:
Hash— el SHA-1 de los primeros 31 MiB de cada PE que el appraiser vio.ProgramId— el hash de identidad de aplicación de 44 caracteres, estable entre hosts para la misma aplicación.
Un único Hash o ProgramId sospechoso en el Host A se convierte
en una consulta que puedes ejecutar contra los CSVs parseados de
Amcache de cualquier otro host que hayas recogido. Esta página es
el playbook completo.
Para los prerrequisitos, ver Referencia completa de Amcache, Amcache FileId explicado y Amcache ProgramId explicado.
El prerrequisito de recolección#
El patrón funciona solo si has recogido Amcache de muchos hosts de una forma que te permita hacer joins entre ellos. Dos patrones prácticos de recolección:
Recolección por host basada en KAPE#
Usa una única raíz de recolección con sub-directorios por host:
\\fileshare\incident-042\
├── HOST01\
│ └── Windows\AppCompat\Programs\Amcache.hve (+ logs)
├── HOST02\
│ └── ...
├── HOST03\
│ ...
Parsea con AmcacheParser apuntando a cada directorio por host:
Get-ChildItem '\\fileshare\incident-042' -Directory | ForEach-Object {
$host = $_.Name
AmcacheParser.exe `
-f "$($_.FullName)\Windows\AppCompat\Programs\Amcache.hve" `
--csv "\\fileshare\parsed\$host" `
--csvf "${host}_amcache.csv" `
--mp
}Acabas con <host>_amcache_UnassociatedFileEntries.csv por host,
todos en un directorio.
Hunt de flota con Velociraptor#
El artefacto Windows.Forensics.Amcache, ejecutado como hunt,
deposita la salida parseada por host en el servidor de
Velociraptor. Los CSVs se nombran con el hostname del host; las
mismas consultas cross-host de abajo aplican.
El pivote de hash#
El pivote más simple y de mayor precisión. Tienes un SHA-1 conocido-malo del Host A; encuentra cada otro host que lo tenga.
$badHash = 'da39a3ee5e6b4b0d3255bfef95601890afd80709'
Get-ChildItem -Recurse -Filter *_UnassociatedFileEntries.csv |
ForEach-Object {
$host = $_.PSChildName.Split('_')[0]
Import-Csv $_.FullName |
Where-Object { $_.Hash -eq $badHash } |
Select-Object @{n='Host';e={$host}}, FullPath, KeyLastWriteTimestamp, Size
} |
Sort-Object KeyLastWriteTimestampLa salida es una timeline por host de cuándo apareció por primera vez el binario malo en cada host. La marca de tiempo más temprana es tu candidato a paciente-cero; las marcas de tiempo posteriores son la propagación.
Cuándo las coincidencias de hash sobre-ajustan#
El pivote de hash se pierde rebuilds de la misma herramienta.
Los atacantes que recompilan su loader antes de cada movimiento
lateral tienen un hash diferente en cada host. Para esos, recurre
a ProgramId.
El pivote de ProgramId#
ProgramId es más perdonador que Hash — captura
recompilaciones que comparten nombre/publisher/versión incluso
cuando el contenido del binario difiere. Ver
Amcache ProgramId explicado
para cómo se construye la identidad.
$badProgramId = '0006fa0b2a9f8a4eb9d7c81e8b1f3c5d3e2a0000ffff'
Get-ChildItem -Recurse -Filter *_UnassociatedFileEntries.csv |
ForEach-Object {
$host = $_.PSChildName.Split('_')[0]
Import-Csv $_.FullName |
Where-Object { $_.ProgramId -eq $badProgramId } |
Select-Object @{n='Host';e={$host}}, FullPath, Hash, KeyLastWriteTimestamp
} |
Sort-Object KeyLastWriteTimestampEsto encuentra cada host que tiene cualquier binario
identificándose como la misma aplicación — incluso con hashes de
contenido diferentes. Empareja con el pivote de hash: hash para
coincidencias de alta precisión, ProgramId para coincidencias a
nivel familia.
Cuándo ProgramId sobre-ajusta#
ProgramId captura falsos positivos si el atacante se monta
sobre una identidad de aplicación legítima (p. ej. recompilar
herramientas nombradas PsExec.exe que obtienen el mismo
ProgramId que el genuino PsExec). Empareja con Hash para
desambiguar; una fila que coincida con ProgramId pero con un
hash que nadie más en tu entorno tiene es altamente sospechosa.
El pivote de patrón de ruta#
Para patrones de ruta de instalación de atacante conocidos, regex
contra FullPath:
$pattern = '\\AppData\\Roaming\\[a-z0-9]{8}\\update\.exe$'
Get-ChildItem -Recurse -Filter *_UnassociatedFileEntries.csv |
ForEach-Object {
$host = $_.PSChildName.Split('_')[0]
Import-Csv $_.FullName |
Where-Object { $_.FullPath -match $pattern } |
Select-Object @{n='Host';e={$host}}, FullPath, Hash, ProgramId, KeyLastWriteTimestamp
}Útil cuando:
- Conoces la convención de instalación del set de intrusión.
- El atacante rota hashes y metadatos pero reutiliza patrones de ruta.
- Quieres encontrar variantes que compartan estilo de ruta.
Empareja las coincidencias con hash y ProgramId de los
resultados por fila para construir una detección más rica.
Vista de propagación en serie temporal#
Para cada pivote, ordena los resultados por
KeyLastWriteTimestamp para ver la propagación a lo largo del
tiempo. Un patrón típico:
2026-04-01 14:23 HOST01 -- paciente cero, acceso inicial del atacante
2026-04-03 09:11 HOST02 -- 2 días después
2026-04-03 11:34 HOST07
2026-04-03 14:55 HOST09
2026-04-04 02:08 HOST15 -- fin de semana; atacante trabajando de noche
2026-04-04 02:33 HOST22
2026-04-04 02:51 HOST31
Dos lecturas:
- La cadencia (múltiples hosts dentro de horas entre sí) es característica de herramientas automatizadas de movimiento lateral (basadas en PsExec / WMI / SMB).
- La ráfaga nocturna es el patrón típico del atacante: acceso inicial durante horario laboral, luego movimiento acelerado una vez que tiene credenciales y control.
Usa estos patrones para acotar en tiempo el resto de tu
recolección de evidencia. Extrae Sysmon / Security 4624 / 4688
para cada host en su ventana KeyLastWriteTimestamp ± 1 h —
obtienes las líneas de comandos reales del atacante y los eventos
de credenciales con alta precisión.
Cross-pivote de evidencia de Driver y Dispositivo#
El patrón cross-host no se limita a
*_UnassociatedFileEntries.csv. Para investigaciones más
profundas, ejecuta los mismos patrones de pivote contra:
*_DriverBinaries.csv#
Para investigaciones BYOVD — un driver vulnerable que el
atacante cargó en un host casi con seguridad está cargado en los
otros que alcanzó. Consulta por Hash o DriverName del driver:
$badDriver = 'mhyprot2.sys'
Get-ChildItem -Recurse -Filter *_DriverBinaries.csv |
ForEach-Object {
$host = $_.PSChildName.Split('_')[0]
Import-Csv $_.FullName |
Where-Object { $_.DriverName -eq $badDriver } |
Select-Object @{n='Host';e={$host}}, DriverName, Service, DriverSigned, KeyLastWriteTimestamp
}*_DeviceContainers.csv#
Para investigaciones en las que el atacante conectó hardware
(raro en ataques remotos, central en casos de amenaza interna) —
consulta por Manufacturer o FriendlyName:
$suspiciousVendor = 'HakShop'
Get-ChildItem -Recurse -Filter *_DeviceContainers.csv |
ForEach-Object {
$host = $_.PSChildName.Split('_')[0]
Import-Csv $_.FullName |
Where-Object { $_.Manufacturer -match $suspiciousVendor } |
Select-Object @{n='Host';e={$host}}, FriendlyName, Manufacturer, KeyLastWriteTimestamp
}Ver Historia de USB y dispositivos en Amcache para los patrones del lado de dispositivos en detalle.
Combinar con fuentes no-Amcache#
El pivote de Amcache te dice dónde se inventarió el binario. Para confirmar ejecución e identificar el método de movimiento, correlaciona con:
- 4624 (Logon) + 4625 (Failed logon) en los hosts de destino — ¿cuándo se autenticó el atacante y como quién?
- 4648 (Explicit credential logon) — movimiento lateral con credenciales (PsExec, RDP con credenciales pasadas).
- Sysmon 1 / 4688 (Process create) con proceso padre — ¿el
proceso del atacante se generó bajo
services.exe(PsExec / servicio remoto), bajowmiprvse.exe(WMI) o bajoexplorer.exe(interactivo)? - Sysmon 3 (Network connect) + Sysmon 22 (DNS query) — C2 saliente.
- Árboles de proceso de Velociraptor / EDR — los mismos datos, más fáciles de navegar.
Un único pivote de Amcache delimitando la propagación, unido a eventos de autenticación y proceso por host en los hosts coincidentes, te da una timeline defendible de: quién, cuándo, desde dónde, vía qué binario, usando qué credencial.
Cuando el pivote falla#
Tres situaciones donde el pivote cross-host de Amcache rinde mal:
El appraiser no ha corrido aún en los hosts de destino#
Si el atacante se movió lateralmente dentro de horas de tu recolección, los appraisers de los hosts de destino pueden no haber inventariado el binario aún. Amcache los muestra como limpios. Re-recoge 24–48 horas después; la propagación aparecerá.
El atacante limpió Amcache en cada host que alcanzó#
Poco común (sobre todo porque es ruidoso y la mayoría de los atacantes no se molestan) pero posible. Usa el flujo de recuperación de Volume Shadow Copy en Dónde está Amcache.hve en disco en cada host donde sospeches limpieza.
El atacante usó binarios diferentes por host#
Si el atacante generó implantes por host (malware verdaderamente
por víctima), los pivotes de hash y ProgramId fallan por
diseño. Los patrones de ruta y detecciones comportamentales más
amplias (logon 4624 desde la misma IP inusual a través de muchos
hosts) se vuelven primarias.
Ver también#
- Referencia completa de Amcache — el artefacto al completo.
- Amcache FileId explicado — el pivote de hash de contenido.
- Amcache ProgramId explicado — el pivote de identidad de aplicación.
- Amcache para investigación de malware — triage de un solo host que produce los indicadores malos con los que pivotas entre hosts.
- Recuperar evidencia de binarios borrados desde Amcache — cuando el binario del host de destino fue borrado después del movimiento.
Para explorar tus propios hives recogidos sin instalar nada, suelta un archivo en la página de inicio del parser — se parsea enteramente en tu navegador.
Artículos relacionados
- Volatility y Amcache: extraer el hive de imágenes de memoria
Una guía práctica para recuperar Amcache de una imagen de memoria de Windows usando Volatility — cuándo la recuperación del lado de memoria es la única opción, qué plugins usar y cómo entregar a AmcacheParser.
- Plugin amcache de RegRipper: qué hace y cuándo usarlo
Una guía práctica del plugin amcache de RegRipper — qué parsea, en qué se diferencia su salida de texto del CSV de AmcacheParser y cuándo recurrir a él en lugar de (o junto con) la herramienta de Zimmerman.
- Las columnas de salida de AmcacheParser explicadas: cada campo CSV decodificado
Referencia campo por campo para la salida CSV de AmcacheParser — FileId, PathHash, ProgramId, LinkDate, BinFileVersion, IsPeFile y cualquier otra columna, con los pivotes que importan en DFIR.
- Guía de descarga de AmcacheParser: fuentes oficiales, mirrors y verificación
Todas las formas de descargar AmcacheParser de Eric Zimmerman — Get-ZimmermanTools, descarga directa, KAPE, Velociraptor — con verificación por suma de control y patrones de instalación en redes aisladas.