Skip to content

How to Analyze Scheduled Tasks in Your Browser (Worked Case)

Step by step: load task XML, .job files and the SOFTWARE hive into a free in-browser parser, read hidden and registry-only tasks, fix time zones and export. With a fictional case.

Published on 9 min read

TL;DR. Collect System32\Tasks, SysWOW64\Tasks, C:\Windows\Tasks and the SOFTWARE hive (with its .LOG1/.LOG2), drop them or the triage ZIP into the Scheduled Tasks Parser, read the warnings, confirm the inferred UTC offset, then work down the findings: registry-only tasks, missing SD, hash mismatches first, then paths, encoded commands, LOLBins and privileges. Export CSV, JSON or a timeline CSV. Nothing leaves the browser. The fictional case below, which is the built-in sample, shows each step.

This is the hands-on companion to the scheduled task forensics guide. Acquisition is covered in scheduled task locations and acquisition.

What the tool does, and does not do

The parser is Rust compiled to WebAssembly, running in a Web Worker in your browser. Files are read locally and never uploaded. It:

  • reads task XML (UTF-16LE, schema 1.2 and later): RegistrationInfo, every trigger type, principals, settings and Exec/ComHandler/SendEmail/ShowMessage actions;
  • reads legacy .job files: fixed and variable sections, triggers, last run time as stored (local SYSTEMTIME);
  • reads TaskCache from the SOFTWARE hive: Tree (Id, Index, SD decoded to SDDL, key last-write times) and Tasks\{GUID} (Path, URI, Author, Date, Hash, Schema, DynamicInfo, decoded Actions, Triggers header and principal);
  • correlates XML with TaskCache by path, recomputes the hash, and flags registry-only, disk-only and SD-less tasks;
  • warns when the hive is dirty. It does not replay transaction logs, carve deleted keys or parse event logs.

Findings are heuristics to order your review, not verdicts.

The fictional case

Everything below is invented for training: the host, account, addresses and files do not exist, and the commands are harmless placeholders. It is exactly the sample you get with Try a sample on the home page, so you can follow along.

A finance workstation, FIN-WKS-07, set to a UTC+02:00 time zone. On 2026-09-14, an alert fires on unusual outbound traffic. Other artifacts show an account nobody recognises, svc_backup. The question for this step: did the intruder leave scheduled tasks behind, and what did they do between 10:00 and 10:55 UTC?

Step 1: Collect the task folders and the SOFTWARE hive

The collection follows the KAPE layout, as produced by:

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

The resulting ZIP holds C/Windows/System32/Tasks (19 XML files), C/Windows/Tasks (one .job file) and C/Windows/System32/config/SOFTWARE. A Velociraptor Windows.Triage.Targets collection with the same targets works the same way. Hash the archive before you start.

Step 2: Load the files in the browser

Open the tool and drop the ZIP. You can also drop loose files or a folder. The parser walks the archive (KAPE layout, or Velociraptor layout with percent-encoded paths and backslash entry names), picks the task files and the SOFTWARE hive, and ignores the rest. It takes a second or two.

The summary bar for the sample reads: 21 tasks (19 XML, 1 .job, 16 TaskCache entries merged with them), 8 flagged, 1 hidden (no SD), 1 registry only, 1 XML only, 5 recently registered.

Step 3: Read the warnings

Before any conclusion about a task being "missing", read the parser warnings:

WarningMeaningAction
Dirty hiveTransaction logs hold changes not in the primary fileReplay with a log-aware tool and re-check absences
No SOFTWARE hiveOnly XML/.job parsed; no hidden-task or registry-only checks possibleCollect the hive
No task folderOnly TaskCache parsedCollect System32\Tasks

The sample hive is clean: no dirty-hive warning, so "registry only" and "XML only" findings can be read at face value. On a live collection you will often see the dirty warning; replay the logs before trusting absences.

Step 4: Check the time zone

XML Date and StartBoundary values are usually local time without an offset (why). The parser compares each task's XML Date with the UTC DynamicInfo creation FILETIME of the same task and counts the offsets it finds. For the sample it reports UTC+02:00 ×4, UTC+01:00 ×1 and applies +02:00. Two of the comparisons:

TaskXML Date (zoneless)DynamicInfo created (UTC)Difference
\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

