Skip to content

Analizar tareas programadas en el navegador: caso práctico

Paso a paso: cargue XML de tareas, archivos .job y el hive SOFTWARE en un parser gratuito en el navegador, lea tareas ocultas, ajuste la zona horaria y exporte.

Publicado el 10 min de lectura

Resumen. Recopile System32\Tasks, SysWOW64\Tasks, C:\Windows\Tasks y el hive SOFTWARE (con sus .LOG1/.LOG2), suéltelos, o el ZIP de triaje, en Scheduled Tasks Parser, lea las advertencias, confirme el desfase UTC deducido y recorra los hallazgos: primero tareas solo en el registro, SD ausente y discrepancias de hash; después rutas, comandos codificados, LOLBins y privilegios. Exporte en CSV, JSON o un CSV de cronología. Nada sale del navegador. El caso ficticio de abajo, que es la muestra integrada, ilustra cada paso.

Este es el complemento práctico de la guía de análisis forense de tareas programadas. La adquisición se trata en ubicaciones y adquisición de las tareas programadas.

Qué hace la herramienta y qué no hace

El parser está escrito en Rust compilado a WebAssembly y se ejecuta en un Web Worker dentro de su navegador. Los archivos se leen localmente y nunca se suben. La herramienta:

  • lee el XML de las tareas (UTF-16LE, esquema 1.2 y posteriores): RegistrationInfo, todos los tipos de desencadenador, entidades de seguridad, configuración y acciones Exec/ComHandler/SendEmail/ShowMessage;
  • lee los archivos .job heredados: secciones fija y variable, desencadenadores y hora de la última ejecución tal como está almacenada (SYSTEMTIME local);
  • lee TaskCache del hive SOFTWARE: Tree (Id, Index, SD descodificado a SDDL, hora de última escritura de las claves) y Tasks\{GUID} (Path, URI, Author, Date, Hash, Schema, DynamicInfo, Actions descodificado, cabecera de Triggers y entidad de seguridad);
  • correlaciona el XML con TaskCache por ruta, recalcula el hash y marca las tareas que están solo en el registro, solo en disco o sin SD;
  • avisa cuando el hive está sucio. No reproduce los registros de transacciones, no recupera claves eliminadas ni analiza registros de eventos.

Los hallazgos son heurísticas para ordenar la revisión, no veredictos.

El caso ficticio

Todo lo que sigue es inventado con fines formativos: el equipo, la cuenta, las direcciones y los archivos no existen, y los comandos son marcadores inofensivos. Es exactamente la muestra que obtiene con Try a sample en la página de inicio, así que puede seguirlo paso a paso.

Una estación de trabajo de finanzas, FIN-WKS-07, configurada en una zona horaria UTC+02:00. El 2026-09-14 salta una alerta por tráfico saliente inusual. Otros artefactos muestran una cuenta que nadie reconoce, svc_backup. La pregunta en esta fase: ¿dejó el intruso tareas programadas y qué hizo entre las 10:00 y las 10:55 UTC?

Paso 1: Recopilar las carpetas de tareas y el hive SOFTWARE

La recopilación sigue la estructura de KAPE, tal como la genera:

kape.exe --tsource C: --tdest C:\triage\kape --target ScheduledTasks,RegistryHivesSystem

El ZIP resultante contiene C/Windows/System32/Tasks (19 archivos XML), C/Windows/Tasks (un archivo .job) y C/Windows/System32/config/SOFTWARE. Una recopilación Windows.Triage.Targets de Velociraptor con los mismos targets funciona igual. Calcule el hash del archivo comprimido antes de empezar.

Paso 2: Cargar los archivos en el navegador

Abra la herramienta y suelte el ZIP. También puede soltar archivos sueltos o una carpeta. El parser recorre el archivo comprimido (estructura de KAPE, o estructura de Velociraptor con rutas codificadas con porcentajes y nombres de entrada con barras invertidas), selecciona los archivos de tareas y el hive SOFTWARE e ignora el resto. Tarda uno o dos segundos.

