Jump List Parser
Volver al blog

Análisis forense de Jump Lists: una guía práctica de DFIR

2026-05-256 min de lectura

Las Jump Lists responden a una pregunta que otros artefactos rodean: qué aplicación abrió qué archivo, en qué host, en qué momento. Tras suficientes casos dejas de recurrir a ShellBags o Prefetch como primer movimiento ante una pregunta del tipo "¿qué tocó este usuario?" y empiezas con AppData\Roaming\Microsoft\Windows\Recent\AutomaticDestinations\. Los campos que te importan están dentro, siempre, en cada versión de Windows desde 7. Este es el flujo de trabajo que ejecuto.

Lo que realmente te da el artefacto

Por entrada, tras el parseo:

  • Ruta de destino completa del elemento abierto, local, UNC o extraíble.
  • Marca temporal del último acceso (FILETIME, UTC) y un recuento de accesos por entrada. El recuento es un float; las entradas ancladas almacenan un centinela en su lugar.
  • Nombre NetBIOS de la máquina registrado en el momento del acceso. Este es el campo que importa para el movimiento lateral.
  • Estado anclado. Anclado significa que el usuario hizo clic activamente en "Anclar a esta lista".
  • AppID, que mapea deterministamente a la aplicación que lanza (CRC64 truncado sobre la ruta del ejecutable).
  • ID de volumen y etiqueta de volumen del LNK incrustado. Útil para correlación de medios extraíbles.
  • Tres FILETIMEs de la cabecera LNK, tiempos de creación, acceso y escritura del destino vistos cuando se escribió el LNK. Capturan el momento y luego nunca se actualizan.
  • Argumentos de línea de comandos y directorio de trabajo cuando están presentes.

Un flujo DFIR de 5 pasos

  1. Adquirir. Extrae %AppData%\Microsoft\Windows\Recent\AutomaticDestinations\ y la carpeta hermana CustomDestinations\ de cada perfil de usuario. Los archivos en vivo suelen estar bloqueados por explorer.exe, así que trabaja desde una imagen forense, un snapshot VSS o una herramienta que maneje el bloqueo correctamente. KAPE tiene un objetivo para esto; de lo contrario, robocopy /b desde una shadow copy montada funciona. No copies en vivo con xcopy simple.

  2. Triaje por AppID. Lista las AppIDs (nombres de archivo menos la extensión) y mapéalas a aplicaciones. La lista de AppIDs que viene con JLECmd es la referencia de facto. Cualquier cosa no mapeada vale una mirada más cercana, las apps personalizadas y portátiles generan sus propias AppIDs, y también las herramientas de atacantes que se registran como shell-aware. Una AppID desconocida con una fila DestList reciente es una pista.

  3. Parsear. Extrae cada flujo LNK numerado y las filas de DestList. JLECmd produce CSV o JSON para trabajo por lotes. JumpListExplorer (el hermano GUI de Eric Zimmerman) es la herramienta adecuada para revisión interactiva. Plaso / log2timeline emite eventos de timeline. Autopsy los muestra como resultados de ingesta. Para una revisión puntual sin mover el artefacto de la estación de trabajo del analista, el parser en navegador de este sitio ejecuta la misma lógica del lado del cliente y nunca sube nada.

  4. Correlacionar. Alinea las marcas temporales de acceso de DestList con la línea de tiempo de la sesión interactiva del usuario. Los pivotes que realmente funcionan:

    • Security.evtx 4624 / 4634 / 4647 para ventanas de inicio y cierre de sesión (consulta el EVTX parser).
    • La clave UserAssist en NTUSER.DAT para lanzamientos GUI (consulta el parser de registro).
    • Aciertos de Prefetch para ejecución de procesos.
    • El diario USN para eventos de creación/acceso en el archivo objetivo.
    • AmCache y ShimCache para el propio ejecutable.
    • SRUM para uso de red y CPU de la aplicación lanzadora.
    • Un volcado de RAM vía Volatility si lo tienes, para confirmar que la aplicación estaba residente en ese momento.
  5. Informar. Cita cada hallazgo por archivo fuente, número de flujo e ID de entrada DestList, por ejemplo, 1b4dd67f29cb1962.automaticDestinations-ms, flujo 7, entrada DestList 0x12. La reproducibilidad es lo que hace que el hallazgo aguante bajo revisión. "La Jump List lo mostró" no es una cita.

