Caza de malware comodín con Amcache

Cuando llegas a un host Windows que "huele raro" — un usuario reportó comportamiento extraño, un EDR lanzó una alerta de baja confianza, un log de firewall muestra algo que el host no debería estar haciendo — Amcache es uno de los artefactos más rápidos para darte una respuesta sí/no sobre "¿hay herramientas del atacante obvias aquí?".

Esta página es el playbook de triage de malware comodín: los filtros, pivotes y consultas específicos que sacan a la luz los artefactos típicos del atacante en la estación de trabajo típica infectada.

Para el background del artefacto, ver la referencia completa de Amcache; para combinar Amcache con otra evidencia de ejecución, ver Amcache vs Prefetch, Amcache vs ShimCache y Amcache vs SRUM.


Por qué Amcache es la primera parada correcta#

Tres propiedades hacen de Amcache el primer artefacto natural en un triage de malware:

  1. Registra el SHA-1 de cada PE que el appraiser vio. Ese hash va directo a una consulta de VirusTotal o feed de TI.
  2. Registra la ruta completa. La ruta es la mitad de la historia para el triage de malware comodín — cualquier cosa en \Users\<x>\AppData\Local\Temp\ o \ProgramData\ es sospechosa por defecto.
  3. Sobrevive al borrado del binario. Ver Recuperar evidencia de binarios borrados desde Amcache.

Juntos: parsea, filtra, comprueba hashes, y tienes una respuesta defendible a "¿está este host comprometido?" en minutos.


El filtro de triage base#

Aplica esto a *_UnassociatedFileEntries.csv primero, cada vez:

Import-Csv .\HOST_amcache_UnassociatedFileEntries.csv |
  Where-Object {
    $_.IsPeFile -eq 'True' -and
    -not $_.Publisher    -and
    $_.FullPath -match '\\Users\\|\\ProgramData\\|\\AppData\\|\\Temp\\|\\Public\\'
  } |
  Select-Object KeyLastWriteTimestamp, FullPath, Hash, Size, LinkDate |
  Sort-Object KeyLastWriteTimestamp -Descending

Qué saca a la luz:

  • Binarios PE sin firmar en rutas en las que un usuario normal puede escribir.

Qué se pierde (y para lo cual necesitas filtros de seguimiento):

  • Binarios firmados-pero-maliciosos (ransomware firmado, RATs firmados).
  • Binarios en rutas protegidas (\Windows\System32\ — requeriría admin para dejar, pero ocurre con escalada de privilegios).
  • Binarios living-off-the-land (LOLBINs) — esos están firmados y legítimamente en \Windows\System32\.

Este filtro típicamente devuelve 5–50 filas en una estación de trabajo típica infectada. La mayoría son falsos positivos (apps portables, herramientas de desarrollo, scripts personalizados). Triage desde ahí.


Controles de falsos positivos#

Algunos patrones que filtran las filas benignas obvias rápidamente:

Excluir rutas de desarrollador / apps portables#

$benignPaths = @(
    '\\AppData\\Local\\JetBrains\\',
    '\\AppData\\Local\\Programs\\Microsoft VS Code\\',
    '\\AppData\\Local\\Programs\\Slack\\',
    '\\AppData\\Local\\Programs\\Notion\\',
    '\\AppData\\Roaming\\Spotify\\',
    '\\AppData\\Local\\GitHubDesktop\\',
    '\\AppData\\Local\\Microsoft\\Teams\\',
    '\\AppData\\Local\\Discord\\',
    '\\AppData\\Local\\1Password\\'
)
 
$rows | Where-Object {
    $path = $_.FullPath
    -not ($benignPaths | Where-Object { $path -match $_ })
}

Ajusta la lista al herramental estándar de desarrollador / power-user de tu entorno. Una línea base de "apps portables conocidas en rutas de usuario" vale la pena mantener una vez por entorno.

Excluir publishers conocidos por hash#

Si tienes una lista de hashes conocidos como buenos (tu allowlist interno, NSRL, feed de hashes limpios de Cisco Talos), une la columna Hash de Amcache contra ella y descarta coincidencias.

Excluir nombres de señuelo de atacante muy comunes que confías en otros sitios#

update.exe, service.exe, svchost.exe en rutas de usuario son sospechosos porque comparten nombres con binarios legítimos de Windows — los nombres solos no son la señal; la ruta + publisher ausente sí. El filtro base ya los captura.


Patrones de atacante de alta precisión#

Una vez que tienes la lista filtrada, estos patrones son típicamente indicadores de alta precisión en un endpoint Windows típico:

\AppData\Local\Temp\ + PE + sin firmar#

C:\Users\bob\AppData\Local\Temp\xyz1234.tmp.exe
C:\Users\bob\AppData\Local\Temp\setup_temp\install.exe

Casi nunca un patrón benigno de desarrollador. Común para:

  • Droppers de acceso inicial de adjuntos de phishing.
  • Payloads de macros de Office.
  • Descargas entregadas por navegador que se ejecutan desde Temp.

Nombres de archivo sospechosos que imitan componentes del SO#

C:\Users\Public\Documents\svchost.exe
C:\ProgramData\msmpeng.exe
C:\Users\bob\AppData\Roaming\winupdate.exe

La combinación de un nombre estilo componente-del-SO y una ruta en la que ningún componente del SO se sentaría nunca es un indicador de malware casi seguro.

Clusters de LinkDate#

Ordena la lista filtrada por LinkDate:

$rows | Sort-Object LinkDate