La barra de resumen de la muestra indica: 21 tareas (19 XML, 1 .job, 16 entradas de TaskCache fusionadas con ellas), 8 marcadas, 1 oculta (sin SD), 1 solo en el registro, 1 solo en XML, 5 registradas recientemente.

Paso 3: Leer las advertencias

Antes de concluir que una tarea «falta», lea las advertencias del parser:

AdvertenciaSignificadoAcción
Hive sucioLos registros de transacciones contienen cambios que no están en el archivo principalReprodúzcalos con una herramienta que tenga en cuenta los logs y vuelva a comprobar las ausencias
Sin hive SOFTWARESolo se analizaron XML/.job; no es posible comprobar tareas ocultas ni tareas solo en el registroRecopile el hive
Sin carpeta de tareasSolo se analizó TaskCacheRecopile System32\Tasks

El hive de la muestra está limpio: no hay advertencia de hive sucio, así que los hallazgos «solo en el registro» y «solo en XML» pueden leerse tal cual. En una recopilación en vivo verá a menudo la advertencia de hive sucio; reproduzca los logs antes de fiarse de las ausencias.

Paso 4: Comprobar la zona horaria

Los valores Date y StartBoundary del XML suelen ser horas locales sin desfase (por qué). El parser compara el Date del XML de cada tarea con el FILETIME UTC de creación en DynamicInfo de la misma tarea y cuenta los desfases que encuentra. Para la muestra indica UTC+02:00 ×4, UTC+01:00 ×1 y aplica +02:00. Dos de las comparaciones:

TareaDate del XML (sin zona)Creación en DynamicInfo (UTC)Diferencia
\IntelGfxTelemetry2026-09-14T12:09:58.44138722026-09-14 10:09:58+02:00
\MicrosoftEdgeUpdateTaskMachineCore2026-03-02T09:44:222026-03-02 08:44:22+01:00

La que se sale de la norma no es un error: el actualizador de Edge se registró en marzo, en horario de invierno (CET, UTC+01:00), y las tareas de septiembre en horario de verano (CEST, UTC+02:00). Por eso un único desfase aplicado a toda una máquina puede ser incorrecto para las tareas más antiguas. En este caso, todas las tareas de interés se registraron el 2026-09-14, así que +02:00 es correcto. A partir de aquí todas las horas se muestran en UTC.

Paso 5: Priorizar los hallazgos

Ordene por gravedad. De las 21 tareas, 13 son tareas corrientes de Microsoft, Office, Edge y sincronización de feeds sin ningún hallazgo. Otras dos están marcadas pero son benignas, y conviene leerlas primero para calibrar:

  • \GoogleUpdateTaskMachineUA: Elevada, no es de Microsoft. Se ejecuta como SYSTEM y no tiene autor. Así es como se registra el actualizador de Google.
  • \OneDrive Standalone Update Task-S-1-5-21-…-1104: Ruta escribible por el usuario. Su comando está bajo %localappdata%, que es donde reside el actualizador de OneDrive por usuario.

Los hallazgos son pistas, no veredictos. Las seis tareas siguientes son las que importan.

\Microsoft\Windows\UPnP\UPnPHostConfigSync: oculta, sin SD

  • Autor: dice ser Microsoft Corporation, y la tarea está bajo \Microsoft\Windows\ para pasar desapercibida.
  • Registrada a las 10:12:40 UTC (Date del XML 2026-09-14T12:12:40.0918251 local).
  • Entidad de seguridad: SYSTEM, HighestAvailable. Desencadenadores: LogonTrigger y un TimeTrigger desde las 12:12:40 local, con repetición cada 30 minutos (PT30M).
  • Acción: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -WindowStyle Hidden -EncodedCommand VwByAGkAdABlAC0ATwB1AHQAcAB1AHQAIAAnAHMAeQBuAHQAaABlAHQAaQBjACAAcwBhAG0AcABsAGUAJwA=, que el parser descodifica como Write-Output 'synthetic sample' (un sustituto de un script real).
  • TaskCache: la clave Tree tiene Id e Index = 2, pero ningún valor SD. Su hora de última escritura es 10:13:05 UTC, 25 segundos después del registro.
  • DynamicInfo: última ejecución 10:42:40 UTC, última ejecución correcta 10:42:41 UTC.

