mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-09-12 11:20:51 +03:00
Complete folder anatomy for all 649 cybersecurity skills + update LICENSE to Mahipal
- Add scripts/agent.py and references/api-reference.md to all remaining skills - Update all 648 LICENSE files: copyright now reads 'Mahipal' - Add implementing-security-monitoring-with-datadog (new skill with full anatomy) - All 649 skills now have: SKILL.md, LICENSE, scripts/agent.py, references/api-reference.md
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Anthropic Agent Skills Contributors
|
||||
Copyright (c) 2025 Mahipal
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
# API Reference: Stuxnet-Style ICS Attack Detection
|
||||
|
||||
## Modbus TCP Protocol
|
||||
|
||||
### Frame Structure
|
||||
| Offset | Size | Field |
|
||||
|--------|------|-------|
|
||||
| 0 | 2 | Transaction ID |
|
||||
| 2 | 2 | Protocol ID (0x0000) |
|
||||
| 4 | 2 | Length |
|
||||
| 6 | 1 | Unit ID |
|
||||
| 7 | 1 | Function Code |
|
||||
| 8+ | var | Data |
|
||||
|
||||
### Write Function Codes (Attack-Relevant)
|
||||
| Code | Name | Risk |
|
||||
|------|------|------|
|
||||
| 5 | Write Single Coil | Medium |
|
||||
| 6 | Write Single Register | Medium |
|
||||
| 15 | Write Multiple Coils | High |
|
||||
| 16 | Write Multiple Registers | High |
|
||||
| 22 | Mask Write Register | High |
|
||||
|
||||
## Siemens S7comm Protocol
|
||||
|
||||
### S7 Parameter Functions
|
||||
| Code | Name |
|
||||
|------|------|
|
||||
| 0x04 | Read Variable |
|
||||
| 0x05 | Write Variable |
|
||||
| 0x1A | Request Download |
|
||||
| 0x1B | Download Block |
|
||||
| 0x1C | Download Ended |
|
||||
| 0x28 | PLC Control (Start/Stop) |
|
||||
|
||||
## Wireshark/tshark Filters
|
||||
|
||||
### Modbus write operations
|
||||
```bash
|
||||
tshark -r capture.pcap -Y "modbus.func_code >= 5 && modbus.func_code <= 16"
|
||||
```
|
||||
|
||||
### S7comm block downloads
|
||||
```bash
|
||||
tshark -r capture.pcap -Y "s7comm.param.func == 0x1a || s7comm.param.func == 0x1b"
|
||||
```
|
||||
|
||||
### S7comm PLC stop/start
|
||||
```bash
|
||||
tshark -r capture.pcap -Y "s7comm.param.func == 0x28"
|
||||
```
|
||||
|
||||
## Stuxnet IOC Signatures
|
||||
|
||||
### YARA Rule
|
||||
```yara
|
||||
rule Stuxnet_Driver {
|
||||
meta:
|
||||
description = "Stuxnet rootkit driver"
|
||||
strings:
|
||||
$mrxcls = "mrxcls.sys" ascii
|
||||
$mrxnet = "mrxnet.sys" ascii
|
||||
$mutex = "{A3BD0EA3-CD10-4258-8784-2F53E56E2010}"
|
||||
condition:
|
||||
any of them
|
||||
}
|
||||
```
|
||||
|
||||
### Registry Keys
|
||||
```
|
||||
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\MS-DOS Emulation
|
||||
HKLM\SYSTEM\CurrentControlSet\Services\MRxCls
|
||||
HKLM\SYSTEM\CurrentControlSet\Services\MRxNet
|
||||
```
|
||||
|
||||
## Siemens Step 7 Project Structure
|
||||
|
||||
### Organization Blocks
|
||||
| Block | Purpose |
|
||||
|-------|---------|
|
||||
| OB1 | Main program cycle |
|
||||
| OB35 | 100ms cyclic interrupt |
|
||||
| OB100 | Startup |
|
||||
|
||||
### File Extensions
|
||||
| Extension | Content |
|
||||
|-----------|---------|
|
||||
| `.awl` | Statement List source |
|
||||
| `.mc7` | Compiled machine code |
|
||||
| `.s7p` | Project file |
|
||||
|
||||
## Snort/Suricata Rules for ICS
|
||||
```
|
||||
alert tcp any any -> any 502 (msg:"Modbus Write Multiple Registers";
|
||||
content:"|00 00|"; offset:2; depth:2;
|
||||
byte_test:1,=,16,7; sid:1000001;)
|
||||
```
|
||||
@@ -0,0 +1,180 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Agent for detecting Stuxnet-style ICS/SCADA attacks targeting PLCs."""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
|
||||
|
||||
STUXNET_IOCS = {
|
||||
"file_hashes": [
|
||||
"b4b290906e3a8f1eabbb2b2864e6e7f7",
|
||||
"e757c7e29297b7b7a090695e2de82b4b",
|
||||
],
|
||||
"registry_keys": [
|
||||
r"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\MS-DOS Emulation",
|
||||
r"HKLM\SYSTEM\CurrentControlSet\Services\MRxCls",
|
||||
r"HKLM\SYSTEM\CurrentControlSet\Services\MRxNet",
|
||||
],
|
||||
"mutex_names": [
|
||||
"Global\\{A3BD0EA3-CD10-4258-8784-2F53E56E2010}",
|
||||
],
|
||||
"driver_files": [
|
||||
"mrxcls.sys", "mrxnet.sys",
|
||||
],
|
||||
}
|
||||
|
||||
MODBUS_FUNCTION_CODES = {
|
||||
5: "Write Single Coil",
|
||||
6: "Write Single Register",
|
||||
15: "Write Multiple Coils",
|
||||
16: "Write Multiple Registers",
|
||||
22: "Mask Write Register",
|
||||
23: "Read/Write Multiple Registers",
|
||||
}
|
||||
|
||||
|
||||
def check_plc_communication(pcap_path):
|
||||
"""Analyze PCAP for suspicious Modbus/S7 PLC communication."""
|
||||
findings = []
|
||||
try:
|
||||
result = subprocess.check_output(
|
||||
["tshark", "-r", pcap_path, "-Y", "modbus || s7comm",
|
||||
"-T", "fields", "-e", "ip.src", "-e", "ip.dst",
|
||||
"-e", "modbus.func_code", "-e", "s7comm.param.func",
|
||||
"-e", "frame.time"],
|
||||
text=True, errors="replace", timeout=60
|
||||
)
|
||||
write_count = 0
|
||||
for line in result.strip().splitlines():
|
||||
fields = line.split("\t")
|
||||
if len(fields) >= 3:
|
||||
func_code = fields[2] if fields[2] else None
|
||||
if func_code:
|
||||
try:
|
||||
fc = int(func_code)
|
||||
if fc in MODBUS_FUNCTION_CODES:
|
||||
write_count += 1
|
||||
if write_count <= 20:
|
||||
findings.append({
|
||||
"src": fields[0], "dst": fields[1],
|
||||
"function": MODBUS_FUNCTION_CODES[fc],
|
||||
"func_code": fc,
|
||||
})
|
||||
except ValueError:
|
||||
pass
|
||||
if write_count > 100:
|
||||
findings.append({
|
||||
"alert": f"Excessive PLC write operations: {write_count}",
|
||||
"severity": "CRITICAL",
|
||||
})
|
||||
except (subprocess.SubprocessError, FileNotFoundError):
|
||||
findings.append({"error": "tshark not available or PCAP parse failed"})
|
||||
return findings
|
||||
|
||||
|
||||
def scan_for_rootkit_drivers():
|
||||
"""Check for Stuxnet-style rootkit driver files."""
|
||||
findings = []
|
||||
search_dirs = [r"C:\Windows\System32\drivers", r"C:\Windows\inf"]
|
||||
for d in search_dirs:
|
||||
if not os.path.isdir(d):
|
||||
continue
|
||||
for fname in os.listdir(d):
|
||||
if fname.lower() in [df.lower() for df in STUXNET_IOCS["driver_files"]]:
|
||||
findings.append({
|
||||
"type": "rootkit_driver",
|
||||
"path": os.path.join(d, fname),
|
||||
"severity": "CRITICAL",
|
||||
})
|
||||
return findings
|
||||
|
||||
|
||||
def check_registry_indicators():
|
||||
"""Check Windows registry for Stuxnet IOCs."""
|
||||
findings = []
|
||||
if sys.platform != "win32":
|
||||
return findings
|
||||
for key in STUXNET_IOCS["registry_keys"]:
|
||||
try:
|
||||
result = subprocess.check_output(
|
||||
["reg", "query", key], text=True, errors="replace", timeout=5
|
||||
)
|
||||
if result.strip():
|
||||
findings.append({
|
||||
"type": "registry_ioc",
|
||||
"key": key,
|
||||
"severity": "CRITICAL",
|
||||
})
|
||||
except subprocess.SubprocessError:
|
||||
pass
|
||||
return findings
|
||||
|
||||
|
||||
def analyze_step7_project(project_dir):
|
||||
"""Check Step 7 project files for unauthorized OB modifications."""
|
||||
findings = []
|
||||
if not os.path.isdir(project_dir):
|
||||
return findings
|
||||
for root, _, files in os.walk(project_dir):
|
||||
for f in files:
|
||||
fpath = os.path.join(root, f)
|
||||
if f.lower().startswith("ob") and f.lower().endswith((".awl", ".mc7")):
|
||||
stat = os.stat(fpath)
|
||||
findings.append({
|
||||
"file": fpath,
|
||||
"size": stat.st_size,
|
||||
"modified": datetime.fromtimestamp(stat.st_mtime, tz=timezone.utc).isoformat(),
|
||||
"note": "Organization Block file — verify integrity",
|
||||
})
|
||||
return findings
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Detect Stuxnet-style ICS/SCADA attacks"
|
||||
)
|
||||
parser.add_argument("--pcap", help="PCAP file with ICS network traffic")
|
||||
parser.add_argument("--step7-project", help="Siemens Step 7 project directory")
|
||||
parser.add_argument("--check-host", action="store_true", help="Check host for IOCs")
|
||||
parser.add_argument("--output", "-o", help="Output JSON report")
|
||||
args = parser.parse_args()
|
||||
|
||||
print("[*] Stuxnet-Style ICS Attack Detection Agent")
|
||||
report = {"timestamp": datetime.now(timezone.utc).isoformat(), "findings": {}}
|
||||
|
||||
if args.pcap:
|
||||
plc = check_plc_communication(args.pcap)
|
||||
report["findings"]["plc_traffic"] = plc
|
||||
print(f"[*] PLC traffic findings: {len(plc)}")
|
||||
|
||||
if args.check_host:
|
||||
drivers = scan_for_rootkit_drivers()
|
||||
registry = check_registry_indicators()
|
||||
report["findings"]["rootkit_drivers"] = drivers
|
||||
report["findings"]["registry_iocs"] = registry
|
||||
print(f"[*] Driver IOCs: {len(drivers)}, Registry IOCs: {len(registry)}")
|
||||
|
||||
if args.step7_project:
|
||||
s7 = analyze_step7_project(args.step7_project)
|
||||
report["findings"]["step7_files"] = s7
|
||||
print(f"[*] Step 7 files to verify: {len(s7)}")
|
||||
|
||||
total = sum(len(v) if isinstance(v, list) else 0 for v in report["findings"].values())
|
||||
report["risk_level"] = "CRITICAL" if total >= 3 else "HIGH" if total >= 1 else "LOW"
|
||||
|
||||
if args.output:
|
||||
with open(args.output, "w") as f:
|
||||
json.dump(report, f, indent=2)
|
||||
print(f"[*] Report saved to {args.output}")
|
||||
else:
|
||||
print(json.dumps(report, indent=2))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user