Windows Persistence: 10 Documented Techniques and Their Countermeasures
Defensive catalog of 10 Windows persistence mechanisms with ready-to-run KQL hunting queries and hardening measures any SOC can deploy this week.

Persistence is not the glamorous part of an engagement, but it is what separates an adversary who loses access on the first reboot from the one who comes back three weeks later when the team has forgotten about the alert. At Basilisk OffSec we run exercises against customers where more than 70% of detections that turned into real cases started with trivial mechanisms: Run keys, scheduled tasks with cute names, services with unquoted paths. The goal of this catalog is not to teach implant hiding. It is to document ten real techniques we see every week, map each to its MITRE ATT&CK ID, and ship KQL queries your Defender XDR or Sentinel can run tomorrow morning, together with the countermeasure that closes each door.
1. Autorun registry keys (T1547.001)
The first family worth covering is the autorun registry keys. HKCU\Software\Microsoft\Windows\CurrentVersion\Run remains the most exploited T1547.001 in commodity campaigns, not because attackers are lazy but because it works in any profile without elevation. A simple query like DeviceRegistryEvents | where RegistryKey has "CurrentVersion\\Run" and InitiatingProcessFileName !in ("explorer.exe","msiexec.exe") catches 80% of cases once you baseline by hostname. The countermeasure is a per-user baseline plus AppLocker or WDAC blocking execution from user-writable paths, so even a written Run value cannot launch. To understand the offensive context of these paths, revisit Simulated Initial Access: Macros, LNK and ISO in an Isolated Windows 11 Lab because most macros we see in the lab end up writing to exactly these keys.
2. Scheduled Tasks (T1053.005)
Scheduled Tasks are the second most abused technique and the most underreported. The challenge is not detecting task creation, it is filtering the noise: a corporate Windows 11 creates about 40 legitimate tasks during update cycles on a quiet day. The query that has worked best for us is DeviceProcessEvents | where FileName == "schtasks.exe" and ProcessCommandLine has_any ("/create","/change") | where InitiatingProcessParentFileName !in (~"msiexec.exe",~"trustedinstaller.exe") combined with Get-ScheduledTask enrichment filtering empty Author or unsigned author. In parallel, monitoring Security event 4698 and walking TaskCache\Tree in the registry catches hidden tasks invisible to schtasks /query. The countermeasure is alerting on task creation outside change windows and denying non-admin task registration via GPO.
3. Windows Services (T1543.003)
Windows services remain the preferred vector once the attacker already has SYSTEM. Blue team focus should sit on three signals: service creation pointing to an unsigned binary, ImagePath in world-writable directories like ProgramData or Public, and the classic unquoted service path. A good hunt starts with DeviceEvents | where ActionType == "ServiceInstalled" | where FolderPath !startswith "C:\\Windows\\" and FolderPath !startswith "C:\\Program Files". To avoid confusing with legitimate installs, join with the certificate table and drop anything signed by a known corporate signer. The countermeasure is quoting every service path, restricting SeCreateServicePrivilege, and code-signing enforcement. This pattern echoes the baseline-driven detection we covered in Hunting Living-off-the-Land Binaries on Windows with KQL.
4. WMI Event Subscription (T1546.003)
WMI Event Subscription is where things get serious. It is silent, survives reboot and rarely appears in junior playbooks. The recipe: monitor __EventFilter, __EventConsumer and __FilterToConsumerBinding in the root\subscription class. In Defender, DeviceEvents | where ActionType == "WmiBindEventFilterToConsumer" works, but in environments without MDE you need Sysmon with events 19, 20 and 21 enabled. Combine with Get-WmiObject -Namespace root\subscription -Class __EventConsumer running weekly as a compliance check; a CommandLineEventConsumer or ActiveScriptEventConsumer on an endpoint is almost never legitimate. Lateral movement techniques that end in WMI persistence are illustrated well in Lateral Movement in the Lab: SMB, WMI and WinRM with a Detection Focus.
5. COM Hijacking (T1546.015)
COM hijacking abuses HKCU precedence over HKLM for CLSIDs. The attacker registers an InProcServer32 under HKCU pointing at a controlled DLL, and any process loading that CLSID in user session executes the code. To hunt, focus on unexpected writes to HKCU\Software\Classes\CLSID\*\InProcServer32 where the default value does not resolve to a Microsoft-signed DLL. The countermeasure is baselining which CLSIDs each host legitimately overrides in HKCU (usually none) and alerting on any new entry, since a clean corporate image rarely populates that key at all.
6. AppInit_DLLs and Image File Execution Options (T1546.010 / T1546.012)
AppInit_DLLs and Image File Execution Options belong to the same category of registry-based execution flow abuse and deserve dedicated queries. AppInit_DLLs loads a DLL into every process linking user32.dll, and modern Windows disables it under Secure Boot, so its mere activation is a red flag: alert on any write to HKLM\...\Windows\AppInit_DLLs. IFEO abuse sets a Debugger value under a target executable's key so that launching, say, sethc.exe runs the attacker's binary instead; hunt writes to the Debugger and GlobalFlag values and correlate with unexpected child processes. Anyone wondering why modern evasion still routes through these registry paths should read EDR Evasion for Research: Direct Syscalls Explained Without the Hype.
7. Startup folder and Logon Scripts (T1037)
The Startup folder and Logon Scripts close the classic user-land trio. A shortcut dropped in the per-user or all-users Startup folder runs at logon with no elevation, and the UserInitMprLogonScript registry value under HKCU\Environment executes a script at every logon while flying under most default rule sets. Hunt file creation events in the two Startup paths where the writing process is not a known installer, and alert on any value in UserInitMprLogonScript, which is empty on a clean host. The countermeasure is a locked-down Startup folder ACL and GPO auditing of logon-script registry values.
8. BITS Jobs (T1197)
BITS deserves special attention because it survives logoff and can pull payloads via a trusted process: bitsadmin /list /allusers /verbose as a weekly check already catches 95% of cases, and the Microsoft-Windows-Bits-Client/Operational log records job creation and notify commands. The dangerous variant sets a SetNotifyCmdLine so BITS itself launches the payload when the transfer completes, which looks like svchost activity to a careless analyst. The countermeasure is monitoring the BITS operational channel for jobs with a notify command line and capping job lifetimes via policy so a stalled transfer cannot lurk for weeks.
9. Print Processors and other autostart extensions (T1547.012)
Print Processors are back on the map after PrintNightmare and monitoring HKLM\SYSTEM\CurrentControlSet\Control\Print\Environments is cheap: a new print processor DLL loaded by spoolsv.exe from a non-standard path is a high-confidence signal. The same boot-and-logon autostart family (T1547) includes Winlogon Shell and Userinit tampering, LSA Security Support Providers, and Netsh helper DLLs; each is a single registry value that should never change on a managed host, so a compliance query comparing current values to a golden image catches all of them at once. The countermeasure everywhere is the same: know the good value, alert on deviation.
10. Turning detections into a program
The tenth technique is the one that ties the other nine together: operationalizing detection as a repeatable program rather than a pile of rules. Stack the ten queries above in a single Sentinel watchlist, configure a 14-day per-host baseline before alerting, and review hits in a weekly threat hunting window. To correlate this with the full offensive cycle, Adversary Emulation with Caldera and MITRE ATT&CK in a Corporate Lab and Purple Team in Practice: Building a Red vs Blue Feedback Loop show how to turn these detections into continuous exercises with the red team, so each rule is exercised, tuned, and re-validated on a cadence instead of rotting.
Prioritizing the ten by prevalence and cost
Not all ten techniques deserve equal effort on day one, and a program that tries to boil the ocean stalls before it ships anything. Order them by prevalence against detection cost: Run keys and scheduled tasks are high prevalence and low cost, so they come first; Windows services and BITS are medium prevalence and cheap to query, so they come second; WMI Event Subscription, COM hijacking, and the IFEO or AppInit family are lower prevalence but far higher impact when they appear, because they signal a more capable operator, so they come third but must not be skipped. Print Processors and the Winlogon or Userinit autostart values are rare but trivially cheap as golden-image comparisons, so fold them into the same weekly compliance sweep. Map each technique to whether prevention, detection, or both is realistic on your fleet, because some, like unquoted service paths, are better fixed once than watched forever, while others, like WMI subscriptions, can only be detected and reviewed. Publishing this priority order as a one-page matrix keeps the program honest and gives leadership a defensible reason for where the next hour of engineering goes.
FAQ
Which technique should a small team detect first? Run keys and scheduled tasks, in that order, because they cover the majority of commodity persistence and the queries are cheap; get those two clean before touching WMI subscriptions. Do I need Sysmon if I already run Defender for Endpoint? For most of these MDE is enough, but WMI Event Subscription (events 19-21) and some registry-write visibility are stronger with Sysmon, so run Sysmon on your crown-jewel and high-risk hosts even if the fleet relies on MDE alone. Coverage is a spectrum, and you spend Sysmon where the blast radius is largest.
Checklist and conclusion
Practical takeaway: persistence is not detected with one brilliant rule, it is detected with review discipline. Walk the checklist for each of the ten: telemetry channel collected, KQL query written and version-controlled, per-host baseline established, countermeasure deployed, and the rule validated with Atomic Red Team so you have seen it fire. Start tomorrow by running the first two queries (Run keys and schtasks) in your production environment in read-only mode, count how many hits you get, and you will discover legitimate persistence nobody documented. That is the real starting point of the program, and everything after it is disciplined iteration.