The odd one out is not an error: the Edge updater was registered in March, under winter time (CET, UTC+01:00), and the September tasks under summer time (CEST, UTC+02:00). That is why a single offset applied to a whole machine can be wrong for older tasks. For this case every task of interest was registered on 2026-09-14, so +02:00 is right. From now on every time is shown in UTC.

Step 5: Triage the findings

Sort by severity. Of the 21 tasks, 13 are ordinary Microsoft, Office, Edge and feed-sync tasks with no finding. Two more are flagged but benign, and they are worth reading first as a calibration:

  • \GoogleUpdateTaskMachineUA: Elevated, not Microsoft. It runs as SYSTEM and has no author. That is how Google's updater registers itself.
  • \OneDrive Standalone Update Task-S-1-5-21-…-1104: User-writable path. Its command is under %localappdata%, which is where the per-user OneDrive updater lives.

Findings are pointers, not verdicts. The six tasks below are the ones that matter.

\Microsoft\Windows\UPnP\UPnPHostConfigSync: hidden, no SD

  • Author claims Microsoft Corporation, and the task sits under \Microsoft\Windows\ to blend in.
  • Registered 10:12:40 UTC (XML Date 2026-09-14T12:12:40.0918251 local).
  • Principal: SYSTEM, HighestAvailable. Triggers: LogonTrigger and a TimeTrigger from 12:12:40 local, repeating every 30 minutes (PT30M).
  • Action: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -WindowStyle Hidden -EncodedCommand VwByAGkAdABlAC0ATwB1AHQAcAB1AHQAIAAnAHMAeQBuAHQAaABlAHQAaQBjACAAcwBhAG0AcABsAGUAJwA=, decoded by the parser as Write-Output 'synthetic sample' (a stand-in for a real script).
  • TaskCache: the Tree key has Id and Index = 2 but no SD value. Its last-write time is 10:13:05 UTC, 25 seconds after registration.
  • DynamicInfo: last run 10:42:40 UTC, last successful run 10:42:41 UTC.

Findings: Hidden: no SD in TaskCache (critical), Encoded PowerShell (high), Recently registered. This is the Tarrask pattern: on the live host, schtasks /query would not list it. The key write 25 seconds after registration is consistent with the SD being removed at 10:13, which also means the intruder had SYSTEM by then.

\IntelGfxTelemetry: hidden setting, SYSTEM, user-writable path

  • Author FIN-WKS-07\svc_backup, description "Intel graphics telemetry", root folder.
  • Registered 10:09:58 UTC. Principal: S-1-5-18, HighestAvailable. <Hidden>true</Hidden>.
  • Triggers: BootTrigger and a TimeTrigger from 12:15:00 local (10:15 UTC), every hour.
  • Action: C:\ProgramData\Intel\m64.exe -svc.
  • DynamicInfo: last run 10:15:00 UTC, last result 0x00041301 (SCHED_S_TASK_RUNNING: the program was still running at collection time).

Findings: User-writable path, Elevated, not Microsoft, Hidden setting, Recently registered. Unlike the UPnP task, it keeps its SD: it is hidden only from the console's default view, not from schtasks.

\a8Xq2LmZ: the definition changed after registration

  • Random-looking name at the root, registered 10:21:30 UTC by svc_backup, running as svc_backup (InteractiveToken, LeastPrivilege) at that user's logon.
  • TaskCache Actions: C:\Windows\System32\rundll32.exe C:\Users\svc_backup\Downloads\tools\helper.dll,Init.
  • XML on disk: the same command with helper.dll,Start. The TaskCache Hash no longer matches the file.
  • DynamicInfo: last run 10:24:02 UTC.

Findings: XML changed after registration and Registry action differs from XML (high), LOLBin, User-writable path, Random-looking name, Recently registered. Someone edited the XML file directly instead of re-registering the task, so the service still holds the registered version. Read both: the registry says what was registered, the file says what someone wanted it to look like afterwards.

\Microsoft\Windows\Maintenance\CleanupTemp: never registered

  • XML file only: no TaskCache entry at all.
  • Author claims Microsoft Corporation; Date 12:31:05 local (10:31:05 UTC with the +02:00 offset); Hidden=true; principal svc_backup; TimeTrigger at 12:35 local.
  • Action: C:\Windows\System32\mshta.exe C:\Users\svc_backup\Downloads\tools\cleanup.hta.

