Marcas de tiempo de Amcache explicadas: KeyLastWriteTimestamp vs LinkDate vs el resto

Amcache expone múltiples marcas de tiempo diferentes, y confundirlas es el error más común que cometen los analistas nuevos de Amcache. Datar mal un hallazgo y toda la timeline se derrumba. Esta página es la referencia completa: cada marca de tiempo que Amcache expone, qué representa realmente y sobre cuál deberías pivotar para cualquier pregunta dada.

Para el contexto más amplio de Amcache, ver la referencia completa de Amcache; para la estructura del registro circundante, ver Estructura del registro Amcache.


Las marcas de tiempo de un vistazo#

Marca de tiempo Origen Representa
KeyLastWriteTimestamp Metadatos de la clave del registro Cuándo el appraiser escribió esta entrada por última vez. Lo más cercano a "cuándo registró Amcache esto".
LinkDate PE IMAGE_FILE_HEADER.TimeDateStamp Cuándo se compiló / enlazó el binario. Controlable por el atacante.
InstallDate Valor de InventoryApplication Cuándo se instaló la aplicación.
MsiInstallDate Valor de InventoryApplicationFile Cuándo se instaló el MSI padre (si lo hay).
LastModified Valor del hive (depende del schema) Un marcador de last-modified, presente en algunas versiones del schema.
LastWriteTimestamp (legacy Programs) Metadatos de la clave del registro Misma idea que KeyLastWriteTimestamp, pero para el schema legacy Root\Programs.

La regla más importante:

KeyLastWriteTimestamp es el pivote "cuándo se vio esto en este host". Todo lo demás es una pregunta diferente.


KeyLastWriteTimestamp#

Esta es la hora de última escritura a nivel del registro de la clave que contiene la entrada. Es metadato del propio hive del registro — Windows la actualiza cada vez que cambia el contenido de la clave.

Para Root\InventoryApplicationFile\<entry>, el KeyLastWriteTimestamp se actualiza cada vez que el appraiser escribe o actualiza esa entrada. En la práctica esto significa:

  • La primera vez que el appraiser inventaría un archivo, se crea la clave y su KeyLastWriteTimestamp es la hora del inventario.
  • Si los metadatos del archivo cambian entre inventarios (tamaño, hash, versión), la clave se reescribe y la marca de tiempo avanza.
  • Si nada cambia entre inventarios, la marca de tiempo se queda donde está — incluso si el appraiser volvió a correr y confirmó que el archivo sigue presente.

Ese último punto importa: KeyLastWriteTimestamp no es "la hora más reciente en que el appraiser vio este archivo". Es "la hora más reciente en que el appraiser escribió sobre este archivo". Para un archivo estable, sin cambios, la marca de tiempo puede tener semanas o meses aunque el archivo haya estado presente todo ese tiempo.

Para qué es bueno KeyLastWriteTimestamp#

  • Aproximaciones de first-seen. Para un binario que el atacante dejó nuevo en un host limpio, KeyLastWriteTimestamp es la hora de la corrida del appraiser después del drop. Sujeto a:
    • el appraiser no corre instantáneamente — hay hasta ~24 h de retraso en estaciones de trabajo, más largo en servidores,
    • el binario debe seguir presente en la hora del appraiser (binarios transitorios borrados antes de la siguiente pasada pueden no aparecer nunca),
    • la resolución de la marca de tiempo es la que escriba el appraiser — típicamente precisión de segundo.
  • Joins por ventana de tiempo. Una vez que tienes una entrada sospechosa, toma su KeyLastWriteTimestamp ± tu ventana elegida (una hora es un default común) y une todos los demás CSVs (Prefetch, Sysmon, Security 4688) sobre esa ventana. Obtienes la historia completa de lo que ocurrió alrededor del evento de inventario.
  • Detección de reemplazo binario. Si dos filas de InventoryApplicationFile comparten el mismo FullPath pero tienen diferentes valores de Hash y diferentes valores de KeyLastWriteTimestamp, el binario en esa ruta cambió entre esos dos momentos. Ordena por marca de tiempo para ver la secuencia.

Para qué no es bueno KeyLastWriteTimestamp#

  • "¿Cuándo existió por primera vez este binario en disco?" — esa es una pregunta del sistema de archivos ($STANDARD_INFORMATION.CreationTime en la MFT). KeyLastWriteTimestamp es como mucho un límite superior: el archivo existió en disco no más tarde de la marca de tiempo, pero probablemente antes.
  • "¿Cuándo se ejecutó este binario?" — Amcache registra presencia, no ejecución. Usa Prefetch.
  • Precisión por debajo del segundo. No saques conclusiones de unos pocos cientos de milisegundos.

LinkDate#

El TimeDateStamp del header PE — el valor que el linker estampó en el IMAGE_FILE_HEADER del binario en hora de compilación/ enlazado. Cada PE tiene uno.

Para qué es bueno LinkDate#

  • Agrupar binarios por campaña de build. Si ordenas todos los PEs no asociados de un host por LinkDate, ves frecuentemente clusters ajustados: 3–10 binarios todos estampados en el mismo día u hora. Eso suele ser un único atacante compilando su toolkit completo en una sola sesión.
  • Detectar builds sospechosamente antiguos o nuevos. Un driver compilado en 2014 que aparece por primera vez en tu Amcache hoy es una bandera de BYOVD. Un binario compilado en el futuro es una bandera de juego con el reloj o herramientas descuidadas.
  • Confirmar que un build pertenece a la campaña esperada. "Nuestra herramienta interna siempre se linkdate los lunes a las 03:00 UTC; esta es el martes a las 14:00 — investigar."

