Scheduled Task Persistence

Malware often abuses the task scheduler to maintain persistence. Scheduled tasks are a popular persistence mechanism likely due to the ease of implementation.

Tasks are stored in C:\Windows\System32\Tasks\ in XML format.

Tasks are also stored in the registry:

HKLM\Software\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{GUID}

Tasks can be viewed and manipulated using schtasks.exe or with PowerShell Get-ScheduledTask and Set-ScheduledTask.


Scheduled tasks can be manipulated with schtasks.exe

A manual for schtasks.exe here:

I use these commands often when triaging security alerts and removing malware from systems:

List all scheduled tasks:

schtasks /query /fo list /v

List a specific task

schtasks /query /tn "CHANGEME" /fo list /v

Delete a task

schtasks /delete /tn "CHANGEME" /f

Run a task

schtasks /run /tn "CHANGEME"

Create a task

schtasks /create /sc onlogon /tn "CHANGEME" /tr "C:\Path\to\whatever.exe"
schtasks /create /sc minute /tn "TEST" /tr "C:\windows\system32\cmd.exe"

Export a task as XML

schtasks /query /tn "CHANGEME" /xml > out.xml

Elevated Scheduled Tasks

Tasks can be configured to run with elevated privileges:

First, export the task as XML:

schtasks /query /tn "CHANGEME" /xml > out.xml

Next, edit out.xml. In the <Principals> section, add a tag to run at the highest level:


Delete original the original task and replace it with the modified version:

schtasks /delete /tn "CHANGEME" /f
schtasks /create /tn "CHANGEME" /xml out.xml

Multi-Action Scheduled Tasks

Scheduled tasks can be modified to perform more than one action. This allows malware to piggyback off of a legitimate, pre-existing scheduled task.

Multi-action tasks will display Multiple actions under Task To Run, when listed with schtasks.exe

To configure a multi-action scheduled task, first export scheduled task as XML:

schtasks /query /tn "CHANGEME" /xml > task.xml

Edit task.xml, adding an <Exec> stanza within <Actions>:


Delete the old task and install the modified task:

schtasks /delete /tn "CHANGEME" /f
schtasks /create /tn "CHANGEME" /xml task.xml

Finding Malicious Scheduled Tasks

Here are some of the tactics I use to find malicious scheduled tasks.

Manually review scheduled tasks

Some systems only have a handful of tasks, which makes this approach easy. Other systems may have hundreds of legitimate tasks, which makes this method time-consuming and tedious.

schtasks /query /fo list /v

Look for tasks created around the time of an intrusion or incident

If you know roughly when the malware was introduced to the host system, reviewing the Creation and Modification timestamps of scheduled tasks may reveal malicious entries:

ls C:\Windows\System32\Tasks\ | Select Name,CreationTime,LastWriteTime

If the host has Audit object access enabled, scheduled task creation is logged as event ID 4698:

Get-Winevent -FilterHashtable @{logname='Security';id=4698} | Select -Property *

Look for odd spelling, grammatical or verbiage in task names and descriptions

Malicious tasks often try to blend in with the legitimate scheduled tasks configured on a host. Popular choices are masquerading as browser software updaters, Microsoft products, and generic-sounding tasks such as WinUpdate.

Often, malware will use a specific name for the scheduled task it installs or an otherwise predictable pattern. These names can be useful as an indicator of compromise.

An example of these kinds of mistakes can be observed in Turla’s Gazer implant. The description is Adobe Acrobat Reader Updater. This task was generated by Adobe Systems, Inc to keep your Adobe Software up-to-data. This example’s use of up-to-data is strange grammar and suspicious.

Other malware such as Dridex creates random-named tasks such as 36jasjg29tkl.

Look for strange “Task to Run” values

Often, malicious scheduled tasks will be running malware out of ProgramData, a user’s AppData folder, or run scripts with wscript, cscript, or PowerShell. Tasks that spawn executables out of strange directories or run script interpreters deserve scrutiny.

An example is Schtasks-Backdoor.ps1, which installs a scheduled task that runs a malicious PowerShell payload:

Event Logs

Audit object access needs to be enabled via group policy in order for these events to be logged:

Enable Audit object access.

Once this setting is enabled, the following Event IDs are logged:

  • 4698 – A scheduled task was created.
  • 4699 – A scheduled task was deleted.
  • 4700 – A scheduled task was enabled.
  • 4701 – A scheduled task was disabled.
  • 4702 – A scheduled task was updated.

These events can be viewed and filtered with Get-WinEvent

Get-WinEvent -FilterHashtable @{logname='Security';id=4699} |select -Property *

Parent/child relationships

Processes spawned via scheduled tasks usually show up as children of taskeng.exe or svchost -k netsvcs -p -s Schedule.

If this parent/child relationship shows up in sandbox detonations or EDR alerts, reviewing scheduled tasks on a host is a logical next step.

Additional Resources

  1. Sektor7’s Windows Persistence course provides instruction on using scheduled tasks as persistence.
  2. My bookmarks tagged scheduledtasks
  4. PowerShell Scheduled Tasks cmdlets:
  5. Documentation for schtasks.exe
  6. Event ID 4798
  7. Event ID 4799
  8. Event ID 4798
  9. Event ID 4798
  10. Event ID 4798

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s