mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-31 00:17:41 +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,69 @@
|
||||
# API Reference: Wireless Network Penetration Testing Agent
|
||||
|
||||
## Overview
|
||||
|
||||
Tests WiFi security: scans access points via beacon capture, detects rogue APs and evil twins, identifies weak encryption, captures WPA2 handshakes, and analyzes client probe requests. For authorized testing only.
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Package | Version | Purpose |
|
||||
|---------|---------|---------|
|
||||
| scapy | >=2.5 | Beacon/probe capture, deauth frames |
|
||||
| aircrack-ng | >=1.7 | Handshake capture and cracking (subprocess) |
|
||||
|
||||
## CLI Usage
|
||||
|
||||
```bash
|
||||
# Enable monitor mode first
|
||||
sudo airmon-ng start wlan0
|
||||
|
||||
# Run wireless pentest
|
||||
python agent.py --interface wlan0mon --duration 60 \
|
||||
--known-ssids "CorpWiFi" "GuestWiFi" \
|
||||
--known-bssids "AA:BB:CC:DD:EE:FF" --output report.json
|
||||
```
|
||||
|
||||
## Key Functions
|
||||
|
||||
### `scan_access_points(interface, duration)`
|
||||
Captures Dot11Beacon frames to discover APs with SSID, BSSID, channel, and crypto type.
|
||||
|
||||
### `detect_rogue_aps(discovered_aps, known_ssids, known_bssids)`
|
||||
Compares discovered APs against known infrastructure to detect evil twin attacks.
|
||||
|
||||
### `detect_weak_encryption(access_points)`
|
||||
Flags open networks, WEP, and WPA1-only configurations as weak.
|
||||
|
||||
### `capture_handshake(interface, target_bssid, channel, output_file, duration)`
|
||||
Uses airodump-ng to capture the WPA2 4-way handshake.
|
||||
|
||||
### `send_deauth(interface, target_bssid, client_mac, count)`
|
||||
Sends deauthentication frames via Scapy to force client reconnection.
|
||||
|
||||
### `crack_handshake(cap_file, wordlist)`
|
||||
Attempts dictionary attack on captured handshake using aircrack-ng.
|
||||
|
||||
### `detect_client_probes(interface, duration)`
|
||||
Captures Dot11ProbeReq frames to identify SSIDs clients are seeking.
|
||||
|
||||
### `check_wps_enabled(interface, target_bssid)`
|
||||
Uses wash to detect WPS-enabled access points vulnerable to Reaver attacks.
|
||||
|
||||
## Scapy 802.11 Layers Used
|
||||
|
||||
| Layer | Purpose |
|
||||
|-------|---------|
|
||||
| `Dot11Beacon` | Access point beacon frames |
|
||||
| `Dot11ProbeReq` | Client probe request frames |
|
||||
| `Dot11Auth` | Deauthentication frames |
|
||||
| `Dot11Elt` | Information elements (SSID, rates) |
|
||||
| `RadioTap` | Radio layer metadata |
|
||||
|
||||
## External Tools Used
|
||||
|
||||
| Tool | Purpose |
|
||||
|------|---------|
|
||||
| airmon-ng | Enable monitor mode |
|
||||
| airodump-ng | Capture handshakes |
|
||||
| aircrack-ng | Crack WPA2 PSK |
|
||||
| wash | Detect WPS-enabled APs |
|
||||
@@ -0,0 +1,183 @@
|
||||
#!/usr/bin/env python3
|
||||
# For authorized penetration testing and lab environments only
|
||||
"""Wireless Network Penetration Testing Agent - Tests WiFi security using Scapy and aircrack-ng."""
|
||||
|
||||
import json
|
||||
import logging
|
||||
import argparse
|
||||
import subprocess
|
||||
from datetime import datetime
|
||||
|
||||
from scapy.all import (
|
||||
Dot11, Dot11Beacon, Dot11Elt, Dot11ProbeReq, Dot11Auth,
|
||||
sniff, RadioTap, sendp, conf,
|
||||
)
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def scan_access_points(interface, duration=30):
|
||||
"""Scan for WiFi access points by capturing beacon frames."""
|
||||
access_points = {}
|
||||
|
||||
def beacon_handler(pkt):
|
||||
if pkt.haslayer(Dot11Beacon):
|
||||
bssid = pkt[Dot11].addr2
|
||||
if bssid not in access_points:
|
||||
ssid = pkt[Dot11Elt].info.decode("utf-8", errors="ignore")
|
||||
stats = pkt[Dot11Beacon].network_stats()
|
||||
access_points[bssid] = {
|
||||
"ssid": ssid,
|
||||
"bssid": bssid,
|
||||
"channel": stats.get("channel", 0),
|
||||
"crypto": list(stats.get("crypto", set())),
|
||||
"signal": pkt.dBm_AntSignal if hasattr(pkt, "dBm_AntSignal") else None,
|
||||
}
|
||||
|
||||
logger.info("Scanning for access points on %s for %ds", interface, duration)
|
||||
sniff(iface=interface, prn=beacon_handler, timeout=duration, store=False)
|
||||
logger.info("Discovered %d access points", len(access_points))
|
||||
return list(access_points.values())
|
||||
|
||||
|
||||
def detect_rogue_aps(discovered_aps, known_ssids, known_bssids):
|
||||
"""Detect rogue access points by comparing against known infrastructure."""
|
||||
rogues = []
|
||||
for ap in discovered_aps:
|
||||
if ap["ssid"] in known_ssids and ap["bssid"] not in known_bssids:
|
||||
ap["rogue_reason"] = "Known SSID with unknown BSSID (potential evil twin)"
|
||||
rogues.append(ap)
|
||||
logger.warning("ROGUE AP detected: SSID=%s BSSID=%s", ap["ssid"], ap["bssid"])
|
||||
return rogues
|
||||
|
||||
|
||||
def detect_weak_encryption(access_points):
|
||||
"""Identify access points using weak or no encryption."""
|
||||
weak = []
|
||||
for ap in access_points:
|
||||
crypto = ap.get("crypto", [])
|
||||
if not crypto or "OPN" in crypto:
|
||||
ap["weakness"] = "Open network - no encryption"
|
||||
weak.append(ap)
|
||||
elif "WEP" in str(crypto):
|
||||
ap["weakness"] = "WEP encryption - trivially crackable"
|
||||
weak.append(ap)
|
||||
elif "WPA" in str(crypto) and "WPA2" not in str(crypto):
|
||||
ap["weakness"] = "WPA1 only - vulnerable to TKIP attacks"
|
||||
weak.append(ap)
|
||||
logger.info("Found %d APs with weak encryption", len(weak))
|
||||
return weak
|
||||
|
||||
|
||||
def capture_handshake(interface, target_bssid, channel, output_file, duration=60):
|
||||
"""Capture WPA2 4-way handshake using airodump-ng."""
|
||||
set_channel_cmd = ["iwconfig", interface, "channel", str(channel)]
|
||||
subprocess.run(set_channel_cmd, capture_output=True)
|
||||
|
||||
cmd = [
|
||||
"airodump-ng", "--bssid", target_bssid, "--channel", str(channel),
|
||||
"--write", output_file, "--output-format", "pcap",
|
||||
interface,
|
||||
]
|
||||
logger.info("Capturing handshake for %s on channel %d", target_bssid, channel)
|
||||
try:
|
||||
subprocess.run(cmd, timeout=duration, capture_output=True)
|
||||
except subprocess.TimeoutExpired:
|
||||
pass
|
||||
return f"{output_file}-01.cap"
|
||||
|
||||
|
||||
def send_deauth(interface, target_bssid, client_mac="FF:FF:FF:FF:FF:FF", count=5):
|
||||
"""Send deauthentication frames to force client reconnection for handshake capture."""
|
||||
dot11 = Dot11(addr1=client_mac, addr2=target_bssid, addr3=target_bssid)
|
||||
frame = RadioTap() / dot11 / Dot11Auth(algo=0, seqnum=1, status=0)
|
||||
sendp(frame, iface=interface, count=count, inter=0.1, verbose=False)
|
||||
logger.info("Sent %d deauth frames to %s (client: %s)", count, target_bssid, client_mac)
|
||||
|
||||
|
||||
def crack_handshake(cap_file, wordlist):
|
||||
"""Attempt to crack WPA2 handshake using aircrack-ng."""
|
||||
cmd = ["aircrack-ng", "-w", wordlist, "-b", "target_bssid", cap_file]
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=3600)
|
||||
if "KEY FOUND" in result.stdout:
|
||||
key_line = [l for l in result.stdout.split("\n") if "KEY FOUND" in l]
|
||||
if key_line:
|
||||
logger.info("WPA2 key cracked: %s", key_line[0])
|
||||
return {"cracked": True, "key": key_line[0]}
|
||||
return {"cracked": False}
|
||||
|
||||
|
||||
def detect_client_probes(interface, duration=30):
|
||||
"""Capture probe requests to identify client-side vulnerabilities."""
|
||||
probes = []
|
||||
|
||||
def probe_handler(pkt):
|
||||
if pkt.haslayer(Dot11ProbeReq):
|
||||
ssid = pkt[Dot11Elt].info.decode("utf-8", errors="ignore") if pkt.haslayer(Dot11Elt) else ""
|
||||
if ssid:
|
||||
probes.append({
|
||||
"client_mac": pkt[Dot11].addr2,
|
||||
"probed_ssid": ssid,
|
||||
})
|
||||
|
||||
sniff(iface=interface, prn=probe_handler, timeout=duration, store=False)
|
||||
unique_clients = len(set(p["client_mac"] for p in probes))
|
||||
logger.info("Captured %d probe requests from %d clients", len(probes), unique_clients)
|
||||
return probes
|
||||
|
||||
|
||||
def check_wps_enabled(interface, target_bssid):
|
||||
"""Check if WPS is enabled on target AP using wash."""
|
||||
cmd = ["wash", "-i", interface, "-C"]
|
||||
try:
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
|
||||
if target_bssid.upper() in result.stdout.upper():
|
||||
logger.warning("WPS enabled on %s - vulnerable to Reaver attack", target_bssid)
|
||||
return True
|
||||
except (subprocess.TimeoutExpired, FileNotFoundError):
|
||||
pass
|
||||
return False
|
||||
|
||||
|
||||
def generate_report(access_points, rogues, weak_crypto, client_probes):
|
||||
"""Generate wireless penetration test report."""
|
||||
report = {
|
||||
"timestamp": datetime.utcnow().isoformat(),
|
||||
"access_points": access_points,
|
||||
"rogue_aps": rogues,
|
||||
"weak_encryption": weak_crypto,
|
||||
"client_probes": client_probes[:50],
|
||||
"summary": {
|
||||
"total_aps": len(access_points),
|
||||
"rogue_aps": len(rogues),
|
||||
"weak_crypto_aps": len(weak_crypto),
|
||||
"clients_probing": len(set(p["client_mac"] for p in client_probes)),
|
||||
},
|
||||
}
|
||||
print(f"WIRELESS PENTEST REPORT: {len(access_points)} APs, {len(rogues)} rogues, {len(weak_crypto)} weak")
|
||||
return report
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Wireless Network Penetration Testing Agent")
|
||||
parser.add_argument("--interface", required=True, help="Wireless interface in monitor mode")
|
||||
parser.add_argument("--duration", type=int, default=30, help="Scan duration in seconds")
|
||||
parser.add_argument("--known-ssids", nargs="*", default=[], help="Known legitimate SSIDs")
|
||||
parser.add_argument("--known-bssids", nargs="*", default=[], help="Known legitimate BSSIDs")
|
||||
parser.add_argument("--output", default="wireless_pentest_report.json")
|
||||
args = parser.parse_args()
|
||||
|
||||
aps = scan_access_points(args.interface, args.duration)
|
||||
rogues = detect_rogue_aps(aps, set(args.known_ssids), set(args.known_bssids))
|
||||
weak = detect_weak_encryption(aps)
|
||||
probes = detect_client_probes(args.interface, args.duration)
|
||||
|
||||
report = generate_report(aps, rogues, weak, probes)
|
||||
with open(args.output, "w") as f:
|
||||
json.dump(report, f, indent=2)
|
||||
logger.info("Report saved to %s", args.output)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user