El campo hostname y por qué se gana su lugar

Cada fila de DestList lleva el nombre NetBIOS registrado cuando se abrió el destino. En una estación de trabajo que monta recursos compartidos de múltiples servidores, ese campo revela qué servidor albergaba cada documento abierto, sin necesitar los propios registros del servidor. En investigaciones de movimiento lateral, una Jump List en un host comprometido contiene frecuentemente el nombre del servidor de staging del atacante mucho después de que el recurso compartido se haya desmontado y el servidor se haya reimagado.

He cerrado casos con este único campo. Un usuario que saltó por RDP abre un archivo desde un host de staging, el atacante desmantela el host de staging, el SOC no tiene nada. El automaticDestinations-ms del endpoint comprometido para Notepad todavía tiene el nombre NetBIOS y el GUID del volumen seis semanas después.

Errores comunes

  • Matemáticas de FILETIME. Intervalos de 100 nanosegundos desde 1601-01-01 UTC. Convierte con unix_seconds = (filetime / 10_000_000) - 11_644_473_600. Los errores de un día aquí son la fuente más común de timelines malas que reviso.
  • Desviación de versión de DestList. Win7 escribía la versión 1. Win10 y Win11 suelen emitir v3 o v4. Los tamaños de fila y los offsets de campo cambian. Los parsers más antiguos que codifican el layout v1 se desalinearán en silencio en hosts modernos y pasarás una hora preguntándote por qué los hostnames parecen basura.
  • Las entradas ancladas inflan los recuentos. Algunas aplicaciones (Office, Explorer) anclan elementos agresivamente y aumentan los recuentos de acceso en indexación en segundo plano. Un recuento alto no es por sí mismo prueba de interacción repetida del usuario. Comprueba con Prefetch y UserAssist.
  • Interruptor "Mostrar elementos abiertos recientemente". Desactivarlo en Configuración → Personalización → Inicio trunca los archivos por AppID. Los archivos se recrean en el siguiente uso, por lo que DestLists inesperadamente cortos con todas las marcas temporales agrupadas en torno a la misma fecha reciente son un indicador de que el usuario (o algo que se hace pasar por el usuario) cambió el interruptor.
  • Las entradas ancladas en customDestinations-ms sobreviven a los resets. Útil, una ruta UNC anclada es intención. Anótalas por separado de las pruebas MRU en el informe.
  • Las colisiones de AppID son raras pero reales. Dos instalaciones del mismo ejecutable en la misma ruta producen la misma AppID. Si estás trabajando en un entorno multi-tenant Citrix o VDI, espera solapamiento; confía en el campo hostname y en el TrackerDataBlock del LNK para desambiguar.

Un pivote final

Una vez que tengas una lista de entradas sospechosas, toma el GUID droid del TrackerDataBlock del LNK y pivota por cada otro LNK del host (Escritorio, Menú Inicio, Recent\, ambas carpetas Destinations). Mismo droid significa misma máquina fuente. Droid diferente en la misma Jump List significa que el archivo se abrió en más de un host y Windows conservó ambas versiones. Ese segundo caso es inusual y casi siempre interesante.

Suelta un archivo en la página de inicio para ver todo esto sin enviar datos a ninguna parte. Para la referencia a nivel de byte, el artículo del formato de archivo automaticDestinations es la siguiente lectura.

Lecturas adicionales

  • Eric Zimmerman, JLECmd y JumpListExplorer, las herramientas offline canónicas.
  • Yogesh Khatri y Mike Stevens, "Jumping into the Past", ingeniería inversa original de DestList.
  • Kacos2000, Jumplist-Browser, visor PowerShell para inspección de flujos en bruto.
  • MITRE ATT&CK T1083 File and Directory Discovery y T1021 Remote Services, para contexto sobre lo que el rastro de Jump List tiende a corroborar.