Table of Contents

← Return to the Red Team Course

User persistence arranges for an action to recur in a user’s context after a defined trigger. A configuration entry, a successful launch, and a verified removal are three separate outcomes. This module uses a visible Notepad startup entry in a disposable Windows VM to examine the complete lifecycle.

Allow about 20 minutes, plus two lab sign-ins. Use a dedicated test account and save your work before signing out.

What You Will Learn

  • Distinguish logon-triggered startup from boot-triggered services.
  • Explain user identity, executable availability, and policy dependencies.
  • Inspect startup configuration before changing it.
  • Observe a benign entry through creation, trigger, and removal.
  • Create a lifecycle record with independent cleanup evidence.
TermMeaning
Startup entryConfiguration requesting execution at a defined trigger
Run valueNamed registry value specifying a command at user logon
RunOnce valueStartup configuration intended for a single logon execution
HKCUHKEY_CURRENT_USER, resolved for the calling context
TriggerEvent which makes the configured action eligible to run
RestorationReturn to the recorded baseline with verification

Define the Persistence Requirement

Persistence is optional unless the assessment objective requires it. A short test with a controlled starting context might have no reason to create a recurring action. If recurrence is needed, define the trigger, account, duration, and removal owner before choosing a mechanism.

A Run entry uses logon, so a reboot without the relevant user signing in is not a complete test. A service with automatic startup follows a different lifecycle. User persistence also does not automatically increase the account’s permissions. Read Microsoft’s Run and RunOnce documentation .

Configuration success proves only the entry was written. The referenced executable must exist, the relevant user must encounter the trigger, and policy must permit the resulting action. Separate those dependencies in both your test and your report.

MechanismTrigger contextQuestion to verify
User Run valueRelevant user’s logonWhich user hive and command?
User Startup shortcutRelevant user’s logonWhich shortcut, target, and arguments?
Scheduled taskConfigured trigger and principalWhich conditions and execution identity?
Automatic serviceService-control startup behaviorWhich account, dependencies, and service state?

Resolve the User Context

HKCU is context-dependent. It is not a universal alias for whichever person appears on the visible desktop. Record the calling account’s SID before interpreting a user startup entry. Read Microsoft’s predefined-key reference .

Profile portability is also conditional. Even if a profile-management system carries a registry entry to another machine, the executable, path, architecture, and applicable policies still need to match. A roaming profile is not a guarantee of execution across the environment.

Scope your claim to the account and machine observed. A successful test for one user does not establish recurrence for every user on the host. Record machine-level and user-level startup locations separately.

Four connected boxes show the user baseline, named startup entry, logon execution evidence, and verified restoration of the original state

Removing configuration and stopping a running process are different cleanup tasks

Inspect Before Changing

Start with read-only queries in the test account’s shell. The first command records the SID, while the second displays values under the user Run key. A missing key or an access error is a result to document, not permission to create unrelated configuration.

whoami /user
reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Run"

reg query displays the selected key’s entries without changing them. The /v option, used later, restricts the request to a named value. Save the baseline output with the account and timestamp. Read the reg-query reference .

Autoruns provides a broader view of configured automatic-start locations. Select the appropriate user and inspect the Logon category, while recording any active filters. A hidden entry in a filtered view is not an absent entry. Read the Autoruns documentation .

Baseline fieldPurpose
Account SIDIdentify the user context
Registry path and viewReproduce the location inspected
Existing value namesAvoid overwriting another entry
Tool filtersExplain which entries the view omits
Executable pathEstablish the intended benign target

Create a Benign Lab Entry

Use native 64-bit PowerShell in a disposable 64-bit Windows VM with the dedicated account. This exercise assumes the Run key already exists and Notepad is installed at the checked system path. If either prerequisite is missing, use a prepared lab image rather than changing broader startup configuration.

The following code creates one visibly named value pointing to Notepad. It stops if the value already exists, checks the target file, and avoids a force-overwrite option. It does not copy an executable or contact a network endpoint.

$runPath = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Run'
$valueName = 'CourseLab-Notepad'
$notepadPath = Join-Path $env:SystemRoot 'System32\notepad.exe'
$runKey = Get-Item -LiteralPath $runPath -ErrorAction Stop