Busca clusters: 3-10 binarios con valores LinkDate dentro de unas pocas horas entre sí. Los atacantes frecuentemente compilan su toolkit completo en una sola sesión, y las marcas de link se agrupan. Esta es una señal fuerte de "esto es una campaña".

Coincidencias solo de Hash en Unassociated#

Toma cada Hash de tus filas filtradas y comprueba si aparece en algún sitio en *_AssociatedFileEntries.csv (es decir, vinculado a una aplicación instalada). Si el mismo hash aparece Asociado en este host o cualquier otro host recogido, el binario tiene un contexto benigno-o-rastreado en otro sitio. Si aparece solo como Unassociated y solo en este único host, eso aumenta la sospecha.


Confirmar ejecución#

Una fila en Amcache significa que el binario estaba en disco en la hora del appraiser; no significa que corrió. Para confirmar ejecución:

Prefetch#

Para cada fila sospechosa, comprueba si C:\Windows\Prefetch\ contiene un .pf para ese binario:

NOTEPAD.EXE-1A2B3C4D.pf
XYZ1234.TMP.EXE-FEDCBA98.pf

Un .pf es evidencia definitiva de ejecución. Parsea Prefetch con PECmd.exe para obtener las marcas de tiempo de ejecución. Ver Amcache vs Prefetch para la comparación completa.

Security 4688 / Sysmon 1#

Si la auditoría de creación de procesos está habilitada (debería estarlo), cada lanzamiento registra un evento 4688 o Sysmon 1 con la línea de comandos completa. Filtra a la ruta del binario y obtienes cada ejecución con argumentos — normalmente el dato único más útil en un triage de malware.

SRUM#

Si el binario usó CPU o red medible, SRUM (SRUDB.dat) tiene una fila a nivel hora para él. Ver Amcache vs SRUM. Especialmente útil para actividad de red — si SRUM muestra que el binario envió gigabytes de bytes de red, esa es tu timeline de exfiltración de datos.


Delimitar el incidente entre hosts#

Una vez que has confirmado al menos un binario malo en un host, la pregunta se vuelve: ¿dónde más existe esto?

Pivote de hash a través del Amcache recogido#

$badHashes = @('da39a3ee5e6b4b0d3255bfef95601890afd80709',
               '1234567890abcdef1234567890abcdef12345678')
 
Get-ChildItem -Recurse -Filter *_UnassociatedFileEntries.csv |
  ForEach-Object {
    $host = $_.PSChildName.Split('_')[0]
    Import-Csv $_.FullName |
      Where-Object { $badHashes -contains $_.Hash } |
      Select-Object @{n='Host';e={$host}}, FullPath, KeyLastWriteTimestamp
  } |
  Sort-Object KeyLastWriteTimestamp

Esto te dice cada host recogido que alguna vez tuvo cualquiera de los hashes malos, ordenado por hora vista por el appraiser. A menudo revela el paciente cero (marca de tiempo más temprana) y la propagación (marcas de tiempo posteriores en otros hosts).

Pivote ProgramId para familias de herramientas#

$badProgramIds = @('0006fa0b2a9f8a4eb9d7c81e8b1f3c5d3e2a0000ffff')
 
Get-ChildItem -Recurse -Filter *_UnassociatedFileEntries.csv |
  ForEach-Object {
    $host = $_.PSChildName.Split('_')[0]
    Import-Csv $_.FullName |
      Where-Object { $badProgramIds -contains $_.ProgramId } |
      Select-Object @{n='Host';e={$host}}, FullPath, Hash, KeyLastWriteTimestamp
  }

ProgramId captura coincidencias a nivel familia que Hash se pierde (rebuilds con los mismos metadatos). Ver Amcache ProgramId explicado.

Pivote por patrón de ruta#

Get-ChildItem -Recurse -Filter *_UnassociatedFileEntries.csv |
  ForEach-Object {
    $host = $_.PSChildName.Split('_')[0]
    Import-Csv $_.FullName |
      Where-Object {
        $_.FullPath -match '\\AppData\\Roaming\\[a-z0-9]{8}\\update\.exe$'
      } |
      Select-Object @{n='Host';e={$host}}, FullPath, Hash, KeyLastWriteTimestamp
  }

Para patrones de ruta de atacante conocidos (una ubicación de instalación específica que usa un set de intrusión), pivota por regex de ruta en lugar de hash.


El flujo completo de triage#

Un flujo end-to-end repetible:

  1. Recoge Amcache (Amcache.hve + .LOG1 + .LOG2) del host sospechoso.
  2. Parsea con AmcacheParser.exe --mp.
  3. Aplica el filtro base a *_UnassociatedFileEntries.csv.
  4. Aplica controles de falsos positivos (apps portables conocidas, hashes de allowlist).
  5. Triage del resto — VirusTotal cada Hash, mira las rutas y nombres sospechosos.
  6. Confirma ejecución vía Prefetch / 4688 / Sysmon para cada fila confirmada-mala.
  7. Acota en el tiempo el incidente: toma el KeyLastWriteTimestamp más temprano y el tiempo de ejecución más tardío de Prefetch; esa ventana es tu marco temporal del incidente.
  8. Delimita la propagación vía pivotes de hash / ProgramId a través de todos los archivos Amcache recogidos.
  9. Confirma la limpieza: re-ejecuta tras la contención para verificar que las filas malas ya no tienen nuevas corridas de Prefetch correspondientes.

Este flujo lleva horas, no días, y funciona en la inmensa mayoría de los engagements de malware comodín sin EDR especializado.


Ver también#

Para hacer triage de un hive ahora mismo sin instalar nada, suelta el archivo en la página de inicio del parser — se parsea enteramente en tu navegador.

Artículos relacionados

Volver a todos los artículos