← Volver al blog

Detectar timestomping y antiforense en el journal USN

Los atacantes que editan timestamps del MFT no pueden esconderse del change journal. Cómo las discrepancias $STANDARD_INFORMATION vs $FILE_NAME y los BasicInfoChange inesperados delatan la actividad antiforense.

5 min de lectura

Los operadores sofisticados no solo borran la evidencia — intentan camuflar lo que dejan. La técnica más común es el timestomping: editar los timestamps NTFS de un archivo para que parezca inocente (o fuera de la ventana de investigación). Solía funcionar. Con el journal USN activo, deja señal clara.

Este artículo recorre lo que el timestomping hace al disco, cómo el journal lo expone y qué otros movimientos antiforense puedes pillar con el mismo artefacto.

Repaso rápido a los timestamps NTFS

Cada entrada MFT lleva timestamps en dos atributos:

  • $STANDARD_INFORMATION (SI): los timestamps que las herramientas de userland y la mayoría de APIs pueden cambiar. Lo que muestran dir, el Explorador y Get-ChildItem. Formato documentado en la referencia NTFS de Microsoft.
  • $FILE_NAME (FN): los timestamps que NTFS pone internamente en cada atributo $FILE_NAME. Suele haber uno por nombre (el archivo puede tener varios nombres si está hard-linkeado). Son mucho más difíciles de cambiar — requieren acceso a kernel o herramientas especializadas.

Las herramientas de timestomping (SetMACE, el timestomp.exe histórico del módulo antiforense de Metasploit, varios implants custom) suelen apuntar a los timestamps SI. Algunas ahora apuntan también a FN. En ambos casos, tocan el MFT — y ese toque enciende el journal.

Qué registra el journal para una edición de timestamp

Cuando se escriben los timestamps SI, NTFS emite un registro BasicInfoChange | Close. Ese registro es el smoking gun, porque:

  • Un «touch» legítimo produce un BasicInfoChange | Close junto con un DataExtend o DataOverwrite de la escritura real que disparó la actualización de timestamps.
  • Un timestomp produce un BasicInfoChange | Close solo, sin escritura previa en el mismo FileReferenceNumber.

Cuando ves BasicInfoChange | Close sin DataOverwrite, DataExtend o FileCreate en la misma sesión de handle, estás mirando manipulación de metadatos — casi siempre timestomping o cambios de atributo (banderas read-only/hidden).

La comparación clásica: SI vs FN

La detección de timestomping más autoritativa compara los timestamps $STANDARD_INFORMATION de cada archivo con sus timestamps $FILE_NAME. Los investigadores de Mandiant escriben sobre esto hace años; el white paper histórico de Mandiant sobre timestomping es la referencia, y Brian Carrier lo cubre en File System Forensic Analysis.

El journal complementa más que reemplaza la comparación:

  • La comparación MFT dice que el timestomping ocurrió en algún momento. No puede decir cuándo.
  • Los BasicInfoChange | Close del journal dicen exactamente cuándo se hizo la escritura SI, y qué contexto de proceso la rodeó (apareado con Security.evtx 4663).

Un archivo timestompeado se ve así en tus datos:

  1. La comparación MFT marca SI < FN (o SI en el futuro de FN, etc.).
  2. El journal tiene un BasicInfoChange | Close a, digamos, 2026-04-12 03:08:14 sin escrituras alrededor.
  3. Ese timestamp es el que pones en tu reporte.

$LogFile y el journal en desacuerdo sobre escrituras MFT

El journal registra escrituras al nivel del archivo; $LogFile registra las transacciones MFT subyacentes. Un timestomp produce:

  • Una transacción de escritura MFT en $LogFile (modificando $STANDARD_INFORMATION de la entrada objetivo).
  • Un BasicInfoChange | Close en el journal.

Si encuentras una transacción de actualización MFT en $LogFile sin BasicInfoChange | Close correspondiente en el journal, el operador puede haber eliminado el registro del journal — posible vía fsutil usn deletejournal seguido de createjournal, lo que deja sus propias huellas.

Otros movimientos antiforense que pilla el journal

Deshabilitar el journal

fsutil usn deletejournal /D /N C: elimina el journal. Tras la llamada:

  • El archivo journal se reconstruye vacío. Los registros anteriores se han ido.
  • La entrada MFT de $UsnJrnl se reescribe — $LogFile registra la transacción.
  • Security.evtx, si había SACL configuradas, registra un Sensitive Privilege Use de SeRestorePrivilege o SeManageVolumePrivilege.

El journal no puede decirte qué contenía, pero el acto mismo de deshabilitarlo es señal fuerte de antiforense. Ver la referencia de fsutil usn de Microsoft para los comandos de gestión y sus prerrequisitos de privilegio.

Flujos de datos alternativos

El esconderse con ADS es más viejo que yo, y el journal lo registra limpio: un bit de razón StreamChange se dispara cuando se añade o quita un flujo alternativo. Filtra StreamChange y sacarás todos los eventos de create/modify de ADS en el volumen. Falsos positivos incluyen los flujos legítimos Zone.Identifier de las descargas del navegador — también producen StreamChange, apareados con el FileCreate del archivo original.

Trucos de hard link

HardLinkChange se dispara cuando se añaden o quitan hard links. Los operadores los usan a veces para hacer un archivo accesible vía dos padres — útil para evadir controles basados en ruta. Trackea HardLinkChange y pivota sobre FileReferenceNumber para ver todos los padres.

Abuso de reparse points

Los reparse points (junctions, links simbólicos, mount points) pueden redirigir una ruta a otro sitio. ReparsePointChange se enciende cuando se añade o modifica uno. Busca reparse points en $Recycle.Bin, \Users\Default u otras ubicaciones «no-debería-tocarse».

Lo que no puedes pillar así

Una lista corta de movimientos antiforense que se saltan el journal por completo:

  • Arrancar desde medio externo y reescribir el disco — nunca tocó el OS vivo.
  • Reescrituras de userland que preservan el mismo tamaño de contenido (overwrite al mismo offset, sin actualización SI). Producen registros DataOverwrite pero pierden el contenido original. El journal ve la escritura, no lo que había antes.
  • Deshabilitar el journal antes de que el operador haga nada más. El journal solo puede registrar lo que pasó mientras estaba encendido.

Para estos, necesitas o $LogFile, o shadow copies, o telemetría fuera del host. El journal es un testigo fuerte, no el único.

Un escaneo práctico

El filtro más rápido para timestomping sobre un journal parseado:

  1. Filtrar registros con razón exactamente BasicInfoChange | Close.
  2. Para cada uno, mirar los 5 minutos previos de registros en la misma FileReferenceNumber. Si no hay DataOverwrite, DataExtend, FileCreate o rename, marcar.
  3. Para entradas marcadas, calcular el delta SI-vs-FN en el MFT. Ordenar por mayor delta.

La cima de la lista suele ser tu timestomping. Las entradas restantes son operaciones como el Explorador alternando «Oculto» o scripting que toca atributos — dependiente de contexto, pero rara vez interesante para una investigación típica.