mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-20 06:20:58 +03:00
Initial commit - 611 cybersecurity skills across all subdomains
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Campaign Attribution Evidence Analysis Script
|
||||
|
||||
Implements structured attribution analysis:
|
||||
- Analysis of Competing Hypotheses (ACH) matrix
|
||||
- Infrastructure overlap scoring
|
||||
- TTP similarity comparison using ATT&CK
|
||||
- Evidence weighting and confidence assessment
|
||||
|
||||
Requirements:
|
||||
pip install attackcti stix2 requests
|
||||
|
||||
Usage:
|
||||
python process.py --evidence evidence.json --hypotheses actors.json --output report.json
|
||||
python process.py --compare-ttps --campaign campaign_techs.json --actor APT29
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
class AttributionEngine:
|
||||
"""Structured attribution analysis using ACH methodology."""
|
||||
|
||||
def __init__(self):
|
||||
self.evidence = []
|
||||
self.hypotheses = {}
|
||||
|
||||
def load_evidence(self, filepath):
|
||||
with open(filepath) as f:
|
||||
self.evidence = json.load(f)
|
||||
|
||||
def add_evidence(self, category, description, value, confidence):
|
||||
self.evidence.append({
|
||||
"id": len(self.evidence),
|
||||
"category": category,
|
||||
"description": description,
|
||||
"value": value,
|
||||
"confidence": confidence,
|
||||
})
|
||||
|
||||
def add_hypothesis(self, actor_name, supporting_info=""):
|
||||
self.hypotheses[actor_name] = {
|
||||
"info": supporting_info,
|
||||
"assessments": {},
|
||||
"score": 0,
|
||||
}
|
||||
|
||||
def evaluate(self, evidence_id, actor_name, assessment):
|
||||
"""Evaluate evidence against hypothesis: C=consistent, I=inconsistent, N=neutral."""
|
||||
weight = self.evidence[evidence_id]["confidence"]
|
||||
self.hypotheses[actor_name]["assessments"][evidence_id] = assessment
|
||||
|
||||
if assessment == "C":
|
||||
self.hypotheses[actor_name]["score"] += weight
|
||||
elif assessment == "I":
|
||||
self.hypotheses[actor_name]["score"] -= weight * 2
|
||||
|
||||
def generate_ach_matrix(self):
|
||||
matrix = {"evidence": [], "hypotheses": {}}
|
||||
for e in self.evidence:
|
||||
matrix["evidence"].append({
|
||||
"id": e["id"],
|
||||
"category": e["category"],
|
||||
"description": e["description"],
|
||||
})
|
||||
|
||||
for actor, data in self.hypotheses.items():
|
||||
matrix["hypotheses"][actor] = {
|
||||
"assessments": data["assessments"],
|
||||
"score": data["score"],
|
||||
"consistent": sum(1 for a in data["assessments"].values() if a == "C"),
|
||||
"inconsistent": sum(1 for a in data["assessments"].values() if a == "I"),
|
||||
"neutral": sum(1 for a in data["assessments"].values() if a == "N"),
|
||||
}
|
||||
|
||||
return matrix
|
||||
|
||||
def rank(self):
|
||||
ranked = sorted(
|
||||
self.hypotheses.items(), key=lambda x: x[1]["score"], reverse=True
|
||||
)
|
||||
results = []
|
||||
for name, data in ranked:
|
||||
incon = sum(1 for a in data["assessments"].values() if a == "I")
|
||||
confidence = "HIGH" if data["score"] >= 80 and incon == 0 else \
|
||||
"MODERATE" if data["score"] >= 40 else "LOW"
|
||||
results.append({
|
||||
"actor": name,
|
||||
"score": data["score"],
|
||||
"confidence": confidence,
|
||||
"inconsistent_count": incon,
|
||||
})
|
||||
return results
|
||||
|
||||
|
||||
def compare_ttp_similarity(campaign_techs, actor_techs):
|
||||
campaign_set = set(campaign_techs)
|
||||
actor_set = set(actor_techs)
|
||||
common = campaign_set & actor_set
|
||||
|
||||
jaccard = len(common) / len(campaign_set | actor_set) if (campaign_set | actor_set) else 0
|
||||
return {
|
||||
"common": sorted(common),
|
||||
"jaccard_similarity": round(jaccard, 3),
|
||||
"campaign_coverage": round(len(common) / len(campaign_set) * 100, 1) if campaign_set else 0,
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Campaign Attribution Analysis")
|
||||
parser.add_argument("--evidence", help="Evidence JSON file")
|
||||
parser.add_argument("--hypotheses", help="Hypotheses JSON file")
|
||||
parser.add_argument("--compare-ttps", action="store_true")
|
||||
parser.add_argument("--campaign", help="Campaign techniques JSON")
|
||||
parser.add_argument("--actor", help="Actor name for ATT&CK lookup")
|
||||
parser.add_argument("--output", default="attribution_report.json")
|
||||
|
||||
args = parser.parse_args()
|
||||
engine = AttributionEngine()
|
||||
|
||||
if args.evidence and args.hypotheses:
|
||||
engine.load_evidence(args.evidence)
|
||||
with open(args.hypotheses) as f:
|
||||
hyps = json.load(f)
|
||||
for h in hyps:
|
||||
engine.add_hypothesis(h["name"], h.get("info", ""))
|
||||
for eid, assessment in h.get("evaluations", {}).items():
|
||||
engine.evaluate(int(eid), h["name"], assessment)
|
||||
|
||||
matrix = engine.generate_ach_matrix()
|
||||
rankings = engine.rank()
|
||||
report = {"ach_matrix": matrix, "rankings": rankings}
|
||||
print(json.dumps(report, indent=2))
|
||||
|
||||
with open(args.output, "w") as f:
|
||||
json.dump(report, f, indent=2)
|
||||
|
||||
elif args.compare_ttps and args.campaign:
|
||||
with open(args.campaign) as f:
|
||||
campaign_techs = json.load(f)
|
||||
|
||||
if args.actor:
|
||||
try:
|
||||
from attackcti import attack_client
|
||||
lift = attack_client()
|
||||
groups = lift.get_groups()
|
||||
group = next(
|
||||
(g for g in groups if args.actor.lower() in g.get("name", "").lower()),
|
||||
None,
|
||||
)
|
||||
if group:
|
||||
gid = group["external_references"][0]["external_id"]
|
||||
techs = lift.get_techniques_used_by_group(gid)
|
||||
actor_techs = [
|
||||
t["external_references"][0]["external_id"]
|
||||
for t in techs if t.get("external_references")
|
||||
]
|
||||
result = compare_ttp_similarity(campaign_techs, actor_techs)
|
||||
print(json.dumps(result, indent=2))
|
||||
except ImportError:
|
||||
print("[-] attackcti not installed")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user