Windows Persistence Hunting: The Autostart Locations Attackers Abuse (and How to Audit Them)
Eviction is the whole game. Detection gets the headlines, but the breach that actually hurts is the one where you thought you were done. An attacker who keeps a single autostart entry survives the reboot, survives the “we reimaged it from backup,” and is back in your network before the incident report is signed. Persistence is where attackers spend their patience and where defenders spend too little. Here are the Windows autostart locations real intrusions abuse, and how to audit every one of them — free, on the machine in front of you.
Persistence is the attacker’s answer to one question: “when this box reboots or the user logs out, how does my code run again without me touching it?” Windows offers an almost comically large number of answers. The community catalog of Autostart Extensibility Points (ASEPs) runs to dozens of distinct mechanisms, and the honest truth is that most defenders can name three or four. Attackers know all of them. The asymmetry is the problem: you have to audit every door; they only need one left open.
The good news is that persistence, unlike a fileless in-memory implant, has to write itself down somewhere durable to survive a reboot — a registry value, a task XML, a service entry, a WMI binding. That durability is the attacker’s necessity and your opportunity. Every one of those is enumerable, baselineable, and diffable. You cannot stop an attacker from trying to persist, but on a machine you control you can know, at any moment, exactly what is configured to run at boot and logon — and that is a fight you win.
The Run Keys: First Stop for a Reason
The classic registry Run and RunOnce keys are persistence-101 because they are trivial, require no admin in the per-user hive, and execute on every logon. They are still, decades later, one of the most common commodity-malware footholds:
# The autostart Run keys, per-user (HKCU) and machine-wide (HKLM):
HKCU\Software\Microsoft\Windows\CurrentVersion\Run
HKLM\Software\Microsoft\Windows\CurrentVersion\Run
HKLM\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Run # 32-bit on 64-bit
# ...plus RunOnce, RunServices, and the Policies\Explorer\Run variants
What makes a Run entry suspicious isn’t its existence — plenty of legitimate software lives here — it’s the shape of the value. A command pointing at %TEMP%, %APPDATA%, or a user-writable path; a base64 blob piped into powershell -enc; mshta or rundll32 calling out to a URL; an executable name squatting on a trusted one. Auditing means enumerating every Run-class key across every hive and asking “does this command line look like software, or like a payload?” — which is exactly the kind of judgement that doesn’t scale by hand but encodes cleanly into rules.
Scheduled Tasks and Services: The Durable Tier
Run keys are noisy and fragile. Serious operators prefer mechanisms that look more like legitimate administration. Scheduled tasks are a favorite: they can trigger at logon, at boot, on an interval, or even on an event-log event, and they can run as SYSTEM. A task named GoogleUpdateTaskMachineCore that actually launches PowerShell from a temp directory is the kind of thing that survives a cursory look. Windows services are the other durable tier — a new service (Event ID 7045 / 4697 if you’re logging it) with an ImagePath in a user-writable directory, or an unquoted service path that lets a low-priv user hijack the binary, is both persistence and a privilege-escalation primitive in one.
The audit question for both is the same: enumerate the full set, then separate the OS-and-vendor baseline from the anomalies. Tasks running unsigned binaries, services with binaries outside C:\Windows or Program Files, anything whose author or path doesn’t match a known publisher. You are not trying to read every entry by eye every morning; you are trying to flag the handful that don’t belong.
The Obscure Ones That Catch Real APTs
Beyond the obvious tiers sit the mechanisms that separate a thorough hunt from a checkbox one — the places defenders forget and red teams love:
- WMI event subscriptions. A permanent
__EventFilter+CommandLineEventConsumerbinding can fire code on a system event (say, a few minutes after boot) with no file on disk in any startup folder. It’s a CISA-documented APT favorite precisely because almost nobody enumerates the WMI repository. - Startup folders & the Winlogon shell. The per-user and All-Users Startup folders, plus
Winlogon\ShellandUserinitvalues — swap in an extra binary alongsideexplorer.exeand it runs at every logon. - Image File Execution Options (IFEO). A
Debuggervalue under an IFEO key hijacks a target process: launch Notepad, run the attacker’s code. Also abused via the “accessibility” backdoor (sticky keys / utilman). - COM hijacking & LSA/SSP providers. A registered
InprocServer32pointed at a rogue DLL, or a malicious Security Support Provider — quiet, powerful, and rarely in anyone’s baseline.
None of these require a CVE. None of them are caught by “is the machine patched?” They are configuration state — the exact surface a posture audit is built to read. On your own machine, enumerating all of it is free and takes seconds:
# Audit every autostart surface on this machine, full depth, no gates:
winsentinel --audit
# Snapshot the persistence/startup state to diff against a known-good baseline:
winsentinel --audit --format json --out persistence-baseline.json
The single most powerful technique here isn’t a clever signature — it’s the baseline diff. Capture the full autostart inventory on a clean machine, then compare. Persistence is, by definition, a new entry. An attacker can make a malicious task look plausible in isolation; what they cannot easily do is avoid appearing in the delta between “yesterday’s autostarts” and “today’s.” A diff turns “is this WMI binding evil?” (hard) into “did this WMI binding exist last week?” (easy).
Where the Org Story Begins: Persistence Is a Fleet Diff
On one machine, the baseline diff is a manual habit — snapshot, store the JSON, compare next week. That’s genuinely enough to catch persistence on the box in front of you, and it costs nothing. The problem is the same one every endpoint discipline hits at scale: a baseline diff you have to run by hand on 80 laptops is a baseline diff that quietly stops happening by Wednesday.
That’s the boundary where fleet orchestration earns its keep. WinSentinel Pro puts an agent on each endpoint reporting the same autostart audit into a central node — the depth is identical to what you run free; Pro doesn’t unlock extra ASEPs. What it adds is the org-level layer: a fleet-wide baseline so a new scheduled task appearing on one machine stands out against the other 79; drift alerts that fire the moment a persistence entry shows up rather than at next month’s manual sweep; and historical trend data proving the fleet’s autostart surface stayed clean over an audit window. Single-machine persistence hunting is free and complete. The fleet-and-time version — “which of my 80 machines grew a new autostart entry overnight?” as one alert — is the org problem Pro exists to solve.
The Takeaway
You do not evict an attacker by killing their process. You evict them by finding the durable entry that brings the process back, and Windows hides that entry in a dozen places most hunts never check. Treat your autostart inventory the way you treat your firewall rules: known, baselined, and diffed. The reboot is the attacker’s reset button — make sure it’s yours instead.
# Hunt persistence across every autostart surface on this machine:
winsentinel --audit
# Then remediate the entries that don’t belong:
winsentinel --fix-it
The attacker only needs one autostart entry to survive. Auditing all of them is how you make sure they don’t get to keep it.