mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-11 05:34:55 +03:00
c47eed6a64
- Fix 25 shell=True subprocess calls with list-based commands - Fix 49 verify=False in defensive skills (env-var override) - Add timeout to 231 HTTP/subprocess/socket calls - Fix 6 SQL injection patterns with whitelist validation - Replace 8 __import__() with standard imports - Remove 701 unused imports across 442 files - Add authorized-testing disclaimers to all offensive skills - Complete 11 incomplete skill directories - Expand 10 stub SKILL.md files with full content - Fix 2 YAML parse errors in frontmatter - Fix 5 pre-existing syntax errors - Convert 22 hardcoded paths/ports to environment variables - Back up 21 redundant skill pairs to .bak - Fix 2 global declaration errors - 724/724 skills with full folder anatomy (SKILL.md + agent.py + api-reference.md + LICENSE) - 0 compile errors across all 724 agent.py files
226 lines
9.1 KiB
Python
226 lines
9.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Agent for performing ransomware response.
|
|
|
|
Automates ransomware identification, impact assessment, backup
|
|
verification, IOC extraction, and recovery tracking during
|
|
ransomware incident response.
|
|
"""
|
|
|
|
import json
|
|
import sys
|
|
import hashlib
|
|
from pathlib import Path
|
|
from datetime import datetime
|
|
|
|
|
|
class RansomwareResponseAgent:
|
|
"""Assists with structured ransomware incident response."""
|
|
|
|
def __init__(self, case_id, output_dir):
|
|
self.case_id = case_id
|
|
self.output_dir = Path(output_dir)
|
|
self.output_dir.mkdir(parents=True, exist_ok=True)
|
|
self.incident = {
|
|
"case_id": case_id,
|
|
"status": "active",
|
|
"timeline": [],
|
|
}
|
|
|
|
def log_event(self, event_type, description, details=None):
|
|
"""Add a timestamped event to the incident timeline."""
|
|
event = {
|
|
"timestamp": datetime.utcnow().isoformat(),
|
|
"type": event_type,
|
|
"description": description,
|
|
}
|
|
if details:
|
|
event["details"] = details
|
|
self.incident["timeline"].append(event)
|
|
|
|
def identify_ransomware(self, ransom_note_path=None, encrypted_file_path=None,
|
|
extension=None):
|
|
"""Identify ransomware variant from note, file, or extension."""
|
|
identification = {
|
|
"method": "manual",
|
|
"extension": extension,
|
|
}
|
|
|
|
if ransom_note_path and Path(ransom_note_path).exists():
|
|
note_content = Path(ransom_note_path).read_text(errors="ignore")
|
|
identification["ransom_note"] = note_content[:2000]
|
|
|
|
known_patterns = {
|
|
"LockBit": ["lockbit", "LOCKBIT", "restore-my-files"],
|
|
"BlackCat/ALPHV": ["ALPHV", "BlackCat", "RECOVER-"],
|
|
"Royal": ["Royal", "royal_w"],
|
|
"Akira": ["akira", ".akira"],
|
|
"Play": [".play", "PLAY"],
|
|
"Cl0p": ["CL0P", "clop"],
|
|
"Rhysida": ["rhysida", "RHYSIDA"],
|
|
}
|
|
for family, patterns in known_patterns.items():
|
|
for pattern in patterns:
|
|
if pattern in note_content:
|
|
identification["family"] = family
|
|
break
|
|
|
|
if encrypted_file_path and Path(encrypted_file_path).exists():
|
|
file_hash = hashlib.sha256(
|
|
Path(encrypted_file_path).read_bytes()
|
|
).hexdigest()
|
|
identification["encrypted_sample_hash"] = file_hash
|
|
|
|
self.incident["identification"] = identification
|
|
self.log_event("identification", f"Ransomware identified: {identification.get('family', 'Unknown')}")
|
|
return identification
|
|
|
|
def check_decryptor_availability(self, family):
|
|
"""Check NoMoreRansom and known sources for free decryptors."""
|
|
known_decryptors = {
|
|
"GandCrab": "https://www.nomoreransom.org/en/decryption-tools.html",
|
|
"REvil": "https://www.nomoreransom.org/en/decryption-tools.html",
|
|
"Maze": "https://www.nomoreransom.org/en/decryption-tools.html",
|
|
"Shade": "https://www.nomoreransom.org/en/decryption-tools.html",
|
|
"Jigsaw": "https://www.nomoreransom.org/en/decryption-tools.html",
|
|
}
|
|
has_decryptor = family in known_decryptors
|
|
return {
|
|
"family": family,
|
|
"decryptor_available": has_decryptor,
|
|
"source": known_decryptors.get(family, "None known"),
|
|
"nomoreransom_url": "https://www.nomoreransom.org/en/decryption-tools.html",
|
|
"id_ransomware_url": "https://id-ransomware.malwarehunterteam.com/",
|
|
}
|
|
|
|
def assess_impact(self, encrypted_hosts=0, total_hosts=0,
|
|
encrypted_servers=0, total_servers=0,
|
|
dc_affected=0, total_dcs=0,
|
|
data_exfiltrated_gb=0, ransom_amount="",
|
|
backup_status="unknown"):
|
|
"""Assess the scope and impact of the ransomware incident."""
|
|
assessment = {
|
|
"encrypted_hosts": encrypted_hosts,
|
|
"total_hosts": total_hosts,
|
|
"host_impact_pct": round(encrypted_hosts / max(total_hosts, 1) * 100, 1),
|
|
"encrypted_servers": encrypted_servers,
|
|
"total_servers": total_servers,
|
|
"dc_affected": dc_affected,
|
|
"total_dcs": total_dcs,
|
|
"data_exfiltrated_gb": data_exfiltrated_gb,
|
|
"double_extortion": data_exfiltrated_gb > 0,
|
|
"ransom_amount": ransom_amount,
|
|
"backup_status": backup_status,
|
|
}
|
|
|
|
if backup_status == "clean":
|
|
assessment["recommended_recovery"] = "Restore from backup"
|
|
elif backup_status == "compromised":
|
|
assessment["recommended_recovery"] = "Rebuild from scratch"
|
|
else:
|
|
assessment["recommended_recovery"] = "Verify backup integrity first"
|
|
|
|
self.incident["impact_assessment"] = assessment
|
|
self.log_event("impact_assessment", f"{encrypted_hosts}/{total_hosts} hosts encrypted")
|
|
return assessment
|
|
|
|
def generate_containment_checklist(self):
|
|
"""Generate prioritized containment checklist."""
|
|
checklist = [
|
|
{"priority": 1, "action": "Disconnect affected network segments from core infrastructure",
|
|
"status": "pending", "note": "Pull network cable, do NOT power off"},
|
|
{"priority": 2, "action": "Isolate all domain controllers immediately",
|
|
"status": "pending", "note": "If GPO-based deployment suspected"},
|
|
{"priority": 3, "action": "Disable compromised accounts used for deployment",
|
|
"status": "pending"},
|
|
{"priority": 4, "action": "Block lateral movement protocols (SMB 445, RDP 3389, WinRM 5985-5986)",
|
|
"status": "pending"},
|
|
{"priority": 5, "action": "Preserve at least one encrypted system powered on for memory forensics",
|
|
"status": "pending", "note": "Encryption keys may be in memory"},
|
|
{"priority": 6, "action": "Verify offline backup integrity",
|
|
"status": "pending"},
|
|
{"priority": 7, "action": "Engage incident response retainer and cyber insurance",
|
|
"status": "pending"},
|
|
{"priority": 8, "action": "Notify legal counsel for OFAC screening and regulatory assessment",
|
|
"status": "pending"},
|
|
]
|
|
self.incident["containment_checklist"] = checklist
|
|
return checklist
|
|
|
|
def generate_recovery_plan(self):
|
|
"""Generate recovery plan based on impact assessment."""
|
|
assessment = self.incident.get("impact_assessment", {})
|
|
backup_status = assessment.get("backup_status", "unknown")
|
|
|
|
steps = []
|
|
if backup_status == "clean":
|
|
steps = [
|
|
"Build clean isolated network segment for recovery",
|
|
"Rebuild domain controllers from clean media",
|
|
"Reset ALL user and service account passwords",
|
|
"Restore servers in priority: auth > DNS > DHCP > business apps",
|
|
"Reimage workstations (do not file-level restore)",
|
|
"Restore data from verified clean backups",
|
|
"Validate and reconnect to production network",
|
|
]
|
|
else:
|
|
steps = [
|
|
"Verify backup integrity before proceeding",
|
|
"If no clean backups, evaluate rebuild from scratch",
|
|
"Check NoMoreRansom.org for available decryptors",
|
|
"Consult with IR retainer on recovery options",
|
|
]
|
|
|
|
plan = {
|
|
"strategy": assessment.get("recommended_recovery", "TBD"),
|
|
"steps": steps,
|
|
"post_recovery_hardening": [
|
|
"Enforce MFA on all remote access",
|
|
"Implement 3-2-1-1-0 backup strategy",
|
|
"Deploy application whitelisting on servers",
|
|
"Implement network segmentation",
|
|
"Deploy LAPS for local admin passwords",
|
|
"Disable NTLM where possible",
|
|
],
|
|
}
|
|
self.incident["recovery_plan"] = plan
|
|
return plan
|
|
|
|
def generate_report(self):
|
|
"""Generate comprehensive ransomware incident report."""
|
|
self.generate_containment_checklist()
|
|
self.generate_recovery_plan()
|
|
|
|
report = self.incident.copy()
|
|
report["report_date"] = datetime.utcnow().isoformat()
|
|
|
|
report_path = self.output_dir / f"{self.case_id}_ransomware_report.json"
|
|
with open(report_path, "w") as f:
|
|
json.dump(report, f, indent=2)
|
|
|
|
print(json.dumps(report, indent=2))
|
|
return report
|
|
|
|
|
|
def main():
|
|
if len(sys.argv) < 2:
|
|
print("Usage: agent.py <case_id> [output_dir] [ransom_note_path]")
|
|
sys.exit(1)
|
|
|
|
case_id = sys.argv[1]
|
|
output_dir = sys.argv[2] if len(sys.argv) > 2 else "./ransomware_response"
|
|
|
|
agent = RansomwareResponseAgent(case_id, output_dir)
|
|
|
|
if len(sys.argv) > 3:
|
|
agent.identify_ransomware(ransom_note_path=sys.argv[3])
|
|
|
|
agent.assess_impact(
|
|
encrypted_hosts=0, total_hosts=0,
|
|
backup_status="unknown"
|
|
)
|
|
agent.generate_report()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|