Hallazgos: Oculta: sin SD en TaskCache (crítico), PowerShell codificado (alto), Registrada recientemente. Es el patrón Tarrask: en el equipo en vivo, schtasks /query no la mostraría. La escritura de la clave 25 segundos después del registro es coherente con que el SD se eliminara a las 10:13, lo que además significa que el intruso ya tenía SYSTEM en ese momento.

\IntelGfxTelemetry: ajuste oculto, SYSTEM, ruta escribible por el usuario

  • Autor FIN-WKS-07\svc_backup, descripción "Intel graphics telemetry", carpeta raíz.
  • Registrada a las 10:09:58 UTC. Entidad de seguridad: S-1-5-18, HighestAvailable. <Hidden>true</Hidden>.
  • Desencadenadores: BootTrigger y un TimeTrigger desde las 12:15:00 local (10:15 UTC), cada hora.
  • Acción: C:\ProgramData\Intel\m64.exe -svc.
  • DynamicInfo: última ejecución 10:15:00 UTC, último resultado 0x00041301 (SCHED_S_TASK_RUNNING: el programa seguía en ejecución en el momento de la recopilación).

Hallazgos: Ruta escribible por el usuario, Elevada, no es de Microsoft, Ajuste oculto, Registrada recientemente. A diferencia de la tarea UPnP, conserva su SD: solo está oculta en la vista por defecto de la consola, no para schtasks.

\a8Xq2LmZ: la definición cambió tras el registro

  • Nombre de aspecto aleatorio en la raíz, registrada a las 10:21:30 UTC por svc_backup y ejecutada como svc_backup (InteractiveToken, LeastPrivilege) al iniciar sesión ese usuario.
  • Actions de TaskCache: C:\Windows\System32\rundll32.exe C:\Users\svc_backup\Downloads\tools\helper.dll,Init.
  • XML en disco: el mismo comando con helper.dll,Start. El Hash de TaskCache ya no coincide con el archivo.
  • DynamicInfo: última ejecución 10:24:02 UTC.

Hallazgos: XML modificado tras el registro y La acción del registro difiere del XML (alto), LOLBin, Ruta escribible por el usuario, Nombre de aspecto aleatorio, Registrada recientemente. Alguien editó directamente el archivo XML en lugar de volver a registrar la tarea, así que el servicio sigue conservando la versión registrada. Lea ambas: el registro dice qué se registró; el archivo, qué aspecto quería alguien que tuviera después.

\Microsoft\Windows\Maintenance\CleanupTemp: nunca registrada

  • Solo el archivo XML: no hay ninguna entrada en TaskCache.
  • Autor: dice ser Microsoft Corporation; Date 12:31:05 local (10:31:05 UTC con el desfase +02:00); Hidden=true; entidad de seguridad svc_backup; TimeTrigger a las 12:35 local.
  • Acción: C:\Windows\System32\mshta.exe C:\Users\svc_backup\Downloads\tools\cleanup.hta.

Hallazgos: No registrada (medio), LOLBin, Ruta escribible por el usuario, Registrada recientemente. Un archivo dejado en la carpeta Tasks no es una tarea hasta que el servicio lo registra. Como el hive está limpio, la ausencia en TaskCache es significativa: esta tarea se preparó pero, según estas evidencias, nunca llegó a programarse.

\SyncBackup: solo en el registro

  • No hay archivo XML en disco; TaskCache conserva Tree y Tasks\{GUID}.
  • Date de TaskCache 2026-09-14T12:44:10.2059113 (local); DynamicInfo: creada 10:44:10 UTC, última ejecución 10:47:12 UTC, última ejecución correcta 10:53:51 UTC, resultado 0.
  • Actions descodificado: C:\Users\Public\rclone.exe copy C:\Users\Public\data E:\exfil.
  • Cabecera de Triggers: límite de inicio 2026-09-14T12:47:00 local, entidad de seguridad con SID terminado en -1119 (svc_backup).

