When you restart, running programs stop. Persistence is how malware adds itself to the startup sequence. Options range from obvious (registry Run keys, startup folder) to stealthy (WMI subscriptions, service binary hijacking, SetupComplete.cmd). Each level requires different privileges. Higher-privilege persistence is harder to detect and remove but requires the attacker to already have elevated access.
Persistence mechanisms vary by privilege level. Understanding what's available at each level helps defenders prioritize hunting and attackers understand why escalation matters.
HKCU\Software\Microsoft\Windows\CurrentVersion\Run - Current user only%APPDATA%\Microsoft\Windows\Start Menu\Programs\StartupLimitation: Easy to find and remove by any admin. Doesn't survive password changes or profile deletions.
HKLM\Software\Microsoft\Windows\CurrentVersion\Run - All usersThe smart move: Escalate to SYSTEM before installing persistence. SYSTEM-level persistence survives admin password changes.
Why it matters: SYSTEM persistence is invisible to standard admin tools. Survives credential rotations. Requires specialized forensics to detect.
Windows runs C:\Windows\Setup\Scripts\SetupComplete.cmd automatically after any Windows setup completion, OEM customisation, or system reset (Windows Recovery). Writing persistence here survives a user-initiated "Reset this PC" — it executes before the new user session is created.
Requires admin or SYSTEM. Source: shellchain-phoenix C2 framework dual-persistence module (sanitized).
# PowerShell — create SetupComplete.cmd (Admin/SYSTEM required) # Source: shellchain-phoenix/payload/stage_phoenix.ps1 (SANITIZE — operational paths removed) $setupScripts = 'C:\Windows\Setup\Scripts' New-Item -ItemType Directory -Force -Path $setupScripts | Out-Null $cmdContent = @" @echo off copy "[PAYLOAD_PATH]" "C:\Users\Public\[PAYLOAD].vbs" /Y icacls "C:\Users\Public\[PAYLOAD].vbs" /grant Everyone:F reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /v [NAME] /t REG_SZ ^ /d "wscript //nologo C:\Users\Public\[PAYLOAD].vbs" /f /reg:64 "@ Set-Content -Path "$setupScripts\SetupComplete.cmd" -Value $cmdContent -Encoding ASCII
Monitor C:\Windows\Setup\Scripts\ for new or modified files — legitimate post-setup scripts are uncommon outside enterprise provisioning. MITRE T1037.001. Alert on any write to SetupComplete.cmd outside of OS deployment tooling.
Sophisticated attackers follow a pattern:
Even if defenders find and remove the user-level persistence, the SYSTEM-level persistence remains undetected.
User level: Standard autoruns tools catch most. Check Sysinternals Autoruns, review HKCU Run keys, scheduled tasks.
Admin level: Services, AppInit_DLLs, HKLM keys. Requires admin access to review. Compare against known-good baselines.
SYSTEM level: Requires memory forensics, driver analysis, EDR with kernel visibility. Look for unsigned drivers, modified system binaries, unusual SSPs.
Persistence isn't Windows-only. Attackers target macOS and Linux using native scheduling and service management. Understanding these helps defenders protect multi-OS environments.
~/.bashrc / ~/.profile — Executes on user shell login (user-level)crontab -e — User-scheduled tasks, persists across reboots/etc/cron.d/ — System-wide cron (root required)systemd user services — ~/.config/systemd/user/ (user-level)systemd system services — /etc/systemd/system/ (root required)Detection: Compare crontab -l and systemctl list-unit-files against known baselines. Monitor /etc/cron.* directories for new files.
~/Library/LaunchAgents/ — User login items (user-level)/Library/LaunchAgents/ — All users (admin required)/Library/LaunchDaemons/ — System daemons (root required)Detection: Review launchctl list output. Monitor plist creation in LaunchAgents/Daemons directories. Check ~/Library/Application Support/ for unexpected scripts.
Source: 22nd Survey Division persistence research (concept flow — operational details removed).
# CONCEPT: Cross-platform persistence decision logic (PSEUDOCODE) # Real implants check privilege level and choose appropriate mechanism def install_persistence(privilege_level, platform): if platform == "windows": if privilege_level == "user": # HKCU\...\Run or Startup folder add_registry_run(HKCU, "[PAYLOAD_PATH]") elif privilege_level == "admin": # Scheduled task or HKLM Run create_schtask("[TASK_NAME]", "[PAYLOAD_PATH]") elif privilege_level == "system": # Service or SetupComplete.cmd create_service("[SVC_NAME]", "[PAYLOAD_PATH]") elif platform == "linux": if privilege_level == "user": # User cron or systemd user service add_cron_entry("@reboot [PAYLOAD_PATH]") elif privilege_level == "root": # System cron or systemd service create_systemd_service("[SVC_NAME]") elif platform == "darwin": # macOS if privilege_level == "user": # ~/Library/LaunchAgents/*.plist create_launch_agent("[LABEL]", "[PAYLOAD_PATH]") elif privilege_level == "root": # /Library/LaunchDaemons/*.plist create_launch_daemon("[LABEL]", "[PAYLOAD_PATH]")
Why this matters: Defenders should check all three categories on a compromised host. An attacker with root/SYSTEM will install persistence at EVERY level they have access to — user-level as a fallback, system-level as primary.
When investigating a compromised system:
MITRE ATT&CK: T1547 (Boot or Logon Autostart Execution), T1053 (Scheduled Task/Job), T1543.002 (Systemd Service), T1543.001 (Launch Agent/Daemon)