AD Recon — Host Discovery & Enumeration Kill Chain
Architecture
scripts/
├── common_ad.sh # Shared functions (logging, has_tool, phase_done, emit_summary)
└── ad_enum.sh # PHASES 1-2: host discovery + unauthenticated + authenticated enumeration
Each script:
- Accepts
<DC_IP> <DOMAIN> <OUT> [USERNAME] [PASSWORD_OR_HASH] [--phase=N]as args - Uses checkpoints (
.phase_X.done) — re-run safely without repeating completed phases - Emits a JSON summary via
---AD_SUMMARY_JSON---markers for Claude to parse - Handles missing tools gracefully — skips with warning, never crashes
Initial Setup — Gather Required Information
Before running anything, ensure you have:
DC_IP = IP of the Domain Controller (e.g., 192.168.1.10)
DOMAIN = FQDN of the domain (e.g., corp.local)
USERNAME = domain user (optional — Phases 1 and 2 work unauthenticated)
PASSWORD = plaintext password (optional)
NTLM_HASH = LM:NT hash (optional, alternative to password)
If any of these are unknown, ask the user before proceeding.
DC_IP="10.10.10.100"
DOMAIN="corp.local"
USERNAME="" # leave empty for unauthenticated phases
PASSWORD="" # leave empty if using hash
NTLM_HASH="" # format: LM:NT or just :NT
PROJECT=$(echo "$DOMAIN" | sed 's/\./-/g' | tr '[:upper:]' '[:lower:]')
OUT="$(pwd)/$PROJECT"
SCRIPTS="$HOME/.claude/skills/ad-recon/scripts"
mkdir -p "$OUT"/{enum,hashes,bloodhound}
Create progress tasks with TaskCreate:
"PHASE 1 — Host Discovery & Service Scan"
"PHASE 2 — Unauthenticated Enumeration (null sessions, LDAP, kerbrute)"
"PHASE 2auth — Authenticated Enumeration (ldapdomaindump, BloodHound, SPN/AS-REP lists)"
"PHASE 3 — Report & Attack Surface Summary"
Mark each task in_progress when starting, completed when done.
Tool Priority
1. CLI — always first
nmap / rustscan — host and port discovery
enum4linux-ng — SMB/LDAP null session enumeration (preferred over enum4linux)
rpcclient — null session: user/group enumeration
smbclient — null session: share listing
ldapsearch — anonymous LDAP bind, base DN discovery
kerbrute — user enumeration via Kerberos pre-auth (no account needed)
crackmapexec / netexec — credential validation, SMB/LDAP/WinRM enumeration
ldapdomaindump — full LDAP dump (requires valid creds)
bloodhound-python — AD graph data collection (requires valid creds)
impacket-GetNPUsers — identify AS-REP roastable accounts
impacket-GetUserSPNs — identify Kerberoastable SPNs
2. MCPs (when available)
mcp__hexstrike-ai__* — nmap_scan, enum4linux_ng_advanced, netexec_scan, rpcclient_enumeration, nbtscan_netbios
mcp__Notion__* — publish final recon report
3. Manual fallbacks (no tools required)
rpcclient -U "" -N <DC_IP> -c "enumdomusers"
ldapsearch -x -H ldap://<DC_IP> -b "" -s base namingContexts
smbclient -L //<DC_IP> -N
Operational Rules
- Never install tools without explicit permission
- Connectivity first: always verify
ping -c 1 $DC_IPbefore running scripts - Lockout awareness: kerbrute user enumeration does NOT attempt passwords — safe to run
- Password spraying is NOT part of this skill — that belongs in ad-exploitation
- BloodHound collection can be noisy — warn user before running in sensitive environments
- Kerberos time skew: if Kerberos errors occur, sync clock with
sudo ntpdate $DC_IP - Windows commands: PowerShell/net/cmd commands run on Windows targets only — present clearly labeled as "run on target"
PHASE 1 — Host Discovery & Service Scan
bash "$SCRIPTS/ad_enum.sh" "$DC_IP" "$DOMAIN" "$OUT" --phase=1
What it runs:
ping -c 1 $DC_IP— connectivity check- nmap ping sweep of
/24around DC_IP (finds other DCs, servers, workstations) - nmap service scan of DC_IP on AD-critical ports:
53, 88, 135, 139, 389, 445, 464, 593, 636, 1433, 3268, 3269, 3389, 5985, 5986, 9389 - rustscan fast full port scan if available
Read JSON summary. Flag key ports and note potential attack paths:
| Port | Service | Attack implication |
|---|---|---|
| 88 | Kerberos | AS-REP Roasting, Kerberoasting |
| 389/636 | LDAP/LDAPS | enumeration, BloodHound |
| 445 | SMB | null sessions, pass-the-hash, relay |
| 5985/5986 | WinRM | evil-winrm lateral movement |
| 3389 | RDP | xfreerdp/rdesktop |
| 1433 | MSSQL | xp_cmdshell, linked servers |
Output: $OUT/enum/nmap_dc.txt, $OUT/enum/live_hosts.txt
PHASE 2 — Unauthenticated Enumeration
bash "$SCRIPTS/ad_enum.sh" "$DC_IP" "$DOMAIN" "$OUT" --phase=2
What it runs:
Null sessions
enum4linux-ng -A— users, groups, shares, password policy, OS inforpcclient -U "" -N—enumdomusers,enumdomgroups,querydominfosmbclient -L //<DC_IP> -N— list shares- Extract usernames →
$OUT/enum/users_rpcclient.txt
LDAP anonymous bind
ldapsearch -x -H ldap://$DC_IP -b "" -s base namingContexts- Identify base DN, available naming contexts
- Output:
$OUT/enum/ldap_anon.txt
Kerbrute user enumeration
- Searches common SecLists userlist paths automatically
kerbrute userenum -d $DOMAIN --dc $DC_IP <userlist>- Extracts valid usernames →
$OUT/enum/users.txt - Note: this only checks if users exist — no password attempts
Read JSON summary. Report total users found and password policy (lockout threshold matters for Phase 1 of ad-exploitation).
Output: $OUT/enum/users.txt — this file feeds directly into ad-exploitation Phase 1 (AS-REP Roasting).
PHASE 2auth — Authenticated Enumeration
Requires USERNAME + PASSWORD or NTLM_HASH.
bash "$SCRIPTS/ad_enum.sh" "$DC_IP" "$DOMAIN" "$OUT" "$USERNAME" "$PASSWORD" --phase=2auth
# OR with hash:
bash "$SCRIPTS/ad_enum.sh" "$DC_IP" "$DOMAIN" "$OUT" "$USERNAME" "$NTLM_HASH" --phase=2auth
What it runs:
Credential validation
- crackmapexec/netexec:
smb $DC_IP -u $USERNAME -p $PASSWORD - Confirms creds are valid before proceeding
Full LDAP data collection
ldapdomaindump— dumps all users, groups, computers, GPOs, trusts to$OUT/enum/ldap/- Key files:
domain_users.html,domain_groups.html,domain_computers.html,domain_trusts.html
BloodHound data collection
bloodhound-python -d $DOMAIN -u $USERNAME -p $PASSWORD -dc $DC_IP -c All --zip- Output:
$OUT/bloodhound/*.zip— import into BloodHound GUI for attack path analysis - If bloodhound-python not available → suggest SharpHound.exe on Windows target
Attack candidate identification
impacket-GetNPUsers— accounts withUF_DONT_REQUIRE_PREAUTH(AS-REP roastable) →$OUT/hashes/asrep_hashes.txtimpacket-GetUserSPNs— accounts with SPNs (Kerberoastable) →$OUT/hashes/kerberoast_hashes.txt
Read JSON summary. Flag:
- Number of AS-REP roastable accounts (exploitable without knowing any password)
- Number of Kerberoastable SPNs
- BloodHound zip ready for import
PHASE 3 — Report & Attack Surface Summary
Consolidate all output into a structured report:
## AD RECON REPORT — [DOMAIN] — [DATE]
## DC: $DC_IP | Output: $OUT
### Environment
- Domain FQDN: [domain]
- DC IP: [ip]
- Additional DCs/servers found: [list from nmap sweep]
- Trust relationships: [from ldapdomaindump/enum4linux]
### Attack Surface
- Users enumerated: [count] → $OUT/enum/users.txt
- Password policy: [lockout threshold, min length, duration]
- Accessible shares (null session): [list]
- SMB signing: [enabled/disabled — disabled = relay attack possible]
### Exploitation Candidates (hand off to ad-exploitation)
1. [CRITICAL] AS-REP roastable accounts: [count] — no creds required
2. [HIGH] Kerberoastable SPNs: [count, accounts]
3. [HIGH] BloodHound data collected → import and run: Shortest Path to Domain Admins
4. [MEDIUM] Null session access — password policy retrieved (lockout: [N] attempts)
5. [INFO] Open ports suggesting attack paths: [list]
### Next Step
Load ad-exploitation skill with:
DC_IP="$DC_IP"
DOMAIN="$DOMAIN"
RECON_OUT="$OUT"
USERNAME="<user if any found/known>"
If Notion MCP is available, publish with mcp__Notion__notion-create-pages.
Evidence Capture
Save evidence from each recon phase to $OUT/evidence/. Essential for documenting the attack surface found.
mkdir -p "$OUT/evidence"
# Terminal screenshot (macOS)
screencapture -x "$OUT/evidence/recon_$(date +%Y%m%d_%H%M%S)_$DESCRIPTION.png"
# Terminal screenshot (Linux)
scrot "$OUT/evidence/recon_$(date +%Y%m%d_%H%M%S)_$DESCRIPTION.png"
What to capture per phase:
- Phase 1 (Host Discovery): nmap output with open ports on DC + live host list
- Phase 2 (Unauth Enum): enum4linux-ng output (shares, users, password policy) + rpcclient user list
- Phase 2auth (Auth Enum): ldapdomaindump — open HTML in browser and screenshot
domain_users.html+domain_computers.html; BloodHound — capture "Shortest Paths to Domain Admins" graph before closing the GUI
BloodHound GUI:
1. Import $OUT/bloodhound/*.zip
2. Click "Shortest Paths to Domain Admins"
3. Right-click the graph → Export → save as $OUT/evidence/bloodhound_path_to_DA.png
Submit to Notion:
mcp__Notion__notion-create-pages — create AD recon page with attack surface
mcp__Notion__notion-update-page — attach nmap output, user list, BloodHound screenshot
MCP Integration (when available)
hexstrike-ai / Kali MCP (mcp__hexstrike-ai__*)
Use for: nmap_scan, nmap_advanced_scan, enum4linux_ng_advanced, netexec_scan,
rpcclient_enumeration, nbtscan_netbios, smbmap_scan.
Notion (mcp__Notion__*)
Publish recon report. Create a subpage for exploitation candidates.
Execution Modes
| Mode | When to use | What runs |
|---|---|---|
--quick |
Fast initial footprint | Phase 1 + Phase 2 (unauthenticated only) |
--full |
Full recon | Phases 1 + 2 + 2auth |
--unauth |
No credentials — OSINT only | Phases 1 + 2 only |
--authenticated |
Already have creds | Phase 2auth only |
Operational Notes
- Output linkage:
$OUT/enum/users.txtand$OUT/hashes/asrep_hashes.txtfeed directly into ad-exploitation — pointRECON_OUT="$OUT"when loading that skill - BloodHound import: after collection, open BloodHound GUI → Database Info → Upload Data → select
$OUT/bloodhound/*.zip - Token efficiency: scripts emit only JSON summaries — do not read full tool output into Claude context
- Kerberos clock skew: if impacket errors with
KRB_AP_ERR_SKEW, runsudo ntpdate $DC_IP