Findings: Not registered (medium), LOLBin, User-writable path, Recently registered. A file dropped into the Tasks folder is not a task until the service registers it. Because the hive is clean, the absence from TaskCache is meaningful: this task was prepared but, on this evidence, never scheduled.

\SyncBackup: registry only

  • No XML file on disk; TaskCache still has Tree and Tasks\{GUID}.
  • TaskCache Date 2026-09-14T12:44:10.2059113 (local); DynamicInfo created 10:44:10 UTC, last run 10:47:12 UTC, last successful run 10:53:51 UTC, result 0.
  • Decoded Actions: C:\Users\Public\rclone.exe copy C:\Users\Public\data E:\exfil.
  • Triggers header: start boundary 2026-09-14T12:47:00 local, principal SID ending -1119 (svc_backup).

Findings: XML file missing (high), User-writable path, Recently registered. The file was deleted but the task was never unregistered, so it would still appear in schtasks on the live host. The registry is the only surviving definition, and it points at a copy tool writing to E:\exfil, a drive worth identifying.

\Cleanup: a legacy .job

  • File: C:\Windows\Tasks\Cleanup.job, author FIN-WKS-07\svc_backup.
  • Command: cmd.exe /c del /q C:\Users\svc_backup\Desktop\creds.txt.
  • Trigger: once, 12:52 local. Last run: 2026-09-14 12:52:30 local (10:52:30 UTC), status 0x00041305 (SCHED_S_TASK_NOT_SCHEDULED: no further runs planned).

Findings: Legacy .job, User-writable path. A .job file on a modern system is unusual by itself; this one deletes a file from the account's desktop at the end of the session, which looks like cleanup.

Step 6: Narrow the time range and export

Open \SyncBackup and center the time range on it with plus or minus 1 hour. The tool centers on the task's first time, its registration at 10:44:10 UTC, so the window is 09:44:10 to 11:44:10 UTC. The density strip shows the burst between 10:09 and 10:54; the thirteen baseline tasks drop away. You can also type From 2026-09-14 10:00:00 and To 10:55:00 UTC to the second.

Export the filtered view as CSV, JSON, or the Timeline CSV, whose message, datetime and timestamp_desc columns import directly into Timesketch. The reconstructed sequence, all UTC:

TimeSourceEvent
10:09:58DynamicInfo, XML Date\IntelGfxTelemetry registered (SYSTEM, boot + hourly)
10:12:40DynamicInfo, XML Date\Microsoft\Windows\UPnP\UPnPHostConfigSync registered (SYSTEM, encoded PowerShell)
10:13:05Tree key last-writeSD removed from the UPnP task (inferred)
10:15:00DynamicInfo last runm64.exe -svc started, still running at collection
10:21:30DynamicInfo, XML Date\a8Xq2LmZ registered (rundll32 helper.dll,Init)
10:24:02DynamicInfo last run\a8Xq2LmZ ran; XML later edited to ,Start
10:31:05XML DateCleanupTemp XML written, never registered
10:42:40DynamicInfo last runUPnP task's latest run
10:44:10DynamicInfo created\SyncBackup registered
10:47:12 to 10:53:51DynamicInforclone copy to E:\exfil: last run and last successful run
after 10:44Missing XML\SyncBackup XML file deleted
10:52:30.job last runCleanup.job deletes a file from the desktop

Next steps outside this tool: confirm execution of m64.exe, rclone.exe and rundll32.exe with Prefetch and Amcache, look for 4698/106 and 200/201 in the event logs, identify the E: volume, recover helper.dll and cleanup.hta, and find how svc_backup got SYSTEM. The indicator checklist behind these findings is in how to detect malicious scheduled tasks.

Related articles

A practical checklist to spot malicious scheduled tasks: user-writable paths, encoded PowerShell, LOLBins, SYSTEM principals, random names, hidden tasks and XML/registry mismatches.
How to read legacy .job files: the MS-TSCH fixed and variable sections, triggers, the local-time last run SYSTEMTIME, and when .job files still appear on modern Windows.
What the TaskCache key in the SOFTWARE hive stores for each scheduled task: Tree Id/Index/SD, Tasks values, DynamicInfo run times, Actions and Triggers blobs, and the Hash.