mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-20 14:30:59 +03:00
- Add validated mitre_attack frontmatter to all 754 skills (286 distinct techniques), verified against MITRE ATT&CK v19.1 via the official mitreattack-python library: 0 revoked, deprecated, or invalid IDs - Curate precise per-skill technique IDs for forensics, malware-analysis, threat-intel, and red-team skills (e.g. DCSync -> T1003.006, Kerberoasting -> T1558.003, Pass-the-Ticket -> T1550.003) - Reconcile v19.1 tactic restructuring: Defense Evasion split into Stealth (TA0005) and Defense Impairment (TA0112); revoked T1562.* family and T1070.001/.002 remapped to active equivalents (T1685.*) - Normalize word-split tags across 35 skills (remove filename-derived stopword tags, add semantic cybersecurity tags) - Add api-reference.md for 3 skills that were missing it - Update README ATT&CK section with accurate v19.1 tactic distribution
477 lines
18 KiB
Markdown
477 lines
18 KiB
Markdown
---
|
|
name: performing-malware-persistence-investigation
|
|
description: Systematically investigate all persistence mechanisms on Windows and
|
|
Linux systems to identify how malware survives reboots and maintains access.
|
|
domain: cybersecurity
|
|
subdomain: digital-forensics
|
|
tags:
|
|
- forensics
|
|
- malware-persistence
|
|
- autoruns
|
|
- registry
|
|
- scheduled-tasks
|
|
- rootkit-detection
|
|
- incident-response
|
|
mitre_attack:
|
|
- T1005
|
|
- T1074
|
|
- T1119
|
|
- T1070
|
|
- T1547
|
|
version: '1.0'
|
|
author: mahipal
|
|
license: Apache-2.0
|
|
nist_csf:
|
|
- RS.AN-01
|
|
- RS.AN-03
|
|
- DE.AE-02
|
|
- RS.MA-01
|
|
---
|
|
|
|
# Performing Malware Persistence Investigation
|
|
|
|
## When to Use
|
|
- When investigating how malware maintains presence on a compromised system after reboots
|
|
- During incident response to identify all persistence mechanisms for complete remediation
|
|
- For threat hunting to discover unauthorized autostart entries across endpoints
|
|
- When analyzing malware behavior to understand its persistence strategy
|
|
- For verifying that all persistence has been removed after incident remediation
|
|
|
|
## Prerequisites
|
|
- Forensic image or live system access with administrative privileges
|
|
- Autoruns (Sysinternals) for Windows persistence enumeration
|
|
- RegRipper for offline registry analysis
|
|
- Understanding of Windows and Linux persistence mechanisms
|
|
- YARA rules for scanning persistence locations
|
|
- Baseline of known-good autorun entries for comparison
|
|
|
|
## Workflow
|
|
|
|
### Step 1: Enumerate Windows Registry Persistence
|
|
|
|
```bash
|
|
# Extract registry hives from forensic image
|
|
mount -o ro,loop,offset=$((2048*512)) /cases/case-2024-001/images/evidence.dd /mnt/evidence
|
|
|
|
# Key registry persistence locations
|
|
python3 << 'PYEOF'
|
|
from Registry import Registry
|
|
import json
|
|
|
|
results = {'registry_persistence': []}
|
|
|
|
# SYSTEM hive analysis
|
|
system_reg = Registry.Registry("/cases/case-2024-001/registry/SYSTEM")
|
|
select = system_reg.open("Select")
|
|
current = select.value("Current").value()
|
|
cs = f"ControlSet{current:03d}"
|
|
|
|
# Services (very common persistence)
|
|
services = system_reg.open(f"{cs}\\Services")
|
|
for svc in services.subkeys():
|
|
try:
|
|
start_type = svc.value("Start").value()
|
|
image_path = ""
|
|
try:
|
|
image_path = svc.value("ImagePath").value()
|
|
except:
|
|
pass
|
|
# Start types: 0=Boot, 1=System, 2=Auto, 3=Manual, 4=Disabled
|
|
if start_type in (0, 1, 2) and image_path:
|
|
svc_type = svc.value("Type").value() if svc.values() else 0
|
|
results['registry_persistence'].append({
|
|
'location': f'HKLM\\SYSTEM\\{cs}\\Services\\{svc.name()}',
|
|
'type': 'Service',
|
|
'value': image_path,
|
|
'start_type': start_type,
|
|
'timestamp': str(svc.timestamp())
|
|
})
|
|
except Exception:
|
|
pass
|
|
|
|
# SOFTWARE hive analysis
|
|
sw_reg = Registry.Registry("/cases/case-2024-001/registry/SOFTWARE")
|
|
|
|
# Machine Run keys
|
|
run_keys = [
|
|
"Microsoft\\Windows\\CurrentVersion\\Run",
|
|
"Microsoft\\Windows\\CurrentVersion\\RunOnce",
|
|
"Microsoft\\Windows\\CurrentVersion\\RunServices",
|
|
"Microsoft\\Windows\\CurrentVersion\\RunServicesOnce",
|
|
"Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\Run",
|
|
"Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run",
|
|
"Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnce",
|
|
]
|
|
|
|
for key_path in run_keys:
|
|
try:
|
|
key = sw_reg.open(key_path)
|
|
for value in key.values():
|
|
results['registry_persistence'].append({
|
|
'location': f'HKLM\\SOFTWARE\\{key_path}',
|
|
'type': 'Run Key',
|
|
'name': value.name(),
|
|
'value': str(value.value()),
|
|
'timestamp': str(key.timestamp())
|
|
})
|
|
except Exception:
|
|
pass
|
|
|
|
# NTUSER.DAT analysis
|
|
import glob
|
|
for ntuser in glob.glob("/cases/case-2024-001/registry/NTUSER*.DAT"):
|
|
try:
|
|
user_reg = Registry.Registry(ntuser)
|
|
user_run_keys = [
|
|
"Software\\Microsoft\\Windows\\CurrentVersion\\Run",
|
|
"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce",
|
|
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\\Startup",
|
|
]
|
|
for key_path in user_run_keys:
|
|
try:
|
|
key = user_reg.open(key_path)
|
|
for value in key.values():
|
|
results['registry_persistence'].append({
|
|
'location': f'HKCU\\{key_path}',
|
|
'type': 'User Run Key',
|
|
'name': value.name(),
|
|
'value': str(value.value()),
|
|
'timestamp': str(key.timestamp()),
|
|
'hive': ntuser
|
|
})
|
|
except Exception:
|
|
pass
|
|
except Exception:
|
|
pass
|
|
|
|
print(f"Total registry persistence entries: {len(results['registry_persistence'])}")
|
|
for entry in results['registry_persistence']:
|
|
print(f" [{entry['type']}] {entry.get('name', '')} -> {entry.get('value', '')[:100]}")
|
|
|
|
with open('/cases/case-2024-001/analysis/registry_persistence.json', 'w') as f:
|
|
json.dump(results, f, indent=2)
|
|
PYEOF
|
|
```
|
|
|
|
### Step 2: Check Scheduled Tasks and WMI Persistence
|
|
|
|
```bash
|
|
# Extract scheduled tasks from forensic image
|
|
mkdir -p /cases/case-2024-001/persistence/tasks/
|
|
cp -r /mnt/evidence/Windows/System32/Tasks/* /cases/case-2024-001/persistence/tasks/ 2>/dev/null
|
|
|
|
# Parse scheduled task XML files
|
|
python3 << 'PYEOF'
|
|
import os, xml.etree.ElementTree as ET
|
|
|
|
tasks_dir = '/cases/case-2024-001/persistence/tasks/'
|
|
suspicious_tasks = []
|
|
|
|
for root_dir, dirs, files in os.walk(tasks_dir):
|
|
for fname in files:
|
|
fpath = os.path.join(root_dir, fname)
|
|
try:
|
|
tree = ET.parse(fpath)
|
|
root = tree.getroot()
|
|
ns = {'t': 'http://schemas.microsoft.com/windows/2004/02/mit/task'}
|
|
|
|
actions = root.findall('.//t:Exec', ns)
|
|
for action in actions:
|
|
command = action.find('t:Command', ns)
|
|
args = action.find('t:Arguments', ns)
|
|
cmd_text = command.text if command is not None else ''
|
|
args_text = args.text if args is not None else ''
|
|
|
|
# Flag suspicious commands
|
|
suspicious_indicators = [
|
|
'powershell', 'cmd.exe', 'wscript', 'cscript', 'mshta',
|
|
'regsvr32', 'rundll32', 'certutil', 'bitsadmin',
|
|
'/c ', '-enc', '-e ', 'hidden', 'bypass', 'downloadstring',
|
|
'invoke-', 'iex', '/tmp/', 'appdata', 'programdata',
|
|
'temp\\', '.ps1', '.vbs', '.hta', 'base64'
|
|
]
|
|
|
|
is_suspicious = any(s in (cmd_text + ' ' + args_text).lower() for s in suspicious_indicators)
|
|
|
|
task_info = {
|
|
'name': fname,
|
|
'path': fpath.replace(tasks_dir, ''),
|
|
'command': cmd_text,
|
|
'arguments': args_text,
|
|
'suspicious': is_suspicious
|
|
}
|
|
|
|
if is_suspicious:
|
|
suspicious_tasks.append(task_info)
|
|
print(f"SUSPICIOUS TASK: {fname}")
|
|
print(f" Command: {cmd_text}")
|
|
print(f" Arguments: {args_text}")
|
|
print()
|
|
|
|
except Exception as e:
|
|
pass
|
|
|
|
print(f"\nTotal suspicious scheduled tasks: {len(suspicious_tasks)}")
|
|
PYEOF
|
|
|
|
# Check WMI event subscriptions (common APT persistence)
|
|
# WMI repository: C:\Windows\System32\wbem\Repository\
|
|
cp -r /mnt/evidence/Windows/System32/wbem/Repository/ /cases/case-2024-001/persistence/wmi/ 2>/dev/null
|
|
|
|
# Parse WMI persistence using PyWMIPersistenceFinder
|
|
python3 << 'PYEOF'
|
|
import os, re
|
|
|
|
# Search WMI OBJECTS.DATA for event subscriptions
|
|
wmi_db = '/cases/case-2024-001/persistence/wmi/OBJECTS.DATA'
|
|
if os.path.exists(wmi_db):
|
|
with open(wmi_db, 'rb') as f:
|
|
data = f.read()
|
|
|
|
# Search for EventFilter strings
|
|
filters = re.findall(b'__EventFilter.*?(?=\x00\x00)', data)
|
|
consumers = re.findall(b'CommandLineEventConsumer.*?(?=\x00\x00)', data)
|
|
bindings = re.findall(b'__FilterToConsumerBinding.*?(?=\x00\x00)', data)
|
|
|
|
print("=== WMI PERSISTENCE ===")
|
|
print(f"Event Filters: {len(filters)}")
|
|
print(f"Command Consumers: {len(consumers)}")
|
|
print(f"Filter-Consumer Bindings: {len(bindings)}")
|
|
|
|
for consumer in consumers:
|
|
decoded = consumer.decode('utf-8', errors='ignore')
|
|
print(f" Consumer: {decoded[:200]}")
|
|
else:
|
|
print("WMI repository not found")
|
|
PYEOF
|
|
```
|
|
|
|
### Step 3: Check File System and Boot Persistence
|
|
|
|
```bash
|
|
# Startup folders
|
|
echo "=== STARTUP FOLDER CONTENTS ===" > /cases/case-2024-001/analysis/startup_items.txt
|
|
|
|
ls -la "/mnt/evidence/ProgramData/Microsoft/Windows/Start Menu/Programs/Startup/" \
|
|
>> /cases/case-2024-001/analysis/startup_items.txt 2>/dev/null
|
|
|
|
for userdir in /mnt/evidence/Users/*/; do
|
|
username=$(basename "$userdir")
|
|
echo "--- User: $username ---" >> /cases/case-2024-001/analysis/startup_items.txt
|
|
ls -la "$userdir/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup/" \
|
|
>> /cases/case-2024-001/analysis/startup_items.txt 2>/dev/null
|
|
done
|
|
|
|
# Check DLL search order hijacking locations
|
|
echo "=== DLL HIJACKING CHECK ===" > /cases/case-2024-001/analysis/dll_hijack.txt
|
|
# Check for DLLs in application directories that should only be in System32
|
|
find /mnt/evidence/Program\ Files/ /mnt/evidence/Program\ Files\ \(x86\)/ \
|
|
-name "*.dll" -newer /mnt/evidence/Windows/System32/ntdll.dll 2>/dev/null \
|
|
>> /cases/case-2024-001/analysis/dll_hijack.txt
|
|
|
|
# Check for COM object hijacking
|
|
python3 << 'PYEOF'
|
|
from Registry import Registry
|
|
|
|
reg = Registry.Registry("/cases/case-2024-001/registry/SOFTWARE")
|
|
|
|
# Check for suspicious CLSID entries
|
|
try:
|
|
clsid = reg.open("Classes\\CLSID")
|
|
for key in clsid.subkeys():
|
|
try:
|
|
server = key.subkey("InprocServer32")
|
|
dll_path = server.value("(default)").value()
|
|
if any(s in dll_path.lower() for s in ['temp', 'appdata', 'programdata', 'downloads', 'tmp']):
|
|
print(f"SUSPICIOUS COM: {key.name()} -> {dll_path}")
|
|
except:
|
|
pass
|
|
except:
|
|
pass
|
|
PYEOF
|
|
|
|
# Check boot configuration for bootkits
|
|
# BCD (Boot Configuration Data)
|
|
ls -la /mnt/evidence/Boot/BCD 2>/dev/null
|
|
# Check for modified bootmgr or winload.exe
|
|
sha256sum /mnt/evidence/Windows/System32/winload.exe 2>/dev/null
|
|
```
|
|
|
|
### Step 4: Check Linux Persistence Mechanisms
|
|
|
|
```bash
|
|
# If analyzing a Linux system
|
|
LINUX_ROOT="/mnt/evidence"
|
|
|
|
echo "=== LINUX PERSISTENCE CHECK ===" > /cases/case-2024-001/analysis/linux_persistence.txt
|
|
|
|
# Cron jobs
|
|
echo "--- Cron Jobs ---" >> /cases/case-2024-001/analysis/linux_persistence.txt
|
|
cat $LINUX_ROOT/etc/crontab >> /cases/case-2024-001/analysis/linux_persistence.txt 2>/dev/null
|
|
ls -la $LINUX_ROOT/etc/cron.d/ >> /cases/case-2024-001/analysis/linux_persistence.txt 2>/dev/null
|
|
cat $LINUX_ROOT/etc/cron.d/* >> /cases/case-2024-001/analysis/linux_persistence.txt 2>/dev/null
|
|
cat $LINUX_ROOT/var/spool/cron/crontabs/* >> /cases/case-2024-001/analysis/linux_persistence.txt 2>/dev/null
|
|
|
|
# Systemd services
|
|
echo "--- Custom Systemd Services ---" >> /cases/case-2024-001/analysis/linux_persistence.txt
|
|
find $LINUX_ROOT/etc/systemd/system/ -name "*.service" -not -type l \
|
|
>> /cases/case-2024-001/analysis/linux_persistence.txt 2>/dev/null
|
|
|
|
# SSH authorized keys
|
|
echo "--- SSH Authorized Keys ---" >> /cases/case-2024-001/analysis/linux_persistence.txt
|
|
find $LINUX_ROOT/home/ $LINUX_ROOT/root/ -name "authorized_keys" -exec cat {} \; \
|
|
>> /cases/case-2024-001/analysis/linux_persistence.txt 2>/dev/null
|
|
|
|
# Init scripts and rc.local
|
|
echo "--- RC Scripts ---" >> /cases/case-2024-001/analysis/linux_persistence.txt
|
|
cat $LINUX_ROOT/etc/rc.local >> /cases/case-2024-001/analysis/linux_persistence.txt 2>/dev/null
|
|
|
|
# Shell profile scripts
|
|
echo "--- Profile Scripts ---" >> /cases/case-2024-001/analysis/linux_persistence.txt
|
|
cat $LINUX_ROOT/etc/profile.d/*.sh >> /cases/case-2024-001/analysis/linux_persistence.txt 2>/dev/null
|
|
|
|
# LD_PRELOAD
|
|
echo "--- LD_PRELOAD ---" >> /cases/case-2024-001/analysis/linux_persistence.txt
|
|
cat $LINUX_ROOT/etc/ld.so.preload >> /cases/case-2024-001/analysis/linux_persistence.txt 2>/dev/null
|
|
grep -r "LD_PRELOAD" $LINUX_ROOT/etc/ >> /cases/case-2024-001/analysis/linux_persistence.txt 2>/dev/null
|
|
|
|
# Kernel modules
|
|
echo "--- Loaded Kernel Modules ---" >> /cases/case-2024-001/analysis/linux_persistence.txt
|
|
cat $LINUX_ROOT/etc/modules-load.d/*.conf >> /cases/case-2024-001/analysis/linux_persistence.txt 2>/dev/null
|
|
|
|
# PAM backdoors
|
|
echo "--- PAM Configuration ---" >> /cases/case-2024-001/analysis/linux_persistence.txt
|
|
find $LINUX_ROOT/etc/pam.d/ -exec grep -l "pam_exec\|pam_script" {} \; \
|
|
>> /cases/case-2024-001/analysis/linux_persistence.txt 2>/dev/null
|
|
```
|
|
|
|
### Step 5: Compile Persistence Report
|
|
|
|
```bash
|
|
# Generate comprehensive persistence report
|
|
python3 << 'PYEOF'
|
|
import json
|
|
|
|
with open('/cases/case-2024-001/analysis/registry_persistence.json') as f:
|
|
reg_data = json.load(f)
|
|
|
|
report = """
|
|
MALWARE PERSISTENCE INVESTIGATION REPORT
|
|
==========================================
|
|
|
|
PERSISTENCE MECHANISMS FOUND:
|
|
|
|
1. REGISTRY RUN KEYS:
|
|
"""
|
|
|
|
run_keys = [e for e in reg_data['registry_persistence'] if 'Run' in e.get('type', '')]
|
|
for entry in run_keys:
|
|
report += f" [{entry['timestamp']}] {entry.get('name', 'N/A')} -> {entry.get('value', '')[:100]}\n"
|
|
|
|
services = [e for e in reg_data['registry_persistence'] if e.get('type') == 'Service']
|
|
report += f"\n2. SERVICES ({len(services)} auto-start services):\n"
|
|
for entry in services[:20]:
|
|
report += f" {entry['location'].split('\\')[-1]}: {entry['value'][:100]}\n"
|
|
|
|
report += """
|
|
3. SCHEDULED TASKS: [See scheduled_tasks analysis]
|
|
4. WMI SUBSCRIPTIONS: [See WMI analysis]
|
|
5. STARTUP FOLDER: [See startup_items.txt]
|
|
6. COM HIJACKING: [See COM analysis]
|
|
|
|
SUSPICIOUS ENTRIES REQUIRING INVESTIGATION:
|
|
"""
|
|
|
|
# Flag suspicious entries
|
|
for entry in reg_data['registry_persistence']:
|
|
value = str(entry.get('value', '')).lower()
|
|
suspicious_indicators = ['powershell', 'cmd /c', 'wscript', 'certutil',
|
|
'programdata', 'appdata\\local\\temp', 'base64',
|
|
'.ps1', '.vbs', '.hta', '/tmp/', 'hidden']
|
|
if any(s in value for s in suspicious_indicators):
|
|
report += f" SUSPICIOUS: {entry.get('name', 'N/A')} -> {entry.get('value', '')[:100]}\n"
|
|
|
|
with open('/cases/case-2024-001/analysis/persistence_report.txt', 'w') as f:
|
|
f.write(report)
|
|
|
|
print(report)
|
|
PYEOF
|
|
```
|
|
|
|
## Key Concepts
|
|
|
|
| Concept | Description |
|
|
|---------|-------------|
|
|
| Run keys | Registry keys executing programs at user logon (HKLM and HKCU) |
|
|
| Scheduled tasks | Windows Task Scheduler entries that execute on triggers (time, event, logon) |
|
|
| WMI event subscriptions | Persistent WMI queries that trigger actions (stealthy persistence) |
|
|
| COM hijacking | Redirecting COM object loading to execute malicious DLLs |
|
|
| DLL search order hijacking | Placing malicious DLLs in directories searched before System32 |
|
|
| Service persistence | Installing Windows services that auto-start with the system |
|
|
| Boot-level persistence | Modifying boot configuration or MBR/VBR for pre-OS execution |
|
|
| Living-off-the-land | Using legitimate system tools (PowerShell, WMI, certutil) for persistence |
|
|
|
|
## Tools & Systems
|
|
|
|
| Tool | Purpose |
|
|
|------|---------|
|
|
| Autoruns | Sysinternals comprehensive autostart enumeration tool |
|
|
| RegRipper | Automated registry persistence artifact extraction |
|
|
| KAPE | Automated persistence artifact collection and analysis |
|
|
| Velociraptor | Endpoint agent with persistence hunting artifacts |
|
|
| OSQuery | SQL-based system querying for persistence enumeration |
|
|
| PersistenceSniper | PowerShell tool for Windows persistence detection |
|
|
| RECmd | Eric Zimmerman registry command-line analysis tool |
|
|
| Volatility | Memory forensics for in-memory only persistence |
|
|
|
|
## Common Scenarios
|
|
|
|
**Scenario 1: APT Persistence After Initial Compromise**
|
|
Check all registry Run keys, enumerate scheduled tasks for encoded PowerShell commands, examine WMI event subscriptions for event-triggered execution, check COM object registrations for hijacked CLSIDs, review services for recently installed entries with suspicious image paths.
|
|
|
|
**Scenario 2: Ransomware Pre-Encryption Persistence**
|
|
Identify how the ransomware maintains access for re-encryption or monitoring, check for scheduled tasks that would re-launch encryption, examine services installed by the ransomware operator, verify no additional backdoor persistence exists before declaring remediation complete.
|
|
|
|
**Scenario 3: Fileless Malware Persistence**
|
|
Focus on registry-based persistence storing payload in registry values, check WMI subscriptions executing PowerShell from event triggers, examine scheduled tasks using encoded command arguments, check for mshta/rundll32 based persistence loading remote content.
|
|
|
|
**Scenario 4: Post-Remediation Verification**
|
|
Run Autoruns comparison against known-good baseline, verify all identified persistence mechanisms have been removed, check for additional persistence that may have been missed, confirm services, tasks, and registry entries are clean, monitor for re-infection indicators.
|
|
|
|
## Output Format
|
|
|
|
```
|
|
Persistence Investigation Summary:
|
|
System: DESKTOP-ABC123 (Windows 10 Pro)
|
|
Analysis Date: 2024-01-20
|
|
|
|
Persistence Mechanisms Found:
|
|
Registry Run Keys (HKLM): 5 entries (1 SUSPICIOUS)
|
|
Registry Run Keys (HKCU): 3 entries (1 SUSPICIOUS)
|
|
Services (Auto-Start): 142 entries (2 SUSPICIOUS)
|
|
Scheduled Tasks: 67 entries (3 SUSPICIOUS)
|
|
WMI Subscriptions: 1 entry (SUSPICIOUS)
|
|
Startup Folder: 4 items (1 SUSPICIOUS)
|
|
COM Objects: 0 hijacked entries
|
|
DLL Hijacking: 0 detected
|
|
|
|
Suspicious Entries:
|
|
1. HKCU\Run\WindowsUpdate -> powershell -ep bypass -e <base64>
|
|
Timestamp: 2024-01-15 14:35:00
|
|
Action: Encoded PowerShell download cradle
|
|
|
|
2. Service: WinDefenderUpdate -> C:\ProgramData\svc\update.exe
|
|
Timestamp: 2024-01-15 14:40:00
|
|
Action: Unknown executable in ProgramData
|
|
|
|
3. Task: \Microsoft\Windows\Maintenance\SecurityUpdate
|
|
Command: cmd.exe /c powershell -w hidden -e <base64>
|
|
Trigger: On system startup
|
|
|
|
4. WMI: __EventFilter "ProcessStart" -> CommandLineEventConsumer
|
|
Action: Execute C:\Windows\Temp\svc.exe on WMI event
|
|
|
|
Remediation Required: 4 persistence mechanisms to remove
|
|
Report: /cases/case-2024-001/analysis/persistence_report.txt
|
|
```
|