Hunting Windows Persistence: Registry Run Keys and Scheduled Tasks

Introduction to Windows Persistence
When an attacker compromises a host, initial access is only the first phase. To ensure continued access across system reboots or credential rotations, adversaries establish persistence. According to the MITRE ATT&CK framework, persistence consists of techniques adversaries use to keep an access foothold across restarts, changed credentials, and other interruptions.
Among the most frequent and effective persistence mechanisms on Windows endpoints are Registry Autostart Execution Points (often called Run keys) and Scheduled Tasks. While sophisticated threat actors may employ advanced techniques such as DLL search order hijacking or WMI event subscriptions, traditional autostart mechanisms remain heavily utilized due to their simplicity and reliability.
In this guide, we will examine how adversaries leverage these mechanisms, explore native CLI and PowerShell tools to inspect them, and establish robust hunting queries to spot malicious activity across your fleet.
Understanding Registry Autostart Execution Points
The Windows Registry acts as a centralized hierarchical database for configuration settings. Certain registry keys are specifically evaluated by the Windows shell (explorer.exe) or Winlogon during system boot or user logon.
The primary registry locations targeted by adversaries include:
- Current User Run Key: ‘HKCU\Software\Microsoft\Windows\CurrentVersion\Run’
- Current User RunOnce Key: ‘HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce’
- Local Machine Run Key: ‘HKLM\Software\Microsoft\Windows\CurrentVersion\Run’
- Local Machine RunOnce Key: ‘HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce’
- Userinit Execution: ‘HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Userinit’
- Shell Execution: ‘HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell’
Keys located under ‘HKCU’ execute with the privileges of the logging-in user, requiring no administrative rights to write. Keys under ‘HKLM’ apply system-wide across all users and typically require administrative privileges to modify.
Adversaries frequently insert commands pointing to malicious scripts, obfuscated PowerShell one-liners, or binaries dropped in user-writable directories like ’C:\Users\Public' or ’C:\Users<username>\AppData\Local\Temp'.
Querying Registry Persistence with Native Tools
To hunt for unauthorized entries without relying on third-party security software, native command-line tools provide immediate visibility.
You can query registry keys directly using ‘reg.exe’ in a Command Prompt:
reg query HKLM\Software\Microsoft\Windows\CurrentVersion\Run
reg query HKCU\Software\Microsoft\Windows\CurrentVersion\Run
For a more structured and scriptable approach, PowerShell allows security analysts to retrieve property names and values efficiently:
Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run'
Get-ItemProperty -Path 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run'
When evaluating registry results, look for these specific red flags:
- Binaries executing from non-standard directories (‘\AppData\Local\Temp’, ‘\Users\Public’, ‘\ProgramData’).
- Execution of Living off the Land Binaries (LOLBins) like ‘mshta.exe’, ‘rundll32.exe’, ‘powershell.exe’, or ‘cmd.exe’ containing encoded parameters (e.g., ‘-EncodedCommand’ or base64 strings).
- Random or pseudo-random entry names designed to evade superficial review.
- Misspelled path names mimicking legitimate applications (e.g., ‘svchost32.exe’ or ‘microsft.exe’).
Advanced Autostart Locations: Winlogon and Image File Execution Options
Beyond standard Run keys, adversaries target secondary autostart locations to achieve stealthier execution.
- Winlogon Execution: The Winlogon registry keys specify helper programs launched during interactive logon.
- Location: ‘HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon’
- Values: ‘Userinit’ and ‘Shell’ Standard configurations set ‘Userinit’ to ‘C:\Windows\system32\userinit.exe,’ and ‘Shell’ to ‘explorer.exe’. Adversaries append malicious binary paths to these values, separated by commas (e.g., ‘userinit.exe, C:\Users\Public\malware.exe’).
- Image File Execution Options (IFEO): IFEO is a developer feature designed to launch debuggers automatically when a target binary starts. Adversaries abuse IFEO by configuring a ‘Debugger’ registry value for common utilities like ‘sethc.exe’ (Sticky Keys) or ‘utilman.exe’ (Accessibility Options).
- Location: ‘HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\sethc.exe’
- Value Name: ‘Debugger’
- Value Data: ‘cmd.exe’
When an attacker presses Shift five times at the Windows logon screen, Windows triggers ‘sethc.exe’, which IFEO redirects to open an administrative Command Prompt before user authentication occurs.
To audit IFEO for malicious debugger attachments, execute:
Get-ChildItem -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options' | ForEach-Object {
$props = Get-ItemProperty -Path $_.PSPath
if ($props.Debugger) {
Write-Output ('Debugger attached to ' + $_.PSChildName + ': ' + $props.Debugger)
}
}
Hunting Scheduled Tasks
Scheduled Tasks present a flexible and powerful vector for attackers. They can be configured to trigger on system boot, on user logon, at specific time intervals, or upon specific Event Log triggers.
Adversaries use tools like ‘schtasks.exe’ or the PowerShell ‘ScheduledTasks’ module to register persistence mechanisms.
To review scheduled tasks using native tools, run:
schtasks /query /fo LIST /v
Because this command yields extensive output, filtering for non-Microsoft tasks is crucial during threat hunting.
Using PowerShell, we can inspect tasks, focusing on their actions and triggers:
Get-ScheduledTask | Where-State State -ne 'Disabled' | Select-Object TaskName, TaskPath, State | Format-Table -AutoSize
To examine the specific executable or script associated with each scheduled task, expand the ‘Actions’ property:
Get-ScheduledTask | ForEach-Object {
$taskName = $_.TaskName
$taskPath = $_.TaskPath
$_.Actions | Select-Object @{Name='TaskName';Expression={$taskName}}, @{Name='TaskPath';Expression={$taskPath}}, Execute, Arguments
}
Key indicators of malicious scheduled tasks include:
- Tasks executing scripts directly from temporary folders or user profile directories.
- Use of hidden task configurations or tasks created under system accounts executing network downloads (e.g., using ‘curl’, ‘certutil’, or ‘Invoke-WebRequest’).
- Tasks with missing author descriptions or standard software vendor names coupled with unusual binaries.
Automating Audit Tasks across Endpoints
To scale this detection effort across multiple machines, you can combine registry and task auditing into a single PowerShell hunting script.
Consider the following script template designed to identify suspicious execution paths across both autostart registries and scheduled tasks:
$suspiciousPaths = @('AppData', 'Temp', 'Public', 'PerfLogs', 'ProgramData')
Write-Output '[+] Checking Registry Autostart Entries...'
$regPaths = @(
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run',
'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run'
)
foreach ($path in $regPaths) {
$props = Get-ItemProperty -Path $path -ErrorAction SilentlyContinue
if ($props) {
$props.psobject.properties | Where-Object { $_.Name -notmatch '^\PS' } | ForEach-Object {
$val = $_.Value
foreach ($sus in $suspiciousPaths) {
if ($val -like ('*' + $sus + '*')) {
Write-Output ('[!] Suspicious Registry Entry Found in ' + $path)
Write-Output (' Name: ' + $_.Name + ' | Value: ' + $val)
}
}
}
}
}
Write-Output '[+] Checking Scheduled Tasks...'
Get-ScheduledTask | ForEach-Object {
$name = $_.TaskName
foreach ($action in $_.Actions) {
$cmd = '' + $action.Execute + ' ' + $action.Arguments
foreach ($sus in $suspiciousPaths) {
if ($cmd -like ('*' + $sus + '*')) {
Write-Output ('[!] Suspicious Task Action Found: ' + $name)
Write-Output (' Command: ' + $cmd)
}
}
}
}
Monitoring Persistence Creation via Sysmon and Event Logs
Querying the current state provides a static snapshot, but real-time telemetry is essential to capture persistence as it is established.
Microsoft Sysmon (System Monitor) provides high-fidelity event logs ideal for tracking registry modifications and task creation.
Relevant Sysmon Event IDs include:
- Event ID 12: Registry object added or deleted.
- Event ID 13: Registry value set.
- Event ID 1: Process Creation (monitoring execution of ‘schtasks.exe’ or ‘reg.exe’).
When monitoring native Security Event Logs, focus on:
- Event ID 4697: A service was installed in the system.
- Event ID 4698: A scheduled task was created.
- Event ID 4702: A scheduled task was updated.
By ingesting Event ID 4698 into your SIEM, you can generate immediate alerts whenever a new scheduled task is registered. Pay close attention to the XML event data contained within Event 4698, specifically the ‘Command’ and ‘Arguments’ nodes under ‘Actions’.
Summary and Next Steps
Adversaries continue to rely on Windows Registry autostart keys and Scheduled Tasks because they offer dependable execution under normal operating system workflow.
To strengthen your defensive posture:
- Baseline your registry autostart locations and scheduled tasks across standard workstation images.
- Implement centralized logging for Sysmon Event IDs 12/13 and Security Event ID 4698.
- Deploy proactive PowerShell audits across remote endpoints to detect anomalous execution paths in user-writable directories.
Mastering these detection mechanics allows security analysts to uncover host persistence quickly, turning a common adversary advantage into a high-confidence detection opportunity.