if ($runKey.GetValueNames() -contains $valueName) {
    throw 'The lab value already exists. Review the baseline first.'
}
if (-not (Test-Path -LiteralPath $notepadPath -PathType Leaf)) {
    throw 'The expected Notepad executable is missing.'
}
$expectedCommand = '"' + $notepadPath + '"'
New-ItemProperty -LiteralPath $runPath -Name $valueName `
    -PropertyType String -Value $expectedCommand -ErrorAction Stop

Parameter meanings: -LiteralPath uses the exact registry path, -Name selects the single new value, and -PropertyType String creates a string value. -Value stores the quoted command path, while -ErrorAction Stop prevents continuing past a reported error in the selected operation. Read New-ItemProperty .

Verify the stored value before testing logon. The query should show the visible lab name and the intended quoted path. Recheck the account SID if you opened a different shell or changed credentials.

reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v CourseLab-Notepad

Observe the Logon Trigger

Close existing Notepad windows, save the baseline and creation records, then sign out and back into the dedicated VM account. Observe whether a new Notepad instance appears and collect process evidence for the relevant window. Windows does not promise an immediate launch order for Run entries, so record the observation window rather than assuming a precise startup deadline.

Interpret the trigger carefully. Automatic application restoration or another startup entry also might launch Notepad. Correlate the new entry, the sign-in, and process evidence instead of treating a visible window as unique proof of its origin.

A missing launch calls for dependency checks. Verify the account, stored command, executable availability, startup policy, and recorded errors. Do not alter security settings merely to force the expected result.

ObservationSupported conclusion
Registry value existsConfiguration creation succeeded
Relevant logon occurredThe intended trigger was exercised
New process correlatedExecution evidence supports the tested path
No visible windowFurther evidence is needed to explain the outcome

Verify Restoration Separately

Removal starts with identity. Use the same test account and compare its SID with the creation record. Recreate the variables in the new PowerShell session, then verify the stored command still matches the lab entry before removing the named value.

$runPath = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Run'
$valueName = 'CourseLab-Notepad'
$notepadPath = Join-Path $env:SystemRoot 'System32\notepad.exe'
$expectedCommand = '"' + $notepadPath + '"'
$runKey = Get-Item -LiteralPath $runPath -ErrorAction Stop

if ($runKey.GetValueNames() -notcontains $valueName) {
    throw 'The lab value is absent. Reconcile the account and evidence.'
}
if ($runKey.GetValue($valueName) -cne $expectedCommand) {
    throw 'The value changed. Review it before removal.'
}
Remove-ItemProperty -LiteralPath $runPath -Name $valueName -ErrorAction Stop
if ((Get-Item -LiteralPath $runPath).GetValueNames() -contains $valueName) {
    throw 'The lab value is still present.'
}

Remove-ItemProperty removes the selected value rather than the entire Run key. The prechecks protect against deleting an unexpected entry encountered during the exercise. Preserve the removal result and a fresh query. Read Remove-ItemProperty .

Configuration removal does not terminate Notepad. Close the specific lab window normally, then repeat the sign-out and sign-in test. Confirm the value remains absent and no execution attributable to the lab entry recurs.

Cleanup layerEvidence
ConfigurationNamed value absent in the correct user context
Running instanceLab process or window closed normally
Later triggerNo recurrence attributable to the removed entry
BaselineUnrelated startup entries preserved

Understand Observation Limits

Startup configuration is observable regardless of whether a native utility or in-process extension writes it. MITRE documents registry Run keys and Startup folders as established persistence locations. The delivery mechanism does not erase the resulting configuration. Read ATT&CK T1547.001 .

A familiar value name is not proof of legitimate ownership. Evaluate the command, path, signer information, installation context, and observed behavior together. A file timestamp also does not establish provenance or explain who created the startup entry.

Broader startup locations have different consequences. Winlogon configuration, service settings, and application-loading mechanisms affect different triggers and process contexts. Inspect them as distinct mechanisms rather than treating every autostart entry as an interchangeable Run value.

Evidence typeUseful question
Configuration recordWhat action is requested, for whom, and when?
File identityWhich executable or document is referenced?
Execution recordDid the intended process run under the expected context?
Removal recordWas the specific change reversed and retested?

Work a Failed-Launch Case

Illustrative scenario: a user Run value appears in both the registry and Autoruns. After signing into another account, the reviewer sees no Notepad window and reports the persistence test failed. The original account’s hive still contains the lab entry.

Evaluate the report using trigger and identity evidence. Decide which part of the test was completed and which prerequisite was missed. Then write the narrowest justified next step.

Expected reasoning: configuration creation was confirmed, but the intended user’s logon was not tested. Signing into another account does not exercise the same user Run entry. Resume the test in the original lab account or record the untested trigger as a limitation.

Case variationExpected next check
Wrong user signed inReconcile SID and user hive
Correct user, missing executableConfirm path and file availability
Correct entry, delayed launchReview the observation window and execution evidence
Entry removed, window remainsClose the existing instance and test recurrence separately

Watch the Autoruns Demonstration

Aaron Margosis’s Microsoft demonstration explains Autoruns and its startup views. Watch how selecting categories, users, and filters changes the visible configuration. Identify which view supports each stage of your lab record.

Watch on YouTube: Sysinternals: Autoruns deep dive .

Create the Lifecycle Record

Document the whole exercise, including an unexpected result if one occurred. Record the before-state, exact named change, trigger, evidence, removal, and later retest. If you stop before removal verification, leave the exercise open with a named owner.

Lab asset, account SID, and registry view:
Baseline timestamp and evidence:
Value name, type, and exact command:
Creation result:
Logon trigger and observation window:
Execution evidence and alternative explanations:
Removal result and fresh configuration query:
Existing process closure:
Later logon result:
Remaining differences from baseline:

A completed record proves more than a single screenshot of Notepad. Another reviewer should reconstruct the sequence and identify the evidence supporting restoration. Keep this record for the cleanup comparison in Module 15 .

Check Your Understanding

  1. Trigger: is a reboot without user logon a sufficient Run-entry test?
  2. Identity: which account determines the HKCU context?
  3. Portability: why does a copied profile entry not guarantee execution elsewhere?
  4. Cleanup: does removing the value stop a running process?
QuestionExpected reasoning
TriggerThe relevant user logon still needs to occur
IdentityThe calling security context, verified against the recorded SID
PortabilityExecutable, path, policy, and environment dependencies remain
CleanupConfiguration removal and process termination are separate actions

Next Steps

Local privilege escalation concerns crossing a permission boundary, which user persistence alone does not establish. Continue to Module 13: Local Privilege Escalation to analyze prerequisites and supported impact. Return to the Red Team Course hub for the full sequence.