Para qué no es bueno LinkDate#

  • "¿Cuándo apareció este binario en este host?" Controlable por el atacante. Un atacante puede establecer el TimeDateStamp que quiera en hora de enlazado, y a veces se establece a 0 deliberadamente (para builds reproducibles) o a una fecha en el pasado (para hacer parecer el binario antiguo/establecido). Confiar en LinkDate como pivote de presencia en el host produce hallazgos incorrectos.
  • Identidad criptográfica. LinkDate por sí solo no es único; muchos binarios comparten la misma marca de link.

InstallDate (en InventoryApplication)#

Cuándo se instaló la aplicación, en formato FILETIME del registro. Útil para:

  • Cruzar con KeyLastWriteTimestamp en los registros de archivo. Si el KeyLastWriteTimestamp de un archivo es significativamente más antiguo que el InstallDate de su aplicación padre, algo es inusual — el archivo parece haber estado en disco antes de que la aplicación existiera según Windows.
  • Detectar instalaciones silenciosas. Las aplicaciones instaladas sin interacción del usuario a veces dejan InstallDate cerca de 1601-01-01 (la época FILETIME) o en fechas futuras poco realistas. Ambas son banderas.

MsiInstallDate (en InventoryApplicationFile)#

La fecha de instalación del MSI padre para archivos que vinieron de un instalador MSI. Mismo formato FILETIME que InstallDate. Útil para distinguir archivos que llegaron vía una instalación MSI correcta de archivos que llegaron vía copia / drop.


LastModified (cuando está presente)#

Algunas versiones del schema de Amcache exponen un valor LastModified por archivo. No todos los hives lo tienen. Cuando está presente, trátalo como el tiempo de última modificación del sistema de archivos tal como el appraiser lo vio en el inventario — no como autoritativo. El $STANDARD_INFORMATION de la MFT es la fuente autoritativa.


LastWriteTimestamp en Programs legacy#

El schema legacy Root\Programs expone un LastWriteTimestamp por entrada que es conceptualmente idéntico a KeyLastWriteTimestamp en el schema moderno. Aplican las mismas advertencias.


El pivote estándar acotado en el tiempo#

El patrón de investigación en el que la mayoría de los analistas se estandarizan:

  1. Identifica una fila sospechosa en *_UnassociatedFileEntries.csv (típicamente vía "PE sin firmar en ruta escribible por usuario").
  2. Toma su KeyLastWriteTimestamp.
  3. Define una ventana de una hora centrada en esa marca de tiempo.
  4. Extrae de esa ventana:
    • Todas las demás filas de Amcache (cross-key — drivers, dispositivos, accesos directos).
    • Todas las entradas de Prefetch (ejecución definitiva).
    • Todos los eventos de creación de proceso Security 4688.
    • Todos los eventos de Sysmon 1 (process create), 7 (image load) y 11 (file create).
    • Todas las creaciones del sistema de archivos desde la MFT y el journal USN.
  5. La timeline resultante es la imagen completa de lo que ocurrió alrededor de ese evento de inventario.

Este es el join canónico "¿qué estaba haciendo el atacante en este minuto?", y KeyLastWriteTimestamp es el ancla que lo hace posible.


Un ejemplo trabajado#

Ves dos filas de Amcache para la misma ruta:

FullPath: C:\Users\bob\AppData\Local\Temp\notepad.exe
Row A:   KeyLastWriteTimestamp = 2026-03-12 14:23:11 UTC
         Hash                  = aaaaaaaa...
         LinkDate              = 2018-04-03 09:00:00 UTC
         Publisher             = ""

Row B:   KeyLastWriteTimestamp = 2026-04-19 02:14:55 UTC
         Hash                  = bbbbbbbb...
         LinkDate              = 2018-04-03 09:00:00 UTC
         Publisher             = ""

Leyendo esto:

  • LinkDate es idéntico. Ese es el TimeDateStamp en el header PE — el atacante reutilizó la misma identidad de build, o usó una plantilla que linkstampa cada build igual. No es evidencia de hora de build.
  • Hash difiere. Diferente contenido de archivo estuvo en la ruta en los dos momentos KeyLastWriteTimestamp.
  • KeyLastWriteTimestamp difiere. Amcache vio la ruta dos veces, con ~5 semanas de diferencia, con contenido diferente cada vez.

Conclusión: un binario en esta ruta fue reemplazado entre el 12 de marzo y el 19 de abril. Pivota sobre la marca de tiempo del 19 de abril ± 1 h para el evento de drop del nuevo binario; pivota sobre el 12 de marzo ± 1 h para el drop original. Dos eventos de intrusión; una ruta; una entrada de Amcache para encontrar ambos.


Ver también#

Para explorar marcas de tiempo en tu propio hive sin instalar nada, suelta un archivo en la página de inicio del parser — se parsea enteramente en tu navegador.

Artículos relacionados

Volver a todos los artículos