Hallazgos: Falta el archivo XML (alto), Ruta escribible por el usuario, Registrada recientemente. Se borró el archivo pero la tarea nunca se dio de baja, así que seguiría apareciendo en schtasks en el equipo en vivo. El registro es la única definición que sobrevive, y apunta a una herramienta de copia que escribe en E:\exfil, una unidad que conviene identificar.

\Cleanup: un .job heredado

  • Archivo: C:\Windows\Tasks\Cleanup.job, autor FIN-WKS-07\svc_backup.
  • Comando: cmd.exe /c del /q C:\Users\svc_backup\Desktop\creds.txt.
  • Desencadenador: una vez, a las 12:52 local. Última ejecución: 2026-09-14 12:52:30 local (10:52:30 UTC), estado 0x00041305 (SCHED_S_TASK_NOT_SCHEDULED: no hay más ejecuciones previstas).

Hallazgos: .job heredado, Ruta escribible por el usuario. Un archivo .job en un sistema moderno ya es inusual de por sí; este borra un archivo del escritorio de la cuenta al final de la sesión, lo que tiene todo el aspecto de una limpieza.

Paso 6: Acotar el intervalo de tiempo y exportar

Abra \SyncBackup y centre el intervalo de tiempo en ella con más o menos 1 hora. La herramienta se centra en la primera hora de la tarea, su registro a las 10:44:10 UTC, así que la ventana va de 09:44:10 a 11:44:10 UTC. La franja de densidad muestra la ráfaga entre las 10:09 y las 10:54; las trece tareas de la línea base desaparecen. También puede escribir Desde 2026-09-14 10:00:00 y Hasta 10:55:00 UTC con precisión de segundos.

Exporte la vista filtrada en CSV, JSON o el CSV de Timeline, cuyas columnas message, datetime y timestamp_desc se importan directamente en Timesketch. La secuencia reconstruida, toda en UTC:

HoraFuenteEvento
10:09:58DynamicInfo, Date del XMLSe registra \IntelGfxTelemetry (SYSTEM, arranque + cada hora)
10:12:40DynamicInfo, Date del XMLSe registra \Microsoft\Windows\UPnP\UPnPHostConfigSync (SYSTEM, PowerShell codificado)
10:13:05Última escritura de la clave TreeSD eliminado de la tarea UPnP (deducido)
10:15:00Última ejecución en DynamicInfoSe inicia m64.exe -svc, todavía en ejecución en la recopilación
10:21:30DynamicInfo, Date del XMLSe registra \a8Xq2LmZ (rundll32 helper.dll,Init)
10:24:02Última ejecución en DynamicInfoSe ejecuta \a8Xq2LmZ; el XML se edita después a ,Start
10:31:05Date del XMLSe escribe el XML de CleanupTemp, nunca registrado
10:42:40Última ejecución en DynamicInfoÚltima ejecución de la tarea UPnP
10:44:10Creación en DynamicInfoSe registra \SyncBackup
10:47:12 a 10:53:51DynamicInfoCopia con rclone a E:\exfil: última ejecución y última ejecución correcta
después de 10:44XML ausenteSe borra el archivo XML de \SyncBackup
10:52:30Última ejecución del .jobCleanup.job borra un archivo del escritorio

Próximos pasos fuera de esta herramienta: confirmar la ejecución de m64.exe, rclone.exe y rundll32.exe con Prefetch y Amcache, buscar los eventos 4698/106 y 200/201 en los registros de eventos, identificar el volumen E:, recuperar helper.dll y cleanup.hta y averiguar cómo obtuvo svc_backup privilegios de SYSTEM. La lista de indicadores en la que se basan estos hallazgos está en cómo detectar tareas programadas maliciosas.

Artículos relacionados

Lista práctica para detectar tareas programadas maliciosas: rutas escribibles, PowerShell codificado, LOLBins, SYSTEM, tareas ocultas y discrepancias XML/registro.
Cómo leer los archivos .job heredados: secciones fija y variable de MS-TSCH, desencadenadores, la última ejecución en SYSTEMTIME local y su presencia en Windows actual.
Qué guarda la clave TaskCache de SOFTWARE para cada tarea programada: Id/Index/SD de Tree, valores de Tasks, DynamicInfo, blobs Actions y Triggers, y el Hash.