Persistence techniques
The persistence/* package tree groups Windows-only mechanisms
that re-launch an implant across reboots and user logons. The
Mechanism interface is the composition
primitive: each sub-package returns a Mechanism, and
InstallAll / VerifyAll /
UninstallAll operate on a flat slice — operators typically
install two or three mechanisms in parallel so failure of any
single one (cleanup sweep, AV remediation, EDR auto-roll-back)
does not lose persistence.
flowchart TB
subgraph trig [Triggers]
LOGON[user logon]
BOOT[boot]
SCHED[schedule / time]
CLICK[user execution]
end
subgraph mechs [persistence/*]
REG[registry<br>HKCU + HKLM<br>Run / RunOnce]
ST[startup<br>StartUp-folder LNK]
SCHEDP[scheduler<br>COM ITaskService]
SVC[service<br>SCM SYSTEM]
ACC[account<br>local user + admin]
LNK[lnk<br>shortcut primitive]
end
subgraph compose [Composition]
IFACE[Mechanism interface]
ALL[InstallAll / VerifyAll / UninstallAll]
end
LOGON --> REG
LOGON --> ST
LOGON --> SCHEDP
BOOT --> SVC
BOOT --> SCHEDP
SCHED --> SCHEDP
CLICK --> LNK
ACC -. companion to .-> SVC
LNK -. underlying primitive of .-> ST
REG --> IFACE
ST --> IFACE
SCHEDP --> IFACE
SVC --> IFACE
IFACE --> ALL
Where to start (novice path):
registry— HKCU Run key. The classic "implant relaunches at every user logon" mechanism. Smallest footprint, easiest to set up.startup-folder— drop a LNK in the Startup folder. Same trigger (user logon), different artefact class — use one or the other based on which surface defenders inventory.task-scheduler— COM ITaskService. Survives when Run keys / startup folder get cleaned by AV remediation. Heavier setup but most resilient.service— boot-time SYSTEM persistence. Requires admin; pair withcleanup/serviceto hide it fromservices.msc.- Compose 2-3 mechanisms via
InstallAllso failure of one doesn't lose persistence. NEVER rely on a single mechanism.
Packages
| Package | Tech page | Detection | One-liner |
|---|---|---|---|
persistence/registry | registry.md | moderate | HKCU + HKLM Run / RunOnce key persistence |
persistence/startup | startup-folder.md | moderate | StartUp-folder LNK persistence (user + machine) |
persistence/scheduler | task-scheduler.md | moderate | COM-based scheduled tasks; logon / startup / daily / time triggers |
persistence/service | service.md | noisy | Windows service via SCM (SYSTEM-scope) |
persistence/lnk | lnk.md | quiet | Underlying LNK creation primitive (used by startup, also for T1204.002 user-execution traps) |
persistence/account | account.md | noisy | Local user account add / delete / group membership |
Quick decision tree
| You want to… | Use |
|---|---|
| …survive a reboot, no admin | registry.RunKey(HiveCurrentUser, …) or startup.Shortcut |
| …survive a reboot, machine-wide | registry.RunKey(HiveLocalMachine, …) or startup.InstallMachine |
| …trigger before user logon (boot / startup) | scheduler with WithTriggerStartup or service |
| …schedule recurring callbacks | scheduler.Create with WithTriggerDaily |
| …run as SYSTEM | service or scheduler with startup trigger |
| …compose multiple mechanisms with redundancy | persistence.InstallAll |
| …leave a credential that survives implant removal | account.Add + SetAdmin (loud) |
| …drop a user-execution trap (Desktop / Quick Launch) | lnk.New |
Layered redundancy recipe
The canonical "redundant persistence" pattern installs two mechanisms with different telemetry profiles. Loss of one does not lose persistence; the noisier one provides reach, the quieter one provides resilience.
mechs := []persistence.Mechanism{
// Loud + reach: SYSTEM-scope service, runs at boot.
service.Service(&service.Config{
Name: "WinUpdate",
BinPath: `C:\ProgramData\Microsoft\winupdate.exe`,
StartType: service.StartAuto,
}),
// Quiet + resilience: HKCU Run-key, runs at user logon.
registry.RunKey(registry.HiveCurrentUser, registry.KeyRun,
"WinUpdateBackup",
`C:\ProgramData\Microsoft\winupdate.exe`),
}
errs := persistence.InstallAll(mechs)
MITRE ATT&CK
| T-ID | Name | Packages | D3FEND counter |
|---|---|---|---|
| T1547.001 | Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder | persistence/registry, persistence/startup | D3-SICA, D3-FCA |
| T1547.009 | Shortcut Modification | persistence/lnk, persistence/startup | D3-FCA |
| T1053.005 | Scheduled Task/Job: Scheduled Task | persistence/scheduler | D3-SCA |
| T1543.003 | Create or Modify System Process: Windows Service | persistence/service | D3-PSA, D3-SICA |
| T1136.001 | Create Account: Local Account | persistence/account | D3-LAM |
| T1098 | Account Manipulation | persistence/account (group changes) | D3-UAP |
| T1204.002 | User Execution: Malicious File | persistence/lnk (Desktop / Quick Launch traps) | D3-FCA |
See also
- Operator path: persistence selection
- Detection eng path: persistence telemetry
pe/masquerade— clone svchost identity for the persisted binary.pe/cert— graft Authenticode signature.cleanup— remove persistence artefacts at op end.privesc— pair to obtain the admin / SYSTEM tokens HKLM-scope and SCM persistence require.