Files
mukul975 c47eed6a64 Production hardening: security fixes, code quality, 724 skills complete
- 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
2026-03-19 13:26:49 +01:00

198 lines
6.7 KiB
Python

#!/usr/bin/env python3
"""Ransomware leak site intelligence analysis agent.
Monitors and analyzes ransomware group leak site data for threat intelligence,
victim tracking, and TTI (time-to-intelligence) reporting.
"""
import sys
import json
from datetime import datetime, timedelta
from collections import defaultdict, Counter
try:
import requests
HAS_REQUESTS = True
except ImportError:
HAS_REQUESTS = False
RANSOMWARE_GROUPS = {
"lockbit": {"aliases": ["LockBit 3.0", "LockBit Black"], "status": "active"},
"alphv": {"aliases": ["BlackCat", "ALPHV"], "status": "disrupted"},
"cl0p": {"aliases": ["Clop", "TA505"], "status": "active"},
"play": {"aliases": ["PlayCrypt"], "status": "active"},
"8base": {"aliases": ["8Base"], "status": "active"},
"akira": {"aliases": ["Akira"], "status": "active"},
"bianlian": {"aliases": ["BianLian"], "status": "active"},
"blackbasta": {"aliases": ["Black Basta"], "status": "active"},
"medusa": {"aliases": ["MedusaLocker", "Medusa Blog"], "status": "active"},
"rhysida": {"aliases": ["Rhysida"], "status": "active"},
"royal": {"aliases": ["Royal", "BlackSuit"], "status": "rebranded"},
"ransomhub": {"aliases": ["RansomHub"], "status": "active"},
}
def query_ransomwatch_api():
"""Query ransomwatch or ransomware.live API for leak site data."""
if not HAS_REQUESTS:
return []
try:
resp = requests.get("https://api.ransomware.live/recentvictims",
timeout=30)
resp.raise_for_status()
return resp.json()
except requests.RequestException as e:
return [{"error": str(e)}]
def query_ransomlook_group(group_name):
"""Query ransomlook.io API for group information."""
if not HAS_REQUESTS:
return {}
try:
resp = requests.get(f"https://www.ransomlook.io/api/group/{group_name}",
timeout=30)
resp.raise_for_status()
return resp.json()
except requests.RequestException:
return {}
def analyze_victim_data(victims):
"""Analyze victim listing data for intelligence."""
sector_counts = Counter()
country_counts = Counter()
group_counts = Counter()
timeline = defaultdict(int)
for v in victims:
group = v.get("group_name", v.get("group", "unknown")).lower()
group_counts[group] += 1
sector = v.get("activity", v.get("sector", "unknown"))
if sector:
sector_counts[sector] += 1
country = v.get("country", "unknown")
if country:
country_counts[country] += 1
date_str = v.get("discovered", v.get("published", ""))
if date_str:
try:
dt = datetime.fromisoformat(date_str.replace("Z", "+00:00"))
timeline[dt.strftime("%Y-%m")] += 1
except (ValueError, TypeError):
pass
return {
"total_victims": len(victims),
"top_groups": dict(group_counts.most_common(10)),
"top_sectors": dict(sector_counts.most_common(10)),
"top_countries": dict(country_counts.most_common(10)),
"monthly_trend": dict(sorted(timeline.items())),
}
def search_victims(victims, query):
"""Search victims by name, domain, or sector."""
results = []
query_lower = query.lower()
for v in victims:
name = (v.get("victim", v.get("post_title", "")) or "").lower()
website = (v.get("website", "") or "").lower()
sector = (v.get("activity", v.get("sector", "")) or "").lower()
if query_lower in name or query_lower in website or query_lower in sector:
results.append(v)
return results
def assess_group_activity(victims, group_name, days=90):
"""Assess activity level of a specific ransomware group."""
cutoff = datetime.now() - timedelta(days=days)
group_victims = []
for v in victims:
g = (v.get("group_name", v.get("group", "")) or "").lower()
if group_name.lower() in g:
group_victims.append(v)
recent = []
for v in group_victims:
date_str = v.get("discovered", v.get("published", ""))
if date_str:
try:
dt = datetime.fromisoformat(date_str.replace("Z", "+00:00"))
if dt.replace(tzinfo=None) > cutoff:
recent.append(v)
except (ValueError, TypeError):
pass
info = RANSOMWARE_GROUPS.get(group_name.lower(), {})
return {
"group": group_name,
"aliases": info.get("aliases", []),
"status": info.get("status", "unknown"),
"total_victims": len(group_victims),
"recent_victims": len(recent),
"period_days": days,
"activity_level": "HIGH" if len(recent) > 20 else "MEDIUM" if len(recent) > 5 else "LOW",
}
def generate_intelligence_report(victims, target_org=None):
"""Generate ransomware threat intelligence report."""
analysis = analyze_victim_data(victims)
report = {
"report_date": datetime.now().isoformat(),
"data_source": "ransomware.live API",
"analysis": analysis,
}
if target_org:
matches = search_victims(victims, target_org)
report["org_search"] = {
"query": target_org,
"matches": len(matches),
"results": matches[:10],
}
return report
if __name__ == "__main__":
print("=" * 60)
print("Ransomware Leak Site Intelligence Agent")
print("Victim tracking, group analysis, sector trends")
print("=" * 60)
query = sys.argv[1] if len(sys.argv) > 1 else None
if not HAS_REQUESTS:
print("[!] Install requests: pip install requests")
sys.exit(1)
print("\n[*] Fetching recent ransomware victims...")
victims = query_ransomwatch_api()
if not victims or (len(victims) == 1 and "error" in victims[0]):
print(f"[!] API error: {victims}")
sys.exit(1)
print(f"[*] Retrieved {len(victims)} victim entries")
report = generate_intelligence_report(victims, target_org=query)
analysis = report["analysis"]
print(f"\n--- Top Groups ---")
for g, c in list(analysis["top_groups"].items())[:5]:
print(f" {g:20s} {c} victims")
print(f"\n--- Top Sectors ---")
for s, c in list(analysis["top_sectors"].items())[:5]:
print(f" {s:30s} {c}")
print(f"\n--- Top Countries ---")
for co, c in list(analysis["top_countries"].items())[:5]:
print(f" {co:20s} {c}")
if query:
matches = report.get("org_search", {})
print(f"\n--- Search: '{query}' ({matches.get('matches', 0)} results) ---")
for m in matches.get("results", [])[:5]:
print(f" {m.get('group_name', '?'):15s} | {m.get('victim', m.get('post_title', '?'))}")
print(f"\n{json.dumps(report, indent=2, default=str)}")