mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-08-30 21:29: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,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,73 @@
|
||||
# API Reference: Diamond Model Analysis Agent
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Library | Version | Purpose |
|
||||
|---------|---------|---------|
|
||||
| Python stdlib | 3.8+ | json, dataclasses, hashlib, argparse |
|
||||
|
||||
## CLI Usage
|
||||
|
||||
```bash
|
||||
python scripts/agent.py \
|
||||
--input events.json \
|
||||
--output diamond_report.json \
|
||||
--pivot-type infrastructure \
|
||||
--pivot-value "185.220.101.42"
|
||||
```
|
||||
|
||||
## Input Format
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"event_id": "EVT-001",
|
||||
"timestamp": "2025-01-15T14:30:00Z",
|
||||
"adversary": ["APT29"],
|
||||
"adversary_confidence": "high",
|
||||
"capabilities": ["SUNBURST", "T1071.001"],
|
||||
"infrastructure": ["185.220.101.42", "evil-redir.com"],
|
||||
"victims": ["TargetCorp"],
|
||||
"phase": "C2",
|
||||
"result": "success"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Functions
|
||||
|
||||
### `create_event(event_data) -> DiamondEvent`
|
||||
Constructs a `DiamondEvent` dataclass from raw dict. Auto-generates `event_id` via MD5 if not provided.
|
||||
|
||||
### `pivot_on_vertex(events, vertex_type, value) -> list`
|
||||
Returns events sharing a specified vertex value. Supports pivoting on `adversary`, `capability`, `infrastructure`, `victim`.
|
||||
|
||||
### `cluster_events(events) -> dict`
|
||||
Groups events by shared infrastructure or capability values. Returns clusters with overlapping event IDs.
|
||||
|
||||
### `build_activity_thread(events) -> list`
|
||||
Sorts events chronologically and assigns sequence numbers for timeline reconstruction.
|
||||
|
||||
### `generate_report(events) -> dict`
|
||||
Produces the full Diamond Model report with unique entities, activity thread, and clusters.
|
||||
|
||||
## Data Classes
|
||||
|
||||
### `Vertex`
|
||||
Fields: `vertex_type` (str), `values` (list), `confidence` (str), `notes` (str)
|
||||
|
||||
### `DiamondEvent`
|
||||
Fields: `event_id`, `timestamp`, `adversary` (Vertex), `capability` (Vertex), `infrastructure` (Vertex), `victim` (Vertex), `phase`, `direction`, `result`
|
||||
|
||||
## Output Schema
|
||||
|
||||
```json
|
||||
{
|
||||
"report_date": "ISO-8601",
|
||||
"total_events": 5,
|
||||
"unique_adversaries": ["APT29"],
|
||||
"unique_infrastructure": ["185.220.101.42"],
|
||||
"activity_thread": [{"sequence": 1, "event_id": "EVT-001", ...}],
|
||||
"clusters": {"clusters": [...], "total_events": 5}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Diamond Model intrusion analysis agent for structuring adversary activity."""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import hashlib
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from dataclasses import dataclass, field, asdict
|
||||
from typing import List, Optional
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Vertex:
|
||||
vertex_type: str
|
||||
values: List[str] = field(default_factory=list)
|
||||
confidence: str = "medium"
|
||||
notes: str = ""
|
||||
|
||||
|
||||
@dataclass
|
||||
class DiamondEvent:
|
||||
event_id: str
|
||||
timestamp: str
|
||||
adversary: Vertex
|
||||
capability: Vertex
|
||||
infrastructure: Vertex
|
||||
victim: Vertex
|
||||
phase: str = ""
|
||||
direction: str = "external-to-internal"
|
||||
result: str = "success"
|
||||
meta_notes: str = ""
|
||||
|
||||
|
||||
def create_event(event_data: dict) -> DiamondEvent:
|
||||
"""Build a DiamondEvent from a raw dict of incident data."""
|
||||
return DiamondEvent(
|
||||
event_id=event_data.get("event_id", hashlib.md5(
|
||||
json.dumps(event_data, sort_keys=True).encode()
|
||||
).hexdigest()[:8]),
|
||||
timestamp=event_data.get("timestamp", datetime.utcnow().isoformat()),
|
||||
adversary=Vertex(
|
||||
vertex_type="adversary",
|
||||
values=event_data.get("adversary", []),
|
||||
confidence=event_data.get("adversary_confidence", "medium"),
|
||||
),
|
||||
capability=Vertex(
|
||||
vertex_type="capability",
|
||||
values=event_data.get("capabilities", []),
|
||||
),
|
||||
infrastructure=Vertex(
|
||||
vertex_type="infrastructure",
|
||||
values=event_data.get("infrastructure", []),
|
||||
),
|
||||
victim=Vertex(
|
||||
vertex_type="victim",
|
||||
values=event_data.get("victims", []),
|
||||
),
|
||||
phase=event_data.get("phase", ""),
|
||||
direction=event_data.get("direction", "external-to-internal"),
|
||||
result=event_data.get("result", "success"),
|
||||
)
|
||||
|
||||
|
||||
def pivot_on_vertex(events: List[DiamondEvent], vertex_type: str, value: str) -> List[DiamondEvent]:
|
||||
"""Pivot across events sharing a common vertex value."""
|
||||
matches = []
|
||||
for event in events:
|
||||
vertex = getattr(event, vertex_type, None)
|
||||
if vertex and value in vertex.values:
|
||||
matches.append(event)
|
||||
logger.info("Pivot on %s='%s' returned %d events", vertex_type, value, len(matches))
|
||||
return matches
|
||||
|
||||
|
||||
def cluster_events(events: List[DiamondEvent]) -> dict:
|
||||
"""Cluster events by shared infrastructure and capability vertices."""
|
||||
infra_map = {}
|
||||
cap_map = {}
|
||||
for event in events:
|
||||
for val in event.infrastructure.values:
|
||||
infra_map.setdefault(val, []).append(event.event_id)
|
||||
for val in event.capability.values:
|
||||
cap_map.setdefault(val, []).append(event.event_id)
|
||||
|
||||
clusters = []
|
||||
for key, eids in infra_map.items():
|
||||
if len(eids) > 1:
|
||||
clusters.append({"pivot": "infrastructure", "value": key, "event_ids": eids})
|
||||
for key, eids in cap_map.items():
|
||||
if len(eids) > 1:
|
||||
clusters.append({"pivot": "capability", "value": key, "event_ids": eids})
|
||||
return {"clusters": clusters, "total_events": len(events)}
|
||||
|
||||
|
||||
def build_activity_thread(events: List[DiamondEvent]) -> List[dict]:
|
||||
"""Order events into a time-sorted activity thread."""
|
||||
sorted_events = sorted(events, key=lambda e: e.timestamp)
|
||||
thread = []
|
||||
for idx, event in enumerate(sorted_events):
|
||||
thread.append({
|
||||
"sequence": idx + 1,
|
||||
"event_id": event.event_id,
|
||||
"timestamp": event.timestamp,
|
||||
"phase": event.phase,
|
||||
"adversary": event.adversary.values,
|
||||
"capability": event.capability.values,
|
||||
"infrastructure": event.infrastructure.values,
|
||||
"victim": event.victim.values,
|
||||
"result": event.result,
|
||||
})
|
||||
return thread
|
||||
|
||||
|
||||
def generate_report(events: List[DiamondEvent]) -> dict:
|
||||
"""Generate a complete Diamond Model analysis report."""
|
||||
clusters = cluster_events(events)
|
||||
thread = build_activity_thread(events)
|
||||
|
||||
all_adversaries = set()
|
||||
all_infra = set()
|
||||
all_caps = set()
|
||||
for e in events:
|
||||
all_adversaries.update(e.adversary.values)
|
||||
all_infra.update(e.infrastructure.values)
|
||||
all_caps.update(e.capability.values)
|
||||
|
||||
return {
|
||||
"report_date": datetime.utcnow().isoformat(),
|
||||
"total_events": len(events),
|
||||
"unique_adversaries": sorted(all_adversaries),
|
||||
"unique_infrastructure": sorted(all_infra),
|
||||
"unique_capabilities": sorted(all_caps),
|
||||
"activity_thread": thread,
|
||||
"clusters": clusters,
|
||||
}
|
||||
|
||||
|
||||
def load_events_from_file(filepath: str) -> List[DiamondEvent]:
|
||||
"""Load raw event data from a JSON file."""
|
||||
with open(filepath) as f:
|
||||
raw = json.load(f)
|
||||
events_data = raw if isinstance(raw, list) else raw.get("events", [])
|
||||
return [create_event(e) for e in events_data]
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Diamond Model Analysis Agent")
|
||||
parser.add_argument("--input", required=True, help="JSON file with raw event data")
|
||||
parser.add_argument("--output", default="diamond_report.json", help="Output report path")
|
||||
parser.add_argument("--pivot-type", choices=["adversary", "capability", "infrastructure", "victim"])
|
||||
parser.add_argument("--pivot-value", help="Value to pivot on")
|
||||
args = parser.parse_args()
|
||||
|
||||
events = load_events_from_file(args.input)
|
||||
logger.info("Loaded %d Diamond events", len(events))
|
||||
|
||||
if args.pivot_type and args.pivot_value:
|
||||
events = pivot_on_vertex(events, args.pivot_type, args.pivot_value)
|
||||
|
||||
report = generate_report(events)
|
||||
with open(args.output, "w") as f:
|
||||
json.dump(report, f, indent=2, default=str)
|
||||
logger.info("Diamond Model report saved to %s", args.output)
|
||||
print(json.dumps(report, indent=2, default=str))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user