mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-19 14:09:40 +03:00
Add folder anatomy (scripts/agent.py + references/api-reference.md) for 648 cybersecurity skills
Complete skill folder anatomy across all cybersecurity skills: - scripts/agent.py: 80-150 line Python agents using real libraries (impacket, boto3, azure-mgmt-*, kubernetes, pefile, yara, scapy, shodan, stix2, etc.) - references/api-reference.md: real API documentation with method signatures - LICENSE: MIT license for all skill folders
This commit is contained in:
@@ -0,0 +1,255 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Cuckoo Sandbox behavioral analysis agent for automated malware detonation and reporting."""
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import hashlib
|
||||
import datetime
|
||||
|
||||
try:
|
||||
import requests
|
||||
HAS_REQUESTS = True
|
||||
except ImportError:
|
||||
HAS_REQUESTS = False
|
||||
|
||||
|
||||
CUCKOO_API = os.environ.get("CUCKOO_API", "http://localhost:8090")
|
||||
CUCKOO_STORAGE = os.environ.get("CUCKOO_STORAGE", "/opt/cuckoo/storage/analyses")
|
||||
|
||||
|
||||
def submit_file(filepath, timeout=300, machine=None, package=None):
|
||||
"""Submit a malware sample to Cuckoo via REST API."""
|
||||
if not HAS_REQUESTS:
|
||||
return None
|
||||
url = f"{CUCKOO_API}/tasks/create/file"
|
||||
files = {"file": (os.path.basename(filepath), open(filepath, "rb"))}
|
||||
data = {"timeout": timeout}
|
||||
if machine:
|
||||
data["machine"] = machine
|
||||
if package:
|
||||
data["package"] = package
|
||||
resp = requests.post(url, files=files, data=data)
|
||||
if resp.status_code == 200:
|
||||
return resp.json().get("task_id")
|
||||
return None
|
||||
|
||||
|
||||
def submit_url(url_to_analyze, timeout=300):
|
||||
"""Submit a URL to Cuckoo for analysis."""
|
||||
if not HAS_REQUESTS:
|
||||
return None
|
||||
url = f"{CUCKOO_API}/tasks/create/url"
|
||||
data = {"url": url_to_analyze, "timeout": timeout}
|
||||
resp = requests.post(url, data=data)
|
||||
if resp.status_code == 200:
|
||||
return resp.json().get("task_id")
|
||||
return None
|
||||
|
||||
|
||||
def get_task_status(task_id):
|
||||
"""Check the status of a Cuckoo analysis task."""
|
||||
if not HAS_REQUESTS:
|
||||
return None
|
||||
url = f"{CUCKOO_API}/tasks/view/{task_id}"
|
||||
resp = requests.get(url)
|
||||
if resp.status_code == 200:
|
||||
return resp.json().get("task", {}).get("status")
|
||||
return None
|
||||
|
||||
|
||||
def load_report(task_id, report_dir=None):
|
||||
"""Load a Cuckoo JSON report from disk."""
|
||||
if report_dir is None:
|
||||
report_dir = CUCKOO_STORAGE
|
||||
report_path = os.path.join(report_dir, str(task_id), "reports", "report.json")
|
||||
if os.path.exists(report_path):
|
||||
with open(report_path, "r") as f:
|
||||
return json.load(f)
|
||||
return None
|
||||
|
||||
|
||||
def analyze_processes(report):
|
||||
"""Extract and analyze the process tree from the Cuckoo report."""
|
||||
processes = []
|
||||
for proc in report.get("behavior", {}).get("processes", []):
|
||||
pid = proc.get("pid")
|
||||
ppid = proc.get("ppid")
|
||||
name = proc.get("process_name")
|
||||
suspicious_apis = []
|
||||
dangerous_apis = [
|
||||
"CreateRemoteThread", "VirtualAllocEx", "WriteProcessMemory",
|
||||
"NtCreateThreadEx", "RegSetValueExA", "URLDownloadToFileA",
|
||||
"ShellExecuteA", "ShellExecuteW", "WinExec", "CreateProcessA",
|
||||
"NtWriteVirtualMemory", "QueueUserAPC",
|
||||
]
|
||||
for call in proc.get("calls", []):
|
||||
if call.get("api") in dangerous_apis:
|
||||
args = {arg["name"]: arg["value"] for arg in call.get("arguments", [])}
|
||||
suspicious_apis.append({"api": call["api"], "args": args})
|
||||
processes.append({
|
||||
"pid": pid,
|
||||
"ppid": ppid,
|
||||
"name": name,
|
||||
"suspicious_api_calls": len(suspicious_apis),
|
||||
"top_suspicious": suspicious_apis[:10],
|
||||
})
|
||||
return processes
|
||||
|
||||
|
||||
def analyze_network(report):
|
||||
"""Extract network activity from the Cuckoo report."""
|
||||
network = report.get("network", {})
|
||||
return {
|
||||
"dns": [
|
||||
{"request": d.get("request"), "answers": d.get("answers", [])}
|
||||
for d in network.get("dns", [])
|
||||
],
|
||||
"http": [
|
||||
{"method": h.get("method"), "host": h.get("host"),
|
||||
"uri": h.get("uri"), "body_size": len(h.get("body", ""))}
|
||||
for h in network.get("http", [])
|
||||
],
|
||||
"tcp_connections": [
|
||||
{"src": t.get("src"), "sport": t.get("sport"),
|
||||
"dst": t.get("dst"), "dport": t.get("dport")}
|
||||
for t in network.get("tcp", [])
|
||||
],
|
||||
"udp_connections": [
|
||||
{"src": u.get("src"), "sport": u.get("sport"),
|
||||
"dst": u.get("dst"), "dport": u.get("dport")}
|
||||
for u in network.get("udp", [])
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def analyze_dropped_files(report):
|
||||
"""Extract dropped file information from the report."""
|
||||
dropped = []
|
||||
for d in report.get("dropped", []):
|
||||
dropped.append({
|
||||
"filepath": d.get("filepath", ""),
|
||||
"sha256": d.get("sha256", ""),
|
||||
"size": d.get("size", 0),
|
||||
"type": d.get("type", ""),
|
||||
})
|
||||
return dropped
|
||||
|
||||
|
||||
def analyze_signatures(report):
|
||||
"""Extract triggered behavioral signatures."""
|
||||
signatures = []
|
||||
for sig in report.get("signatures", []):
|
||||
marks = []
|
||||
for mark in sig.get("marks", []):
|
||||
if mark.get("ioc"):
|
||||
marks.append(mark["ioc"])
|
||||
elif mark.get("call"):
|
||||
marks.append(mark["call"].get("api", ""))
|
||||
signatures.append({
|
||||
"name": sig.get("name"),
|
||||
"severity": sig.get("severity"),
|
||||
"description": sig.get("description"),
|
||||
"marks": marks[:5],
|
||||
})
|
||||
return sorted(signatures, key=lambda x: x.get("severity", 0), reverse=True)
|
||||
|
||||
|
||||
def analyze_registry(report):
|
||||
"""Extract registry modifications from behavior summary."""
|
||||
summary = report.get("behavior", {}).get("summary", {})
|
||||
return {
|
||||
"keys_modified": summary.get("keys", [])[:20],
|
||||
"files_created": summary.get("files", [])[:20],
|
||||
"mutexes": summary.get("mutexes", [])[:10],
|
||||
}
|
||||
|
||||
|
||||
def generate_summary(report, processes, network, dropped, signatures, registry):
|
||||
"""Generate a consolidated analysis summary."""
|
||||
info = report.get("info", {})
|
||||
score = info.get("score", 0)
|
||||
return {
|
||||
"task_id": info.get("id"),
|
||||
"sample": info.get("category", "file"),
|
||||
"analysis_time": info.get("duration", 0),
|
||||
"machine": info.get("machine", {}).get("name", ""),
|
||||
"threat_score": score,
|
||||
"process_count": len(processes),
|
||||
"suspicious_api_total": sum(p["suspicious_api_calls"] for p in processes),
|
||||
"dns_queries": len(network["dns"]),
|
||||
"http_requests": len(network["http"]),
|
||||
"tcp_connections": len(network["tcp_connections"]),
|
||||
"dropped_files": len(dropped),
|
||||
"signatures_triggered": len(signatures),
|
||||
"high_severity_sigs": len([s for s in signatures if s["severity"] >= 3]),
|
||||
"registry_keys_modified": len(registry["keys_modified"]),
|
||||
"files_created": len(registry["files_created"]),
|
||||
}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("=" * 60)
|
||||
print("Cuckoo Sandbox Behavioral Analysis Agent")
|
||||
print("Automated malware detonation and report parsing")
|
||||
print("=" * 60)
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
arg = sys.argv[1]
|
||||
|
||||
# Check if argument is a report JSON path
|
||||
if arg.endswith(".json") and os.path.exists(arg):
|
||||
print(f"\n[*] Loading report: {arg}")
|
||||
with open(arg, "r") as f:
|
||||
report = json.load(f)
|
||||
elif arg.isdigit():
|
||||
print(f"\n[*] Loading report for task ID: {arg}")
|
||||
report = load_report(int(arg))
|
||||
elif os.path.exists(arg):
|
||||
print(f"\n[*] Submitting sample: {arg}")
|
||||
sha256 = hashlib.sha256(open(arg, "rb").read()).hexdigest()
|
||||
print(f"[*] SHA-256: {sha256}")
|
||||
task_id = submit_file(arg)
|
||||
if task_id:
|
||||
print(f"[*] Task submitted: ID={task_id}")
|
||||
print(f"[*] Monitor at: {CUCKOO_API.replace('8090', '8080')}/analysis/{task_id}/")
|
||||
else:
|
||||
print("[ERROR] Failed to submit. Check Cuckoo API connection.")
|
||||
sys.exit(0)
|
||||
else:
|
||||
report = None
|
||||
|
||||
if report:
|
||||
processes = analyze_processes(report)
|
||||
network = analyze_network(report)
|
||||
dropped = analyze_dropped_files(report)
|
||||
signatures = analyze_signatures(report)
|
||||
registry = analyze_registry(report)
|
||||
summary = generate_summary(report, processes, network, dropped, signatures, registry)
|
||||
|
||||
print(f"\n--- Analysis Summary ---")
|
||||
print(f" Score: {summary['threat_score']}/10")
|
||||
print(f" Processes: {summary['process_count']}")
|
||||
print(f" Suspicious APIs: {summary['suspicious_api_total']}")
|
||||
print(f" Signatures: {summary['signatures_triggered']} "
|
||||
f"({summary['high_severity_sigs']} high severity)")
|
||||
|
||||
print(f"\n--- Network ---")
|
||||
print(f" DNS: {summary['dns_queries']}, HTTP: {summary['http_requests']}, "
|
||||
f"TCP: {summary['tcp_connections']}")
|
||||
for http in network["http"][:5]:
|
||||
print(f" {http['method']} {http['host']}{http['uri']}")
|
||||
|
||||
print(f"\n--- Dropped Files ---")
|
||||
for d in dropped[:5]:
|
||||
print(f" {d['filepath']} ({d['size']} bytes)")
|
||||
|
||||
print(f"\n--- Top Signatures ---")
|
||||
for s in signatures[:5]:
|
||||
print(f" [{s['severity']}/5] {s['name']}: {s['description']}")
|
||||
else:
|
||||
print(f"\n[DEMO] Usage:")
|
||||
print(f" python agent.py <sample.exe> # Submit to Cuckoo")
|
||||
print(f" python agent.py <task_id> # Parse existing report")
|
||||
print(f" python agent.py <report.json> # Parse JSON report file")
|
||||
Reference in New Issue
Block a user