mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-08-04 18:00:18 +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,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Anthropic Agent Skills Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,50 @@
|
||||
# API Reference: Purple Team Exercise
|
||||
|
||||
## Atomic Red Team (PowerShell)
|
||||
|
||||
```powershell
|
||||
# Install
|
||||
IEX (IWR 'https://raw.githubusercontent.com/redcanaryco/invoke-atomicredteam/master/install-atomicredteam.ps1')
|
||||
Install-AtomicRedTeam -getAtomics
|
||||
|
||||
# Execute technique
|
||||
Invoke-AtomicTest T1059.001 -TestNumbers 1
|
||||
|
||||
# Cleanup after test
|
||||
Invoke-AtomicTest T1059.001 -TestNumbers 1 -Cleanup
|
||||
```
|
||||
|
||||
## MITRE Caldera API
|
||||
|
||||
| Endpoint | Method | Description |
|
||||
|----------|--------|-------------|
|
||||
| `/api/v2/operations` | POST | Start adversary emulation operation |
|
||||
| `/api/v2/operations/{id}` | GET | Get operation status and results |
|
||||
| `/api/v2/abilities` | GET | List available ATT&CK abilities |
|
||||
| `/api/v2/adversaries` | GET | List adversary profiles |
|
||||
|
||||
## ATT&CK Techniques Commonly Tested
|
||||
|
||||
| ID | Technique | Detection Signal |
|
||||
|----|-----------|-----------------|
|
||||
| T1059.001 | PowerShell | Sysmon EventCode 1, PowerShell logging |
|
||||
| T1053.005 | Scheduled Task | EventCode 4698 |
|
||||
| T1003.001 | LSASS Access | Sysmon EventCode 10 |
|
||||
| T1550.002 | Pass-the-Hash | EventCode 4624 with NTLM Type 3 |
|
||||
| T1021.002 | PsExec | EventCode 7045 (PSEXESVC) |
|
||||
| T1490 | Shadow Copy Deletion | vssadmin process creation |
|
||||
|
||||
## Python Libraries
|
||||
|
||||
| Library | Version | Purpose |
|
||||
|---------|---------|---------|
|
||||
| `json` | stdlib | Test plan and report management |
|
||||
| `subprocess` | stdlib | Execute Atomic Red Team tests |
|
||||
| `datetime` | stdlib | Detection latency measurement |
|
||||
|
||||
## References
|
||||
|
||||
- Atomic Red Team: https://github.com/redcanaryco/atomic-red-team
|
||||
- MITRE Caldera: https://github.com/mitre/caldera
|
||||
- Vectr: https://vectr.io/
|
||||
- ATT&CK Navigator: https://mitre-attack.github.io/attack-navigator/
|
||||
@@ -0,0 +1,198 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Agent for performing purple team exercises.
|
||||
|
||||
Coordinates red team technique execution with blue team detection
|
||||
validation, tracks ATT&CK-mapped test results, and generates
|
||||
detection coverage reports.
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
import subprocess
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class PurpleTeamAgent:
|
||||
"""Manages purple team exercise execution and tracking."""
|
||||
|
||||
def __init__(self, exercise_id, output_dir):
|
||||
self.exercise_id = exercise_id
|
||||
self.output_dir = Path(output_dir)
|
||||
self.output_dir.mkdir(parents=True, exist_ok=True)
|
||||
self.test_plan = []
|
||||
self.results = []
|
||||
|
||||
def add_technique(self, attack_id, name, tool, expected_detection):
|
||||
"""Add a technique to the test plan."""
|
||||
self.test_plan.append({
|
||||
"attack_id": attack_id,
|
||||
"name": name,
|
||||
"tool": tool,
|
||||
"expected_detection": expected_detection,
|
||||
"status": "pending",
|
||||
})
|
||||
|
||||
def load_test_plan(self, plan_path):
|
||||
"""Load test plan from a JSON file."""
|
||||
with open(plan_path, "r") as f:
|
||||
data = json.load(f)
|
||||
self.test_plan = data.get("techniques", [])
|
||||
|
||||
def build_default_test_plan(self):
|
||||
"""Build a default FIN7-style purple team test plan."""
|
||||
techniques = [
|
||||
("T1059.001", "PowerShell Execution", "Atomic Red Team", "PowerShell alert"),
|
||||
("T1053.005", "Scheduled Task", "Atomic Red Team", "Task creation alert"),
|
||||
("T1547.001", "Registry Run Keys", "Atomic Red Team", "Registry modification alert"),
|
||||
("T1003.001", "LSASS Memory Access", "Mimikatz", "Credential dumping alert"),
|
||||
("T1550.002", "Pass-the-Hash", "Mimikatz", "NTLM anomaly detection"),
|
||||
("T1021.002", "PsExec", "PsExec.exe", "PsExec service creation alert"),
|
||||
("T1047", "WMI Execution", "wmic", "WMI remote execution alert"),
|
||||
("T1021.001", "RDP Lateral Movement", "xfreerdp", "RDP lateral movement alert"),
|
||||
("T1071.001", "Web C2 Channel", "C2 framework", "C2 beacon detection"),
|
||||
("T1041", "Exfiltration over C2", "rclone", "Data exfiltration alert"),
|
||||
("T1490", "Inhibit Recovery", "vssadmin", "Shadow copy deletion alert"),
|
||||
("T1070.001", "Clear Event Logs", "wevtutil", "Log clearing detection"),
|
||||
]
|
||||
for attack_id, name, tool, detection in techniques:
|
||||
self.add_technique(attack_id, name, tool, detection)
|
||||
|
||||
def record_execution(self, attack_id, execution_time=None):
|
||||
"""Record that a red team technique has been executed."""
|
||||
if execution_time is None:
|
||||
execution_time = datetime.utcnow().isoformat()
|
||||
for technique in self.test_plan:
|
||||
if technique["attack_id"] == attack_id:
|
||||
technique["execution_time"] = execution_time
|
||||
technique["status"] = "executed"
|
||||
break
|
||||
|
||||
def record_detection(self, attack_id, detected, alert_name=None,
|
||||
detection_time=None, notes=""):
|
||||
"""Record blue team detection result for a technique."""
|
||||
if detection_time is None and detected:
|
||||
detection_time = datetime.utcnow().isoformat()
|
||||
|
||||
for technique in self.test_plan:
|
||||
if technique["attack_id"] == attack_id:
|
||||
exec_time = technique.get("execution_time", "")
|
||||
latency = None
|
||||
if detected and exec_time and detection_time:
|
||||
try:
|
||||
t1 = datetime.fromisoformat(exec_time)
|
||||
t2 = datetime.fromisoformat(detection_time)
|
||||
latency = (t2 - t1).total_seconds()
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
result = {
|
||||
"attack_id": attack_id,
|
||||
"name": technique["name"],
|
||||
"detected": detected,
|
||||
"alert_name": alert_name,
|
||||
"execution_time": exec_time,
|
||||
"detection_time": detection_time,
|
||||
"latency_seconds": latency,
|
||||
"notes": notes,
|
||||
"status": "PASS" if detected else "FAIL",
|
||||
}
|
||||
self.results.append(result)
|
||||
technique["status"] = "detected" if detected else "gap"
|
||||
return result
|
||||
return None
|
||||
|
||||
def get_coverage_metrics(self):
|
||||
"""Calculate detection coverage metrics."""
|
||||
if not self.results:
|
||||
return {}
|
||||
|
||||
total = len(self.results)
|
||||
detected = sum(1 for r in self.results if r["detected"])
|
||||
gaps = total - detected
|
||||
latencies = [r["latency_seconds"] for r in self.results
|
||||
if r["latency_seconds"] is not None]
|
||||
avg_latency = sum(latencies) / len(latencies) if latencies else 0
|
||||
|
||||
return {
|
||||
"total_techniques": total,
|
||||
"detected": detected,
|
||||
"gaps": gaps,
|
||||
"coverage_pct": round(detected / total * 100, 1) if total else 0,
|
||||
"avg_latency_seconds": round(avg_latency, 1),
|
||||
"min_latency": round(min(latencies), 1) if latencies else None,
|
||||
"max_latency": round(max(latencies), 1) if latencies else None,
|
||||
}
|
||||
|
||||
def get_gap_analysis(self):
|
||||
"""Identify detection gaps requiring remediation."""
|
||||
return [
|
||||
{
|
||||
"attack_id": r["attack_id"],
|
||||
"name": r["name"],
|
||||
"notes": r["notes"],
|
||||
"remediation": f"Create detection rule for {r['name']}",
|
||||
}
|
||||
for r in self.results if not r["detected"]
|
||||
]
|
||||
|
||||
def generate_report(self):
|
||||
"""Generate comprehensive purple team exercise report."""
|
||||
metrics = self.get_coverage_metrics()
|
||||
gaps = self.get_gap_analysis()
|
||||
|
||||
report = {
|
||||
"exercise_id": self.exercise_id,
|
||||
"report_date": datetime.utcnow().isoformat(),
|
||||
"coverage_metrics": metrics,
|
||||
"detailed_results": self.results,
|
||||
"detection_gaps": gaps,
|
||||
"test_plan": self.test_plan,
|
||||
}
|
||||
|
||||
report_path = self.output_dir / f"{self.exercise_id}_report.json"
|
||||
with open(report_path, "w") as f:
|
||||
json.dump(report, f, indent=2)
|
||||
|
||||
print(f"PURPLE TEAM EXERCISE REPORT - {self.exercise_id}")
|
||||
print("=" * 50)
|
||||
print(f"Techniques Tested: {metrics.get('total_techniques', 0)}")
|
||||
print(f"Detected: {metrics.get('detected', 0)} ({metrics.get('coverage_pct', 0)}%)")
|
||||
print(f"Gaps: {metrics.get('gaps', 0)}")
|
||||
print(f"Avg Detection Latency: {metrics.get('avg_latency_seconds', 0)}s")
|
||||
print(f"\nDetailed Results:")
|
||||
for r in self.results:
|
||||
status = "PASS" if r["detected"] else "FAIL"
|
||||
latency = f"{r['latency_seconds']}s" if r["latency_seconds"] else "N/A"
|
||||
print(f" [{status}] {r['attack_id']} {r['name']} (Latency: {latency})")
|
||||
|
||||
if gaps:
|
||||
print(f"\nDetection Gaps:")
|
||||
for g in gaps:
|
||||
print(f" - {g['attack_id']} {g['name']}: {g['notes']}")
|
||||
|
||||
return report
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: agent.py <exercise_id> [output_dir] [plan_file]")
|
||||
sys.exit(1)
|
||||
|
||||
exercise_id = sys.argv[1]
|
||||
output_dir = sys.argv[2] if len(sys.argv) > 2 else "./purple_team_output"
|
||||
|
||||
agent = PurpleTeamAgent(exercise_id, output_dir)
|
||||
|
||||
if len(sys.argv) > 3:
|
||||
agent.load_test_plan(sys.argv[3])
|
||||
else:
|
||||
agent.build_default_test_plan()
|
||||
|
||||
print(json.dumps({"test_plan": agent.test_plan}, indent=2))
|
||||
print(f"\nTest plan created with {len(agent.test_plan)} techniques")
|
||||
print(f"Output directory: {output_dir}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user