#!/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 [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()