Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-SkillsFramework mappings
MITRE ATT&CK
T1053 on the official MITRE ATT&CK siteT1053.003 on the official MITRE ATT&CK siteT1053.005 on the official MITRE ATT&CK siteT1053.006 on the official MITRE ATT&CK siteT1070 on the official MITRE ATT&CK siteT1078 on the official MITRE ATT&CK siteT1098 on the official MITRE ATT&CK siteT1136 on the official MITRE ATT&CK siteT1486 on the official MITRE ATT&CK siteT1490 on the official MITRE ATT&CK siteT1505.003 on the official MITRE ATT&CK siteT1543 on the official MITRE ATT&CK siteT1543.001 on the official MITRE ATT&CK siteT1543.002 on the official MITRE ATT&CK siteT1543.003 on the official MITRE ATT&CK siteT1546.003 on the official MITRE ATT&CK siteT1546.015 on the official MITRE ATT&CK siteT1547 on the official MITRE ATT&CK siteT1547.001 on the official MITRE ATT&CK siteT1547.004 on the official MITRE ATT&CK siteT1547.005 on the official MITRE ATT&CK siteT1547.009 on the official MITRE ATT&CK siteT1556 on the official MITRE ATT&CK site
When to Use
- Malware infection confirmed and containment is in place
- Forensic investigation has identified all persistence mechanisms
- All compromised systems have been identified and scoped
- Ready to remove attacker artifacts and restore clean state
- Post-containment phase requires systematic cleanup
Prerequisites
- Completed forensic analysis identifying all malware artifacts
- List of all compromised systems and accounts
- EDR/AV with updated signatures deployed
- YARA rules for the specific malware family
- Clean system images or verified backups for restoration
- Network isolation still in effect during eradication
Workflow
Step 1: Map All Persistence Mechanisms
# Windows - Check all known persistence locations
# Autoruns (Sysinternals) - comprehensive autostart enumeration
autorunsc.exe -accepteula -a * -c -h -s -v > autoruns_report.csv
# Registry Run keys
reg query "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /s
reg query "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /s
reg query "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce" /s
reg query "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run" /s
# Scheduled tasks
schtasks /query /fo CSV /v > schtasks_all.csv
# WMI event subscriptions
Get-WMIObject -Namespace root\Subscription -Class __EventFilter
Get-WMIObject -Namespace root\Subscription -Class CommandLineEventConsumer
Get-WMIObject -Namespace root\Subscription -Class __FilterToConsumerBinding
# Services
Get-Service | Where-Object {$_.Status -eq 'Running'} | Select-Object Name, DisplayName, BinaryPathName
# Linux persistence
cat /etc/crontab
ls -la /etc/cron.*/
ls -la /etc/init.d/
systemctl list-unit-files --type=service | grep enabled
cat /etc/rc.local
ls -la ~/.bashrc ~/.profile ~/.bash_profileStep 2: Identify All Malware Artifacts
# Scan with YARA rules specific to the malware family
yara -r -s malware_rules/specific_family.yar C:\ 2>/dev/null
# Scan with multiple AV engines
# ClamAV scan
clamscan -r --infected --remove=no /mnt/infected_disk/
# Check for known malicious file hashes
find / -type f -newer /tmp/baseline_timestamp -exec sha256sum {} \; 2>/dev/null | \
while read hash file; do
grep -q "$hash" known_malicious_hashes.txt && echo "MALICIOUS: $file ($hash)"
done
# Check for web shells
find /var/www/ -name "*.php" -newer /tmp/baseline -exec grep -l "eval\|base64_decode\|system\|passthru\|shell_exec" {} \;
# Check for unauthorized SSH keys
find / -name "authorized_keys" -exec cat {} \; 2>/dev/nullStep 3: Remove Malware Files and Artifacts
# Remove identified malicious files (after forensic imaging)
# Windows
Remove-Item -Path "C:\Windows\Temp\malware.exe" -Force
Remove-Item -Path "C:\Users\Public\backdoor.dll" -Force
# Remove malicious scheduled tasks
schtasks /delete /tn "MaliciousTaskName" /f
# Remove WMI persistence
Get-WMIObject -Namespace root\Subscription -Class __EventFilter -Filter "Name='MalFilter'" | Remove-WMIObject
Get-WMIObject -Namespace root\Subscription -Class CommandLineEventConsumer -Filter "Name='MalConsumer'" | Remove-WMIObject
# Remove malicious registry entries
reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /v "MalEntry" /f
# Remove malicious services
sc stop "MalService" && sc delete "MalService"
# Linux - Remove malicious cron entries, binaries, SSH keys
crontab -r # Remove entire crontab (or edit specific entries)
rm -f /tmp/.hidden_backdoor
sed -i '/malicious_key/d' ~/.ssh/authorized_keys
systemctl disable malicious-service && rm /etc/systemd/system/malicious-service.serviceStep 4: Reset Compromised Credentials
# Reset all compromised user passwords
Import-Module ActiveDirectory
Get-ADUser -Filter * -SearchBase "OU=CompromisedUsers,DC=domain,DC=com" |
Set-ADAccountPassword -Reset -NewPassword (ConvertTo-SecureString "TempP@ss!$(Get-Random)" -AsPlainText -Force)
# Reset KRBTGT password (twice, 12+ hours apart for Kerberos golden ticket attack)
Reset-KrbtgtPassword -DomainController DC01
# Wait 12+ hours, then reset again
Reset-KrbtgtPassword -DomainController DC01
# Rotate service account passwords
Get-ADServiceAccount -Filter * | ForEach-Object {
Reset-ADServiceAccountPassword -Identity $_.Name
}
# Revoke all Azure AD tokens
Get-AzureADUser -All $true | ForEach-Object {
Revoke-AzureADUserAllRefreshToken -ObjectId $_.ObjectId
}
# Rotate API keys and secrets
# Application-specific credential rotationStep 5: Patch Vulnerability Used for Initial Access
# Identify and patch the entry point vulnerability
# Windows Update
Install-WindowsUpdate -KBArticleID "KB5001234" -AcceptAll -AutoReboot
# Linux patching
apt update && apt upgrade -y # Debian/Ubuntu
yum update -y # RHEL/CentOS
# Application-specific patches
# Update web application frameworks, CMS, etc.
# Verify patch was applied
Get-HotFix -Id "KB5001234"Step 6: Validate Eradication
# Full system scan with updated signatures
# CrowdStrike Falcon - On-demand scan
curl -X POST "https://api.crowdstrike.com/scanner/entities/scans/v1" \
-H "Authorization: Bearer $FALCON_TOKEN" \
-H "Content-Type: application/json" \
-d '{"ids": ["device_id"]}'
# Verify no persistence mechanisms remain
autorunsc.exe -accepteula -a * -c -h -s -v | findstr /i "unknown verified"
# Check for any remaining suspicious processes
Get-Process | Where-Object {$_.Path -notlike "C:\Windows\*" -and $_.Path -notlike "C:\Program Files*"}
# Verify no unauthorized network connections
Get-NetTCPConnection -State Established |
Where-Object {$_.RemoteAddress -notlike "10.*" -and $_.RemoteAddress -notlike "172.16.*"} |
Select-Object LocalPort, RemoteAddress, RemotePort, OwningProcess
# Run YARA rules again to confirm no artifacts remain
yara -r malware_rules/specific_family.yar C:\ 2>/dev/nullKey Concepts
| Concept | Description |
|---|---|
| Persistence Mechanism | Method attacker uses to maintain access across reboots |
| Root Cause Remediation | Fixing the vulnerability that enabled initial compromise |
| Credential Rotation | Resetting all potentially compromised passwords and tokens |
| KRBTGT Reset | Invalidating Kerberos tickets after golden ticket attack |
| Indicator Sweep | Scanning all systems for known malicious artifacts |
| Validation Scan | Confirming eradication was successful before recovery |
| Re-imaging | Rebuilding systems from clean images rather than cleaning |
Tools & Systems
| Tool | Purpose |
|---|---|
| Sysinternals Autoruns | Enumerate all Windows autostart locations |
| YARA | Custom rule-based malware scanning |
| CrowdStrike/SentinelOne | EDR-based scanning and remediation |
| ClamAV | Open-source antivirus scanning |
| PowerShell | Scripted cleanup and validation |
| Velociraptor | Remote artifact collection and remediation |
Common Scenarios
- RAT with Multiple Persistence: Remote access trojan using registry, scheduled task, and WMI subscription. Must remove all three persistence mechanisms.
- Web Shell on IIS/Apache: PHP/ASPX web shell in web root. Remove shell, audit all web files, patch application vulnerability.
- Rootkit Infection: Kernel-level rootkit that survives cleanup. Requires full re-image from known-good media.
- Fileless Malware: PowerShell-based attack living in memory and registry. Remove registry entries, clear WMI subscriptions, restart system.
- Active Directory Compromise: Attacker created backdoor accounts and golden tickets. Reset KRBTGT, remove rogue accounts, audit group memberships.
Output Format
- Eradication action log with all removed artifacts
- Credential rotation confirmation report
- Vulnerability patching verification
- Post-eradication validation scan results
- Systems cleared for recovery phase
Source materials
References and resources
Everything below is rendered for inspection. Script files are read-only and never run.
References 3
api-reference.md2.0 KB
API Reference: Malware Eradication
Windows Process Termination
taskkill
taskkill /F /PID 1234 # Kill by PID
taskkill /F /IM malware.exe # Kill by name
taskkill /F /T /PID 1234 # Kill process treePowerShell
Stop-Process -Id 1234 -Force
Get-Process -Name "malware" | Stop-Process -ForceWindows Persistence Cleanup
Registry Run Keys
reg delete "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v MalwareName /f
reg delete "HKLM\Software\Microsoft\Windows\CurrentVersion\Run" /v MalwareName /fScheduled Tasks
schtasks /Delete /TN "MalwareTask" /F
schtasks /Query /FO CSV /V /NHServices
sc stop MalwareService
sc delete MalwareService
sc query type= all state= allLinux Persistence Cleanup
Crontab
crontab -l -u root # List root cron
crontab -r -u root # Remove all cron (use carefully)
ls -la /etc/cron.d/
ls -la /var/spool/cron/Systemd Services
systemctl list-unit-files --type=service
systemctl disable malware.service
systemctl stop malware.service
rm /etc/systemd/system/malware.service
systemctl daemon-reloadProcess Kill
kill -9 <pid>
pkill -f "malware_pattern"File Quarantine Best Practices
Hash Before Move
sha256sum /path/to/malware > /quarantine/hash.txtSecure Move
mv /path/to/malware /quarantine/sha256_filename.quarantine
chmod 000 /quarantine/sha256_filename.quarantineAutoruns (Sysinternals)
Command Line
autorunsc.exe -a * -c -h -s -v -vtOutput Columns
| Column | Description |
|---|---|
| Entry | Autorun name |
| Image Path | Binary location |
| Signer | Code signing info |
| VT Detection | VirusTotal results |
YARA Scanning for Remaining Artifacts
Command
yara -r rules.yar /target/directoryRule Example
rule Malware_Remnant {
strings:
$s1 = "malware_mutex" ascii
$s2 = {4D 5A 90 00}
condition:
any of them
}standards.md2.8 KB
Standards and Framework References - Malware Eradication
NIST SP 800-61 Rev. 3 - Eradication Alignment
- Respond (RS.MI-02): Incidents are eradicated
- Eradication follows containment; remove all attacker artifacts
- Must address root cause, not just symptoms
- Verify eradication before moving to recovery
NIST SP 800-83 - Guide to Malware Incident Prevention and Handling
- Section 4: Handling Malware Incidents
- 4.3: Containment and Eradication
- 4.3.1: Identification of infected hosts
- 4.3.2: Containment options (quarantine, disconnect, block)
- 4.3.3: Eradication and recovery options
- Reference: https://csrc.nist.gov/pubs/sp/800/83/r1/final
SANS PICERL - Eradication Phase
- Phase 4 of SANS incident handling process
- Remove malware and attacker tools from all affected systems
- Identify and remediate the root cause
- Improve defenses based on attack methods used
MITRE ATT&CK - Persistence Techniques to Eradicate
Windows Persistence (T1547)
| Sub-technique | Location | Eradication Method |
|---|---|---|
| T1547.001 | Registry Run Keys | Delete malicious registry values |
| T1547.004 | Winlogon Helper DLL | Restore legitimate DLL path |
| T1547.005 | Security Support Provider | Remove from registry |
| T1547.009 | Shortcut Modification | Restore original shortcuts |
Scheduled Task/Job (T1053)
| Sub-technique | Location | Eradication Method |
|---|---|---|
| T1053.005 | Scheduled Task | schtasks /delete |
| T1053.003 | Cron | Remove crontab entries |
| T1053.006 | Systemd Timers | Disable and remove timer units |
Create/Modify System Process (T1543)
| Sub-technique | Location | Eradication Method |
|---|---|---|
| T1543.003 | Windows Service | sc delete ServiceName |
| T1543.002 | Systemd Service | systemctl disable + rm unit file |
| T1543.001 | Launch Agent | Remove plist file |
Other Persistence
| Technique | Description | Eradication |
|---|---|---|
| T1546.003 | WMI Event Subscription | Remove filter, consumer, binding |
| T1546.015 | COM Object Hijacking | Restore CLSID registry values |
| T1098 | Account Manipulation | Remove backdoor accounts |
| T1136 | Create Account | Delete unauthorized accounts |
| T1556 | Modify Authentication | Restore authentication mechanisms |
| T1505.003 | Web Shell | Remove web shell files |
CISA Malware Analysis Reports (MARs)
- Published IOCs and eradication guidance for specific threats
- Reference: https://www.cisa.gov/news-events/cybersecurity-advisories
Microsoft DART Eradication Guidance
- Recommended approach for Active Directory compromise recovery
- KRBTGT password reset procedures
- Tiered administration model implementation
- Reference: Microsoft Incident Response playbooks
workflows.md3.8 KB
Malware Eradication - Detailed Workflow
Pre-Eradication Checklist
- Forensic images collected from all compromised systems
- All IOCs identified and documented
- All persistence mechanisms mapped
- Root cause (initial access vector) identified
- Containment verified and holding
- Eradication plan approved by Incident Commander
- Rollback plan prepared in case eradication fails
Eradication Phases
Phase 1: Artifact Inventory
- Compile list of all malware files with paths and hashes
- Map all persistence mechanisms per system
- List all compromised accounts (user, service, admin)
- Identify all backdoor access methods
- Document network-level indicators (C2 IPs, domains)
- Note any configuration changes made by attacker
Phase 2: Coordinated Removal
Execute removal across ALL compromised systems simultaneously to prevent attacker from detecting cleanup on one system and acting on another.
Simultaneous Actions:
- Remove malware files from all systems
- Delete persistence mechanisms (registry, tasks, services, WMI)
- Disable compromised accounts
- Block all C2 infrastructure at network level
- Remove unauthorized SSH keys and certificates
- Clean up web shells from all web servers
Phase 3: Credential Reset
Priority Order:
- KRBTGT password (reset twice, 12+ hours apart)
- Domain admin accounts
- Service accounts
- All accounts that logged into compromised systems
- Application credentials and API keys
- Machine account passwords (if targeted)
Phase 4: Vulnerability Remediation
- Patch the vulnerability used for initial access
- Patch any additional vulnerabilities discovered during investigation
- Harden configurations that were exploited
- Update security tool signatures and rules
- Close unnecessary ports and services
Phase 5: Validation
- Full AV/EDR scan on all previously compromised systems
- YARA scan for specific malware family artifacts
- Check all persistence locations are clean
- Verify no unauthorized processes running
- Confirm no unauthorized network connections
- Validate all credentials were successfully rotated
- Test that patches are properly applied
Decision: Clean vs. Re-Image
When to Clean (In-Place Remediation)
- Limited number of artifacts
- Well-understood malware family
- No rootkit or bootkit components
- Time pressure requires faster recovery
- System configuration is complex to rebuild
When to Re-Image (Full Rebuild)
- Rootkit or bootkit detected
- Kernel-level compromise
- Domain controller compromise
- Inability to confirm complete eradication
- Simpler to rebuild than to clean
- Legal requirements demand clean systems
Common Persistence Locations Reference
Windows
Registry:
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunServices
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon (Shell, Userinit)
HKLM\SYSTEM\CurrentControlSet\Services
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options
Filesystem:
%AppData%\Microsoft\Windows\Start Menu\Programs\Startup
C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup
C:\Windows\System32\Tasks\
C:\Windows\System32\drivers\
WMI:
root\Subscription\__EventFilter
root\Subscription\CommandLineEventConsumer
root\Subscription\__FilterToConsumerBindingLinux
Cron:
/etc/crontab
/etc/cron.d/*
/etc/cron.daily/*
/var/spool/cron/crontabs/*
Services:
/etc/systemd/system/*.service
/etc/init.d/*
/etc/rc.local
Shell:
~/.bashrc, ~/.profile, ~/.bash_profile
/etc/profile.d/*
/etc/environment
SSH:
~/.ssh/authorized_keys
/etc/ssh/sshd_config
Other:
/etc/ld.so.preload
Kernel modules: /lib/modules/Scripts 2
agent.py7.4 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Agent for malware eradication from infected systems — process kill, file removal, persistence cleanup."""
import argparse
import json
import os
import subprocess
import sys
from datetime import datetime, timezone
PERSISTENCE_LOCATIONS_WINDOWS = [
r"HKCU\Software\Microsoft\Windows\CurrentVersion\Run",
r"HKLM\Software\Microsoft\Windows\CurrentVersion\Run",
r"HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce",
r"HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce",
r"HKLM\SYSTEM\CurrentControlSet\Services",
]
PERSISTENCE_LOCATIONS_LINUX = [
"/etc/cron.d", "/var/spool/cron", "/etc/crontab",
"/etc/init.d", "/etc/systemd/system", "/usr/lib/systemd/system",
"/etc/rc.local", "~/.bashrc", "~/.bash_profile",
]
def kill_malicious_process(pid):
"""Terminate a malicious process by PID."""
if sys.platform == "win32":
cmd = ["taskkill", "/F", "/PID", str(pid)]
else:
cmd = ["kill", "-9", str(pid)]
try:
subprocess.check_output(cmd, text=True, errors="replace", timeout=10)
return {"pid": pid, "status": "killed"}
except subprocess.SubprocessError as e:
return {"pid": pid, "status": "failed", "error": str(e)}
def quarantine_file(file_path, quarantine_dir):
"""Move malicious file to quarantine directory with metadata."""
os.makedirs(quarantine_dir, exist_ok=True)
if not os.path.isfile(file_path):
return {"file": file_path, "status": "not_found"}
import hashlib
with open(file_path, "rb") as f:
sha256 = hashlib.sha256(f.read()).hexdigest()
dest = os.path.join(quarantine_dir, f"{sha256}_{os.path.basename(file_path)}.quarantine")
try:
os.rename(file_path, dest)
meta = {
"original_path": file_path,
"sha256": sha256,
"quarantined_at": datetime.now(timezone.utc).isoformat(),
"quarantine_path": dest,
}
with open(dest + ".json", "w") as f:
json.dump(meta, f, indent=2)
return {"file": file_path, "status": "quarantined", "sha256": sha256}
except OSError as e:
return {"file": file_path, "status": "failed", "error": str(e)}
def scan_persistence_windows():
"""Scan Windows persistence locations for suspicious entries."""
findings = []
for key in PERSISTENCE_LOCATIONS_WINDOWS:
try:
result = subprocess.check_output(
["reg", "query", key], text=True, errors="replace", timeout=5
)
for line in result.splitlines():
line = line.strip()
if "REG_SZ" in line or "REG_EXPAND_SZ" in line:
parts = line.split(None, 2)
if len(parts) >= 3:
value = parts[2]
if any(d in value.lower() for d in ["temp", "appdata\\local\\temp", "public"]):
findings.append({
"key": key,
"name": parts[0],
"value": value,
"suspicious": True,
})
except subprocess.SubprocessError:
pass
return findings
def scan_persistence_linux():
"""Scan Linux persistence locations for suspicious entries."""
findings = []
for loc in PERSISTENCE_LOCATIONS_LINUX:
expanded = os.path.expanduser(loc)
if os.path.isdir(expanded):
for f in os.listdir(expanded):
fpath = os.path.join(expanded, f)
if os.path.isfile(fpath):
try:
stat = os.stat(fpath)
if stat.st_mtime > (datetime.now().timestamp() - 86400 * 7):
findings.append({
"path": fpath,
"modified": datetime.fromtimestamp(stat.st_mtime).isoformat(),
"note": "Recently modified persistence file",
})
except OSError:
pass
elif os.path.isfile(expanded):
try:
with open(expanded, "r", errors="replace") as fh:
content = fh.read()
for line in content.splitlines():
if any(s in line.lower() for s in ["curl", "wget", "nc ", "ncat", "bash -i"]):
findings.append({
"file": expanded,
"line": line.strip()[:200],
"note": "Suspicious command in startup file",
})
except PermissionError:
pass
return findings
def clean_scheduled_tasks():
"""List suspicious scheduled tasks."""
findings = []
if sys.platform == "win32":
try:
result = subprocess.check_output(
["schtasks", "/Query", "/FO", "CSV", "/NH", "/V"],
text=True, errors="replace", timeout=15
)
for line in result.splitlines():
parts = line.strip('"').split('","')
if len(parts) >= 9:
action = parts[8] if len(parts) > 8 else ""
if any(s in action.lower() for s in ["powershell", "cmd", "temp", "appdata"]):
findings.append({
"task_name": parts[1] if len(parts) > 1 else "",
"action": action[:200],
})
except subprocess.SubprocessError:
pass
return findings
def main():
parser = argparse.ArgumentParser(
description="Eradicate malware from infected systems"
)
parser.add_argument("--scan-persistence", action="store_true")
parser.add_argument("--kill-pid", type=int, nargs="*", help="PIDs to terminate")
parser.add_argument("--quarantine-file", nargs="*", help="Files to quarantine")
parser.add_argument("--quarantine-dir", default=os.environ.get("QUARANTINE_DIR", "/tmp/quarantine"))
parser.add_argument("--output", "-o", help="Output JSON report")
args = parser.parse_args()
print("[*] Malware Eradication Agent")
report = {"timestamp": datetime.now(timezone.utc).isoformat(), "actions": []}
if args.kill_pid:
for pid in args.kill_pid:
result = kill_malicious_process(pid)
report["actions"].append({"action": "kill", **result})
print(f"[*] Kill PID {pid}: {result['status']}")
if args.quarantine_file:
for fpath in args.quarantine_file:
result = quarantine_file(fpath, args.quarantine_dir)
report["actions"].append({"action": "quarantine", **result})
print(f"[*] Quarantine {fpath}: {result['status']}")
if args.scan_persistence:
if sys.platform == "win32":
pers = scan_persistence_windows()
tasks = clean_scheduled_tasks()
else:
pers = scan_persistence_linux()
tasks = []
report["persistence"] = pers
report["scheduled_tasks"] = tasks
print(f"[*] Persistence entries: {len(pers)}, Suspicious tasks: {len(tasks)}")
if args.output:
with open(args.output, "w") as f:
json.dump(report, f, indent=2)
print(f"[*] Report saved to {args.output}")
else:
print(json.dumps(report, indent=2))
if __name__ == "__main__":
main()
process.py18.0 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""
Malware Eradication Automation Script
Scans systems for persistence mechanisms, removes identified malware
artifacts, and validates eradication success.
Requirements:
pip install psutil yara-python
"""
import argparse
import csv
import hashlib
import json
import logging
import os
import platform
import subprocess
import sys
from datetime import datetime, timezone
from pathlib import Path
try:
import psutil
except ImportError:
print("Install psutil: pip install psutil")
sys.exit(1)
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
handlers=[
logging.StreamHandler(),
logging.FileHandler(f"eradication_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log"),
],
)
logger = logging.getLogger("malware_eradication")
class PersistenceScanner:
"""Scan for known persistence mechanisms on Windows and Linux."""
def __init__(self):
self.findings = []
self.system = platform.system()
def scan_all(self) -> list:
"""Run all persistence checks."""
if self.system == "Windows":
self._scan_registry_run_keys()
self._scan_scheduled_tasks()
self._scan_services()
self._scan_startup_folders()
self._scan_wmi_subscriptions()
else:
self._scan_crontabs()
self._scan_systemd_services()
self._scan_rc_local()
self._scan_shell_profiles()
self._scan_authorized_keys()
self._scan_ld_preload()
return self.findings
def _scan_registry_run_keys(self):
"""Scan Windows registry Run keys."""
run_keys = [
r"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run",
r"HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run",
r"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce",
r"HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce",
r"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run",
]
for key in run_keys:
try:
result = subprocess.run(
["reg", "query", key], capture_output=True, text=True, timeout=10,
)
if result.returncode == 0 and result.stdout.strip():
for line in result.stdout.strip().split("\n"):
line = line.strip()
if line and "REG_SZ" in line or "REG_EXPAND_SZ" in line:
self.findings.append({
"type": "registry_run_key",
"location": key,
"value": line,
"risk": "medium",
})
except Exception as e:
logger.warning(f"Failed to scan {key}: {e}")
def _scan_scheduled_tasks(self):
"""Scan Windows scheduled tasks."""
try:
result = subprocess.run(
["schtasks", "/query", "/fo", "CSV", "/v"],
capture_output=True, text=True, timeout=30,
)
if result.returncode == 0:
lines = result.stdout.strip().split("\n")
if len(lines) > 1:
reader = csv.DictReader(lines)
for row in reader:
task_name = row.get("TaskName", "")
task_run = row.get("Task To Run", "")
if task_name and task_run and "N/A" not in task_run:
# Flag tasks with suspicious indicators
suspicious = any(kw in task_run.lower() for kw in [
"powershell", "cmd /c", "mshta", "wscript",
"cscript", "certutil", "bitsadmin", "temp",
"appdata", "public",
])
self.findings.append({
"type": "scheduled_task",
"location": task_name,
"value": task_run,
"risk": "high" if suspicious else "low",
})
except Exception as e:
logger.warning(f"Failed to scan scheduled tasks: {e}")
def _scan_services(self):
"""Scan Windows services for suspicious entries."""
try:
for service in psutil.win_service_iter():
try:
info = service.as_dict()
binpath = info.get("binpath", "")
if binpath and not any(
binpath.lower().startswith(p) for p in [
"c:\\windows\\", "c:\\program files\\",
"c:\\program files (x86)\\",
]
):
self.findings.append({
"type": "service",
"location": info.get("name", ""),
"value": binpath,
"risk": "medium",
"status": info.get("status", ""),
})
except Exception:
continue
except Exception as e:
logger.warning(f"Failed to scan services: {e}")
def _scan_startup_folders(self):
"""Scan Windows startup folders."""
startup_paths = [
os.path.expandvars(r"%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup"),
r"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup",
]
for path in startup_paths:
if os.path.exists(path):
for item in os.listdir(path):
full_path = os.path.join(path, item)
if os.path.isfile(full_path) and item != "desktop.ini":
self.findings.append({
"type": "startup_folder",
"location": path,
"value": full_path,
"risk": "medium",
})
def _scan_wmi_subscriptions(self):
"""Scan for WMI event subscriptions (Windows)."""
try:
result = subprocess.run(
["powershell", "-Command",
"Get-WMIObject -Namespace root\\Subscription -Class __EventFilter | Select-Object Name, Query | ConvertTo-Json"],
capture_output=True, text=True, timeout=15,
)
if result.stdout.strip():
filters = json.loads(result.stdout)
if isinstance(filters, dict):
filters = [filters]
for f in filters:
self.findings.append({
"type": "wmi_subscription",
"location": "root\\Subscription\\__EventFilter",
"value": f.get("Name", "") + ": " + f.get("Query", ""),
"risk": "high",
})
except Exception as e:
logger.warning(f"Failed to scan WMI subscriptions: {e}")
def _scan_crontabs(self):
"""Scan Linux crontab entries."""
cron_paths = ["/etc/crontab"]
cron_dirs = ["/etc/cron.d", "/etc/cron.daily", "/etc/cron.hourly",
"/etc/cron.weekly", "/etc/cron.monthly"]
# User crontabs
spool_dir = "/var/spool/cron/crontabs"
if os.path.exists(spool_dir):
for f in os.listdir(spool_dir):
cron_paths.append(os.path.join(spool_dir, f))
for d in cron_dirs:
if os.path.exists(d):
for f in os.listdir(d):
cron_paths.append(os.path.join(d, f))
for path in cron_paths:
if os.path.isfile(path):
try:
with open(path) as f:
for line in f:
line = line.strip()
if line and not line.startswith("#"):
self.findings.append({
"type": "crontab",
"location": path,
"value": line,
"risk": "medium",
})
except PermissionError:
pass
def _scan_systemd_services(self):
"""Scan for custom systemd services."""
service_dirs = ["/etc/systemd/system", "/usr/lib/systemd/system"]
for sdir in service_dirs:
if os.path.exists(sdir):
for f in os.listdir(sdir):
if f.endswith(".service"):
fpath = os.path.join(sdir, f)
try:
with open(fpath) as sf:
content = sf.read()
if "ExecStart" in content:
self.findings.append({
"type": "systemd_service",
"location": fpath,
"value": f,
"risk": "low",
})
except PermissionError:
pass
def _scan_rc_local(self):
"""Scan /etc/rc.local."""
if os.path.exists("/etc/rc.local"):
try:
with open("/etc/rc.local") as f:
for line in f:
line = line.strip()
if line and not line.startswith("#") and line != "exit 0":
self.findings.append({
"type": "rc_local",
"location": "/etc/rc.local",
"value": line,
"risk": "high",
})
except PermissionError:
pass
def _scan_shell_profiles(self):
"""Scan shell profile files for suspicious entries."""
profile_files = [
os.path.expanduser("~/.bashrc"),
os.path.expanduser("~/.profile"),
os.path.expanduser("~/.bash_profile"),
"/etc/profile",
]
suspicious_commands = ["curl", "wget", "nc ", "ncat", "python -c", "perl -e",
"base64", "eval", "/dev/tcp"]
for pf in profile_files:
if os.path.exists(pf):
try:
with open(pf) as f:
for line in f:
line = line.strip()
if any(cmd in line.lower() for cmd in suspicious_commands):
self.findings.append({
"type": "shell_profile",
"location": pf,
"value": line,
"risk": "high",
})
except PermissionError:
pass
def _scan_authorized_keys(self):
"""Scan for unauthorized SSH keys."""
home_dirs = ["/root"] + [
os.path.join("/home", d) for d in os.listdir("/home")
if os.path.isdir(os.path.join("/home", d))
] if os.path.exists("/home") else ["/root"]
for hd in home_dirs:
ak_path = os.path.join(hd, ".ssh", "authorized_keys")
if os.path.exists(ak_path):
try:
with open(ak_path) as f:
for line in f:
line = line.strip()
if line and not line.startswith("#"):
self.findings.append({
"type": "authorized_keys",
"location": ak_path,
"value": line[:100] + "..." if len(line) > 100 else line,
"risk": "medium",
})
except PermissionError:
pass
def _scan_ld_preload(self):
"""Scan for LD_PRELOAD hijacking."""
if os.path.exists("/etc/ld.so.preload"):
try:
with open("/etc/ld.so.preload") as f:
content = f.read().strip()
if content:
self.findings.append({
"type": "ld_preload",
"location": "/etc/ld.so.preload",
"value": content,
"risk": "critical",
})
except PermissionError:
pass
class MalwareRemover:
"""Remove identified malware artifacts."""
def __init__(self, dry_run: bool = True):
self.dry_run = dry_run
self.removal_log = []
def remove_file(self, filepath: str) -> bool:
if self.dry_run:
logger.info(f"[DRY RUN] Would remove file: {filepath}")
self.removal_log.append({"action": "remove_file", "target": filepath, "status": "dry_run"})
return True
try:
if os.path.exists(filepath):
file_hash = hashlib.sha256(open(filepath, "rb").read()).hexdigest()
os.remove(filepath)
self.removal_log.append({
"action": "remove_file", "target": filepath,
"status": "removed", "sha256": file_hash,
})
logger.info(f"Removed file: {filepath} (SHA256: {file_hash})")
return True
except Exception as e:
self.removal_log.append({"action": "remove_file", "target": filepath, "status": f"failed: {e}"})
logger.error(f"Failed to remove {filepath}: {e}")
return False
def remove_scheduled_task(self, task_name: str) -> bool:
if self.dry_run:
logger.info(f"[DRY RUN] Would remove scheduled task: {task_name}")
self.removal_log.append({"action": "remove_task", "target": task_name, "status": "dry_run"})
return True
try:
result = subprocess.run(
["schtasks", "/delete", "/tn", task_name, "/f"],
capture_output=True, text=True, timeout=10,
)
status = "removed" if result.returncode == 0 else f"failed: {result.stderr}"
self.removal_log.append({"action": "remove_task", "target": task_name, "status": status})
return result.returncode == 0
except Exception as e:
self.removal_log.append({"action": "remove_task", "target": task_name, "status": f"failed: {e}"})
return False
def remove_registry_value(self, key: str, value_name: str) -> bool:
if self.dry_run:
logger.info(f"[DRY RUN] Would remove registry: {key}\\{value_name}")
self.removal_log.append({"action": "remove_reg", "target": f"{key}\\{value_name}", "status": "dry_run"})
return True
try:
result = subprocess.run(
["reg", "delete", key, "/v", value_name, "/f"],
capture_output=True, text=True, timeout=10,
)
status = "removed" if result.returncode == 0 else f"failed: {result.stderr}"
self.removal_log.append({"action": "remove_reg", "target": f"{key}\\{value_name}", "status": status})
return result.returncode == 0
except Exception as e:
self.removal_log.append({"action": "remove_reg", "target": f"{key}\\{value_name}", "status": f"failed: {e}"})
return False
def generate_report(findings: list, removal_log: list, output_path: str):
"""Generate eradication report."""
report = {
"timestamp": datetime.now(timezone.utc).isoformat(),
"hostname": platform.node(),
"platform": platform.platform(),
"persistence_findings": {
"total": len(findings),
"by_risk": {},
"by_type": {},
"details": findings,
},
"eradication_actions": removal_log,
}
for f in findings:
risk = f.get("risk", "unknown")
ftype = f.get("type", "unknown")
report["persistence_findings"]["by_risk"][risk] = report["persistence_findings"]["by_risk"].get(risk, 0) + 1
report["persistence_findings"]["by_type"][ftype] = report["persistence_findings"]["by_type"].get(ftype, 0) + 1
with open(output_path, "w") as fp:
json.dump(report, fp, indent=2)
logger.info(f"Report saved to: {output_path}")
return report
def main():
parser = argparse.ArgumentParser(description="Malware Eradication Tool")
parser.add_argument("--scan", action="store_true", help="Scan for persistence mechanisms")
parser.add_argument("--remove-files", nargs="*", help="Files to remove")
parser.add_argument("--remove-tasks", nargs="*", help="Scheduled tasks to remove")
parser.add_argument("--dry-run", action="store_true", default=True, help="Simulate removal (default)")
parser.add_argument("--execute", action="store_true", help="Actually perform removal (CAUTION)")
parser.add_argument("--output", default="./eradication_report.json", help="Report output path")
args = parser.parse_args()
dry_run = not args.execute
findings = []
if args.scan:
scanner = PersistenceScanner()
findings = scanner.scan_all()
logger.info(f"Found {len(findings)} persistence items")
for f in findings:
risk_label = f"[{f['risk'].upper()}]"
logger.info(f" {risk_label} {f['type']}: {f['location']} -> {f['value'][:80]}")
remover = MalwareRemover(dry_run=dry_run)
if args.remove_files:
for fp in args.remove_files:
remover.remove_file(fp)
if args.remove_tasks:
for task in args.remove_tasks:
remover.remove_scheduled_task(task)
generate_report(findings, remover.removal_log, args.output)
if __name__ == "__main__":
main()
Assets 1
template.mdtext/markdown · 1.8 KBKeep exploring