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:
mukul975
2026-03-10 21:02:12 +01:00
parent c74d52fa30
commit 27c6414ca5
1390 changed files with 106806 additions and 0 deletions
@@ -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,86 @@
# API Reference: Windows Event Log Artifact Extraction Agent
## Dependencies
| Library | Version | Purpose |
|---------|---------|---------|
| evtx (python-evtx) | >=0.8 | Parse Windows EVTX binary log files into JSON records |
## CLI Usage
```bash
python scripts/agent.py \
--evtx-dir /cases/case-001/evtx/ \
--output-dir /cases/case-001/analysis/ \
--output evtx_report.json
# Or specify individual files:
python scripts/agent.py \
--evtx-files Security.evtx System.evtx \
--output-dir /cases/analysis/
```
## Functions
### `parse_evtx_file(evtx_path) -> list`
Parses a single EVTX file using PyEvtxParser. Returns list of dicts with event_id, timestamp, channel, computer, event_data.
### `filter_critical_events(records) -> dict`
Filters records to 15 critical Event IDs (4624, 4625, 4688, 4697, 1102, etc.) grouped by Event ID.
### `detect_lateral_movement(records) -> list`
Identifies network logons (Type 3) and RDP (Type 10) from non-local IPs. Flags pass-the-hash indicators (Type 9 + NTLM).
### `detect_privilege_escalation(records) -> list`
Detects special privilege assignment (4672), group membership changes (4728/4732/4756), and account creation (4720).
### `detect_suspicious_processes(records) -> list`
Matches 4688 process creation events against a list of known attack tools (mimikatz, psexec, rubeus, etc.).
### `detect_log_clearing(records) -> list`
Identifies audit log clearing events (Event ID 1102 and 104).
### `detect_persistence(records) -> list`
Detects service installations (4697/7045) and scheduled task creation (4698).
### `generate_summary(records, findings) -> dict`
Computes statistics: total records, top event IDs, alert counts per detection category.
### `export_timeline_csv(records, output_path)`
Exports critical events as a sorted CSV timeline with timestamp, event_id, description, details.
### `analyze_evtx(evtx_paths, output_dir) -> dict`
Orchestrates parsing of multiple EVTX files and runs all detection functions.
## Critical Event IDs
| Event ID | Description |
|----------|-------------|
| 1102 | Audit Log Cleared |
| 4624 | Successful Logon |
| 4625 | Failed Logon |
| 4648 | Explicit Credential Logon |
| 4672 | Special Privileges Assigned |
| 4688 | New Process Created |
| 4697 | Service Installed |
| 4698 | Scheduled Task Created |
| 4720 | User Account Created |
| 7045 | New Service Installed (System log) |
## Output Schema
```json
{
"files_analyzed": ["/cases/evtx/Security.evtx"],
"summary": {
"total_records": 245678,
"lateral_movement_alerts": 12,
"suspicious_processes": 3,
"persistence": 5
},
"findings": {
"lateral_movement": [{"user": "admin", "source_ip": "10.0.0.5", "logon_type": "Network"}],
"suspicious_processes": [{"matched_pattern": "mimikatz", "process": "m.exe"}]
}
}
```
@@ -0,0 +1,278 @@
#!/usr/bin/env python3
"""Windows Event Log artifact extraction agent using evtx library for EVTX parsing."""
import argparse
import csv
import json
import logging
import os
import sys
from collections import Counter, defaultdict
from datetime import datetime
from typing import Dict, List, Optional
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger(__name__)
try:
from evtx import PyEvtxParser
except ImportError:
sys.exit("evtx required: pip install evtx")
CRITICAL_EVENT_IDS = {
"1102": "Audit Log Cleared",
"4624": "Successful Logon",
"4625": "Failed Logon",
"4634": "Logoff",
"4648": "Explicit Credential Logon",
"4672": "Special Privileges Assigned",
"4688": "New Process Created",
"4697": "Service Installed",
"4698": "Scheduled Task Created",
"4720": "User Account Created",
"4724": "Password Reset Attempted",
"4728": "Member Added to Global Group",
"4732": "Member Added to Local Group",
"4756": "Member Added to Universal Group",
"7045": "New Service Installed (System)",
}
LOGON_TYPES = {
"2": "Interactive", "3": "Network", "4": "Batch", "5": "Service",
"7": "Unlock", "8": "NetworkCleartext", "9": "NewCredentials",
"10": "RemoteInteractive (RDP)", "11": "CachedInteractive",
}
SUSPICIOUS_PROCESSES = [
"mimikatz", "psexec", "procdump", "lazagne", "sharphound",
"rubeus", "certutil", "powershell -enc", "bitsadmin",
"wmic shadowcopy delete", "vssadmin delete", "bcdedit /set",
]
def parse_evtx_file(evtx_path: str) -> List[dict]:
"""Parse an EVTX file and return list of event records."""
if not os.path.isfile(evtx_path):
logger.warning("EVTX file not found: %s", evtx_path)
return []
records = []
try:
parser = PyEvtxParser(evtx_path)
for record in parser.records_json():
try:
data = json.loads(record["data"])
event = data.get("Event", {})
system = event.get("System", {})
event_id = str(system.get("EventID", ""))
if isinstance(system.get("EventID"), dict):
event_id = str(system["EventID"].get("#text", ""))
timestamp = system.get("TimeCreated", {}).get("#attributes", {}).get("SystemTime", "")
event_data = event.get("EventData", {})
records.append({
"event_id": event_id, "timestamp": timestamp,
"channel": system.get("Channel", ""),
"computer": system.get("Computer", ""),
"event_data": event_data if isinstance(event_data, dict) else {},
})
except (json.JSONDecodeError, KeyError):
continue
except Exception as exc:
logger.error("Error parsing %s: %s", evtx_path, exc)
logger.info("Parsed %d records from %s", len(records), evtx_path)
return records
def filter_critical_events(records: List[dict]) -> Dict[str, List[dict]]:
"""Filter records for critical security event IDs."""
filtered = defaultdict(list)
for r in records:
if r["event_id"] in CRITICAL_EVENT_IDS:
r["description"] = CRITICAL_EVENT_IDS[r["event_id"]]
filtered[r["event_id"]].append(r)
return dict(filtered)
def detect_lateral_movement(records: List[dict]) -> List[dict]:
"""Detect lateral movement indicators from logon events."""
findings = []
for r in records:
if r["event_id"] != "4624":
continue
ed = r["event_data"]
logon_type = str(ed.get("LogonType", ""))
auth_pkg = str(ed.get("AuthenticationPackageName", ""))
src_ip = ed.get("IpAddress", "-")
user = ed.get("TargetUserName", "")
if logon_type in ("3", "10") and src_ip not in ("-", "::1", "127.0.0.1"):
findings.append({
"timestamp": r["timestamp"], "type": "lateral_movement",
"logon_type": LOGON_TYPES.get(logon_type, logon_type),
"user": user, "source_ip": src_ip, "auth_package": auth_pkg,
"pth_indicator": logon_type == "9" and "NTLM" in auth_pkg,
})
return findings
def detect_privilege_escalation(records: List[dict]) -> List[dict]:
"""Detect privilege escalation from group membership and special privilege events."""
findings = []
escalation_ids = {"4672", "4728", "4732", "4756", "4720"}
for r in records:
if r["event_id"] not in escalation_ids:
continue
ed = r["event_data"]
findings.append({
"timestamp": r["timestamp"], "type": "privilege_escalation",
"event_id": r["event_id"], "description": CRITICAL_EVENT_IDS.get(r["event_id"], ""),
"user": ed.get("TargetUserName", ed.get("SubjectUserName", "")),
"group": ed.get("TargetDomainName", ""),
})
return findings
def detect_suspicious_processes(records: List[dict]) -> List[dict]:
"""Detect suspicious process creation events."""
findings = []
for r in records:
if r["event_id"] != "4688":
continue
ed = r["event_data"]
cmd = str(ed.get("CommandLine", ed.get("NewProcessName", ""))).lower()
process_name = str(ed.get("NewProcessName", "")).lower()
for pattern in SUSPICIOUS_PROCESSES:
if pattern in cmd or pattern in process_name:
findings.append({
"timestamp": r["timestamp"], "type": "suspicious_process",
"matched_pattern": pattern,
"process": ed.get("NewProcessName", ""),
"command_line": str(ed.get("CommandLine", ""))[:300],
"user": ed.get("SubjectUserName", ""),
"parent": ed.get("ParentProcessName", ""),
})
break
return findings
def detect_log_clearing(records: List[dict]) -> List[dict]:
"""Detect audit log clearing events."""
findings = []
for r in records:
if r["event_id"] in ("1102", "104"):
findings.append({
"timestamp": r["timestamp"], "type": "log_cleared",
"event_id": r["event_id"], "channel": r.get("channel", ""),
"user": r["event_data"].get("SubjectUserName", "SYSTEM"),
})
return findings
def detect_persistence(records: List[dict]) -> List[dict]:
"""Detect persistence mechanisms from service and scheduled task events."""
findings = []
for r in records:
if r["event_id"] in ("4697", "7045"):
ed = r["event_data"]
findings.append({
"timestamp": r["timestamp"], "type": "service_install",
"service_name": ed.get("ServiceName", ""),
"image_path": ed.get("ImagePath", ed.get("ServiceFileName", "")),
"start_type": ed.get("StartType", ""),
"user": ed.get("AccountName", ed.get("SubjectUserName", "")),
})
elif r["event_id"] == "4698":
ed = r["event_data"]
findings.append({
"timestamp": r["timestamp"], "type": "scheduled_task",
"task_name": ed.get("TaskName", ""),
"user": ed.get("SubjectUserName", ""),
})
return findings
def generate_summary(records: List[dict], findings: dict) -> dict:
"""Generate analysis summary statistics."""
event_counts = Counter(r["event_id"] for r in records)
top_events = [(eid, count, CRITICAL_EVENT_IDS.get(eid, "Other"))
for eid, count in event_counts.most_common(15)]
return {
"total_records": len(records),
"unique_event_ids": len(event_counts),
"top_events": top_events,
"lateral_movement_alerts": len(findings.get("lateral_movement", [])),
"priv_esc_alerts": len(findings.get("privilege_escalation", [])),
"suspicious_processes": len(findings.get("suspicious_processes", [])),
"log_clearing": len(findings.get("log_clearing", [])),
"persistence": len(findings.get("persistence", [])),
}
def export_timeline_csv(records: List[dict], output_path: str) -> None:
"""Export critical events as a CSV timeline."""
critical = [r for r in records if r["event_id"] in CRITICAL_EVENT_IDS]
critical.sort(key=lambda r: r["timestamp"])
with open(output_path, "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["timestamp", "event_id", "description", "computer", "details"])
for r in critical:
desc = CRITICAL_EVENT_IDS.get(r["event_id"], "")
details = json.dumps(r["event_data"], default=str)[:300]
writer.writerow([r["timestamp"], r["event_id"], desc, r["computer"], details])
logger.info("Timeline exported: %d events to %s", len(critical), output_path)
def analyze_evtx(evtx_paths: List[str], output_dir: str) -> dict:
"""Run full EVTX analysis across multiple log files."""
all_records = []
for path in evtx_paths:
all_records.extend(parse_evtx_file(path))
all_records.sort(key=lambda r: r["timestamp"])
findings = {
"lateral_movement": detect_lateral_movement(all_records),
"privilege_escalation": detect_privilege_escalation(all_records),
"suspicious_processes": detect_suspicious_processes(all_records),
"log_clearing": detect_log_clearing(all_records),
"persistence": detect_persistence(all_records),
}
report = {
"analysis_date": datetime.utcnow().isoformat(),
"files_analyzed": evtx_paths,
"summary": generate_summary(all_records, findings),
"findings": findings,
"critical_events": filter_critical_events(all_records),
}
export_timeline_csv(all_records, os.path.join(output_dir, "event_timeline.csv"))
return report
def main():
parser = argparse.ArgumentParser(description="Windows Event Log Artifact Extraction Agent")
parser.add_argument("--evtx-dir", default="", help="Directory containing EVTX files")
parser.add_argument("--evtx-files", nargs="*", default=[], help="Specific EVTX files to parse")
parser.add_argument("--output-dir", default=".", help="Output directory")
parser.add_argument("--output", default="evtx_report.json")
args = parser.parse_args()
os.makedirs(args.output_dir, exist_ok=True)
evtx_paths = list(args.evtx_files)
if args.evtx_dir and os.path.isdir(args.evtx_dir):
for f in os.listdir(args.evtx_dir):
if f.lower().endswith(".evtx"):
evtx_paths.append(os.path.join(args.evtx_dir, f))
if not evtx_paths:
logger.error("No EVTX files specified")
sys.exit(1)
report = analyze_evtx(evtx_paths, args.output_dir)
out_path = os.path.join(args.output_dir, args.output)
with open(out_path, "w") as f:
json.dump(report, f, indent=2, default=str)
logger.info("Report saved to %s", out_path)
print(json.dumps(report["summary"], indent=2, default=str))
if __name__ == "__main__":
main()