#!/usr/bin/env python3 """Ransomware kill switch detection and mutex vaccination agent. Detects ransomware kill switch mechanisms (mutexes, domains, registry keys) and can proactively deploy mutex vaccinations to prevent known ransomware families from executing. Monitors for kill switch domain DNS queries. """ import json import logging import platform import socket import subprocess import sys from datetime import datetime logging.basicConfig( level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s", ) logger = logging.getLogger("killswitch_agent") KNOWN_KILL_SWITCH_MUTEXES = { "Global\\MsWinZonesCacheCounterMutexA": { "family": "WannaCry", "type": "instance_guard", "notes": "Prevents multiple WannaCry instances from running", }, "Global\\kasKDJSAFJauisiudUASIIQWUA82": { "family": "Conti", "type": "instance_guard", "notes": "Conti ransomware single-instance mutex", }, "Global\\YOURPRODUCT_MUTEX": { "family": "Ryuk variant", "type": "instance_guard", "notes": "Ryuk variant instance check", }, "Global\\JhbGjhBsSQjz": { "family": "Maze", "type": "instance_guard", "notes": "Maze ransomware single-instance mutex", }, "Global\\{A7FE5338-4DDE-8CDE-9F54-FE88C3B8B532}": { "family": "LockBit", "type": "instance_guard", "notes": "LockBit variant mutex (GUID-based)", }, "Global\\MsWinZonesCacheCounterMutexA0": { "family": "WannaCry variant", "type": "instance_guard", "notes": "WannaCry variant with appended zero", }, "Global\\55a42b46-43dc-4e6c-abef-2529ddd744c7": { "family": "BlackCat/ALPHV", "type": "instance_guard", "notes": "ALPHV ransomware instance mutex", }, "Global\\sdjfhksjdhfsd": { "family": "Generic ransomware", "type": "instance_guard", "notes": "Common in several ransomware builders", }, } KNOWN_KILL_SWITCH_DOMAINS = { "iuqerfsodp9ifjaposdfjhgosurijfaewrwergwea.com": { "family": "WannaCry v1", "type": "domain_kill_switch", "notes": "Primary WannaCry kill switch domain registered by MalwareTech", }, "fferfsodp9ifjaposdfjhgosurijfaewrwergwea.com": { "family": "WannaCry v1 (alternate)", "type": "domain_kill_switch", "notes": "Secondary WannaCry kill switch domain", }, "ayloginilider.com": { "family": "Emotet (ransomware loader)", "type": "c2_sinkhole", "notes": "Emotet C2 domain sinkholed by law enforcement", }, } KNOWN_KILL_SWITCH_REGISTRY = { "HKLM\\SOFTWARE\\WannaDecrypt0r": { "family": "WannaCry", "type": "registry_marker", "key": "HKLM\\SOFTWARE\\WannaDecrypt0r", }, } def check_mutex_exists_windows(mutex_name): """Check if a named mutex exists on Windows using PowerShell.""" ps_script = ( f'try {{ $m = [System.Threading.Mutex]::OpenExisting("{mutex_name}"); ' f'"EXISTS" }} catch {{ "NOT_FOUND" }}' ) try: result = subprocess.run( ["powershell", "-Command", ps_script], capture_output=True, text=True, timeout=10, ) return result.stdout.strip() == "EXISTS" except (FileNotFoundError, subprocess.TimeoutExpired): return None def create_mutex_windows(mutex_name): """Create a named mutex on Windows for vaccination.""" ps_script = ( f'$created = $false; ' f'$m = New-Object System.Threading.Mutex($true, "{mutex_name}", [ref]$created); ' f'if ($created) {{ "CREATED" }} else {{ "ALREADY_EXISTS" }}; ' f'Start-Sleep -Seconds 2' ) try: result = subprocess.run( ["powershell", "-Command", ps_script], capture_output=True, text=True, timeout=15, ) output = result.stdout.strip() return output == "CREATED" or output == "ALREADY_EXISTS", output except (FileNotFoundError, subprocess.TimeoutExpired) as e: return False, str(e) def check_kill_switch_domain(domain): """Check if a kill switch domain resolves (indicating it is active).""" try: ip = socket.gethostbyname(domain) return { "domain": domain, "resolves": True, "ip": ip, "kill_switch_active": True, "notes": "Domain resolves - kill switch is ACTIVE (ransomware should abort)", } except socket.gaierror: return { "domain": domain, "resolves": False, "ip": None, "kill_switch_active": False, "notes": "Domain does NOT resolve - kill switch INACTIVE (ransomware would proceed)", } def scan_all_kill_switches(): """Scan for all known kill switch mechanisms.""" report = { "scan_time": datetime.now().isoformat(), "hostname": platform.node(), "platform": platform.system(), "mutex_checks": [], "domain_checks": [], "registry_checks": [], "summary": {"total_checked": 0, "active_vaccinations": 0, "active_domains": 0}, } # Check mutexes (Windows only) if platform.system() == "Windows": logger.info("Checking %d known ransomware mutexes...", len(KNOWN_KILL_SWITCH_MUTEXES)) for mutex_name, info in KNOWN_KILL_SWITCH_MUTEXES.items(): exists = check_mutex_exists_windows(mutex_name) check = { "mutex": mutex_name, "family": info["family"], "exists": exists, "vaccinated": exists is True, } report["mutex_checks"].append(check) report["summary"]["total_checked"] += 1 if exists: report["summary"]["active_vaccinations"] += 1 logger.warning("Mutex EXISTS: %s (%s)", mutex_name, info["family"]) else: logger.info("Mutex checking is Windows-only. Skipping on %s.", platform.system()) # Check kill switch domains logger.info("Checking %d known kill switch domains...", len(KNOWN_KILL_SWITCH_DOMAINS)) for domain, info in KNOWN_KILL_SWITCH_DOMAINS.items(): result = check_kill_switch_domain(domain) result["family"] = info["family"] report["domain_checks"].append(result) report["summary"]["total_checked"] += 1 if result["resolves"]: report["summary"]["active_domains"] += 1 return report def vaccinate_endpoint(mutex_list=None): """Deploy mutex vaccinations to prevent ransomware execution.""" if platform.system() != "Windows": return {"error": "Mutex vaccination is only supported on Windows"} if mutex_list is None: mutex_list = list(KNOWN_KILL_SWITCH_MUTEXES.keys()) results = {"vaccinated": [], "failed": [], "already_exists": []} for mutex_name in mutex_list: info = KNOWN_KILL_SWITCH_MUTEXES.get(mutex_name, {"family": "Custom"}) success, status = create_mutex_windows(mutex_name) record = {"mutex": mutex_name, "family": info.get("family", "Custom"), "status": status} if status == "CREATED": results["vaccinated"].append(record) logger.info("Vaccinated: %s (%s)", mutex_name, info.get("family")) elif status == "ALREADY_EXISTS": results["already_exists"].append(record) logger.info("Already vaccinated: %s", mutex_name) else: results["failed"].append(record) logger.error("Failed to vaccinate: %s - %s", mutex_name, status) results["summary"] = { "total_attempted": len(mutex_list), "newly_vaccinated": len(results["vaccinated"]), "already_vaccinated": len(results["already_exists"]), "failed": len(results["failed"]), } return results def generate_vaccination_script(): """Generate a PowerShell script for persistent mutex vaccination.""" lines = [ "# Ransomware Mutex Vaccination Script", "# Deploy via Group Policy Startup Script or Scheduled Task", f"# Generated: {datetime.now().isoformat()}", "# This script creates named mutexes that prevent known ransomware from executing", "", "$mutexHandles = @()", "", ] for mutex_name, info in KNOWN_KILL_SWITCH_MUTEXES.items(): lines.append(f"# {info['family']} - {info['notes']}") lines.append(f'$created = $false') lines.append(f'$m = New-Object System.Threading.Mutex($true, "{mutex_name}", [ref]$created)') lines.append(f'if ($created) {{ Write-Host "Vaccinated: {mutex_name}" }}') lines.append(f'$mutexHandles += $m') lines.append("") lines.append("# Keep script running to maintain mutex handles") lines.append("Write-Host 'Mutex vaccination active. Press Ctrl+C to stop.'") lines.append("while ($true) { Start-Sleep -Seconds 60 }") return "\n".join(lines) if __name__ == "__main__": print("=" * 60) print("Ransomware Kill Switch Detection & Vaccination Agent") print("Mutex vaccination, domain monitoring, kill switch analysis") print("=" * 60) if len(sys.argv) < 2: print("\nUsage:") print(" python agent.py scan Scan for all known kill switches") print(" python agent.py vaccinate Deploy mutex vaccinations") print(" python agent.py domains Check kill switch domain status") print(" python agent.py generate-script Generate PowerShell vaccination script") print(" python agent.py list List all known kill switches") sys.exit(0) command = sys.argv[1] if command == "scan": report = scan_all_kill_switches() print(f"\n--- Kill Switch Scan Results ---") print(f" Total checked: {report['summary']['total_checked']}") print(f" Active mutex vaccinations: {report['summary']['active_vaccinations']}") print(f" Active kill switch domains: {report['summary']['active_domains']}") for mc in report["mutex_checks"]: status = "VACCINATED" if mc["vaccinated"] else "not vaccinated" print(f" [{status:15s}] {mc['family']:20s} {mc['mutex']}") for dc in report["domain_checks"]: status = "ACTIVE" if dc["resolves"] else "INACTIVE" print(f" [{status:15s}] {dc['family']:20s} {dc['domain']}") print(f"\n{json.dumps(report, indent=2, default=str)}") elif command == "vaccinate": print("\n[*] Deploying mutex vaccinations...") results = vaccinate_endpoint() print(f"\n--- Vaccination Results ---") print(f" Newly vaccinated: {results['summary']['newly_vaccinated']}") print(f" Already vaccinated: {results['summary']['already_vaccinated']}") print(f" Failed: {results['summary']['failed']}") elif command == "domains": print("\n--- Kill Switch Domain Status ---") for domain, info in KNOWN_KILL_SWITCH_DOMAINS.items(): result = check_kill_switch_domain(domain) status = "ACTIVE (resolves)" if result["resolves"] else "INACTIVE (no DNS)" print(f" [{status}] {info['family']}: {domain}") if result["resolves"]: print(f" Resolves to: {result['ip']}") elif command == "generate-script": script = generate_vaccination_script() output_file = "mutex_vaccination.ps1" with open(output_file, "w") as f: f.write(script) print(f"\n[+] Vaccination script saved to: {output_file}") print(f"[+] Deploy via GPO startup script or scheduled task") print(f"\n{script[:500]}...") elif command == "list": print(f"\n--- Known Ransomware Kill Switches ---") print(f"\nMutexes ({len(KNOWN_KILL_SWITCH_MUTEXES)}):") for name, info in KNOWN_KILL_SWITCH_MUTEXES.items(): print(f" {info['family']:20s} {name}") print(f"\nDomains ({len(KNOWN_KILL_SWITCH_DOMAINS)}):") for domain, info in KNOWN_KILL_SWITCH_DOMAINS.items(): print(f" {info['family']:20s} {domain}") else: print(f"[!] Unknown command: {command}")