OSCP Reference

9.6.1 Active Directory Domain Mapping

← Stage index | LDAP/Kerberos baseline | AD cheatsheet | Master Notes | Strategy map | Study methods: Map Active Directory attack paths

Prerequisite: one authorized domain identity and a route to the required DC/hosts. Record the source host, exact identity, domain FQDN, DNS server, DC FQDN/IP and time state before interpreting failures.

Coverage: mapping only. SPNs, ACLs, sessions and credentials are candidate transitions; ticket requests, directory changes, credential access and remote execution belong to the later Stage 06 procedures.

Exit: produce a ranked, manually checked map in the form CONTROLLED IDENTITY → EFFECTIVE RELATIONSHIP → OBJECT/HOST → REACHABLE SERVICE → POSSIBLE NEW ACCESS.

9.6.1.1 AD capability transitions

AD capability transitions

Open scalable SVG | Open PNG

9.6.1.2 Keep four maps, not one tool output

IDENTITY MAP: USER/COMPUTER -> DIRECT + NESTED GROUPS -> DIRECTORY RIGHTS
HOST MAP:     COMPUTER -> OS/ROLE -> LOCAL/REMOTE-ACCESS RIGHTS -> SESSIONS
ROUTE MAP:    SOURCE -> DNS/KDC/DC/HOST -> REQUIRED PORT/SERVICE
LEAD MAP:     EVIDENCE -> HYPOTHESIS -> MINIMUM VALIDATION -> NEXT BLOCK

Authentication, authorization, reachability and session presence are independent. A valid LDAP bind does not prove share access; SMB administration on one host does not prove directory privilege; a session edge does not prove retrievable credentials.

9.6.1.3 Establish identity, domain, DC, DNS and time

9.6.1.3.1 Domain-joined Windows source

whoami /all
echo %USERDNSDOMAIN%
echo %USERDOMAIN%
echo %LOGONSERVER%
nltest /dsgetdc:DOMAIN
nltest /dclist:DOMAIN
w32tm /query /status
[System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
Resolve-DnsName -Type SRV _ldap._tcp.dc._msdcs.DOMAIN
Resolve-DnsName -Type SRV _kerberos._tcp.DOMAIN

Decisive output: domain FQDN, DC FQDN/IP, current user SID/groups, DNS SRV answers and a plausible time source. USERDOMAIN can be a NetBIOS label; prefer the DNS domain for LDAP/Kerberos.

9.6.1.3.2 Kali/off-domain source

dig +short SRV _ldap._tcp.dc._msdcs.DOMAIN @DC_IP
dig +short SRV _kerberos._tcp.DOMAIN @DC_IP
nxc smb DC_IP -d DOMAIN -u USER -p 'PASSWORD'
ldapsearch -x -LLL -H ldap://DC_HOST:389 -s base -b '' \
  defaultNamingContext configurationNamingContext rootDomainNamingContext dnsHostName

RootDSE is a directory-server metadata object. Reading it can reveal naming contexts even when anonymous subtree searches are denied. Convert corp.example to DC=corp,DC=example; do not guess the base DN when RootDSE can supply it.

9.6.1.3.2.1 Remote Windows session and double-hop caveat
whoami /all
klist
dir \\DC_HOST\SYSVOL

A supplied credential may create the remote session without being delegated onward to the DC. If local identity commands work but access to a second host fails, distinguish a WinRM/PowerShell remoting credential-delegation problem from invalid credentials. An interactive RDP session, explicit credentials, /netonly network credentials or an off-domain LDAP client may create a different context; always record which identity is used locally and over the network.

9.6.1.4 Find domain identities and relationships with built-in utilities Native Windows baseline

Windows context: native commands first; RSAT only when installed.
net user /domain
net user USER /domain
net group /domain
net group "Domain Admins" /domain
net group "GROUP" /domain
net accounts /domain
nltest /domain_trusts /all_trusts
net view /domain
net view \\DC_HOST

These commands are broadly available but provide partial views. Expand interesting users and groups individually, trace nested groups rather than assuming memberOf is complete, and retain SIDs when names can collide across domains.

9.6.1.4.1 RSAT ActiveDirectory module, only when installed
Get-Command -Module ActiveDirectory
Get-ADDomain
Get-ADForest
Get-ADDomainController -Filter *
Get-ADUser -Filter * -Properties Enabled,Description,MemberOf,ServicePrincipalName,UserPrincipalName,PasswordLastSet,LastLogonDate,AdminCount
Get-ADGroup -Filter * -Properties GroupScope,GroupCategory,Members,Description
Get-ADGroupMember -Identity 'GROUP' -Recursive
Get-ADComputer -Filter * -Properties DNSHostName,OperatingSystem,OperatingSystemVersion,ServicePrincipalName,TrustedForDelegation,LastLogonDate
Get-ADTrust -Filter *

Get-AD* cmdlets require the RSAT ActiveDirectory module. Its absence on a client is normal; use ADSI, LDAP, PowerView or an off-domain client.

9.6.1.5 Query domain objects when the RSAT module is unavailable Built-in ADSI/DirectorySearcher fallback

Windows/.NET directory queries without RSAT; use the current network identity and correct base.

For automatic, explicitly scoped inventory, run the AD surface helpers with an explicit DC/domain. Collection runs by default, prints a bounded findings summary and saves a unique private evidence directory; -Preview displays checks without connecting. The helper preserves query failures, candidate clues, account-context limits and linked manual-validation handoffs without requesting roast material or changing directory objects.

For repeated queries, define LDAPSearch once inline, then use its purpose-labelled calls. The transparent one-off procedure below remains useful when no helper is loaded.

$root = [ADSI]'LDAP://RootDSE'
$base = [ADSI]("LDAP://" + $root.defaultNamingContext)
$searcher = New-Object System.DirectoryServices.DirectorySearcher($base)
$searcher.PageSize = 1000
$searcher.PropertiesToLoad.AddRange(@('samaccountname','userprincipalname','objectsid','memberof','serviceprincipalname','description','useraccountcontrol','pwdlastset','lastlogontimestamp'))
$searcher.Filter = '(&(objectCategory=person)(objectClass=user))'
$searcher.FindAll() | ForEach-Object { $_.Properties }

Change only the filter and requested attributes for another object class:

9.6.1.5.1 Groups

# Groups
$searcher.Filter = '(objectCategory=group)'
$searcher.PropertiesToLoad.Clear()
$searcher.PropertiesToLoad.AddRange(@('samaccountname','objectsid','member','grouptype','description'))
$searcher.FindAll() | ForEach-Object { $_.Properties }

9.6.1.5.2 Computers

# Computers
$searcher.Filter = '(objectCategory=computer)'
$searcher.PropertiesToLoad.Clear()
$searcher.PropertiesToLoad.AddRange(@('dnshostname','operatingsystem','operatingsystemversion','serviceprincipalname','useraccountcontrol','lastlogontimestamp'))
$searcher.FindAll() | ForEach-Object { $_.Properties }

PageSize = 1000 asks for paged results; without paging, the server's result-size limit can silently produce an incomplete inventory. LDAP filters are data selection, not proof of access or exploitability.

9.6.1.6 Find useful directory objects using your domain credentials Authenticated LDAP from Kali

Directory connectivity and a supported authenticated query context; check base, filter and paging.

9.6.1.6.1 Discover the naming context

ldapsearch -x -LLL -H ldap://DC_HOST:389 -s base -b '' \
  defaultNamingContext configurationNamingContext rootDomainNamingContext dnsHostName

9.6.1.6.2 Identify domain principals and their memberships Users, groups and computers

ldapsearch -x -LLL -H ldap://DC_HOST:389 -D 'USER@DOMAIN' -W \
  -E pr=1000/noprompt -b 'DC=DOMAIN,DC=TLD' \
  '(&(objectCategory=person)(objectClass=user))' \
  sAMAccountName userPrincipalName objectSid userAccountControl memberOf description servicePrincipalName pwdLastSet lastLogonTimestamp adminCount
ldapsearch -x -LLL -H ldap://DC_HOST:389 -D 'USER@DOMAIN' -W \
  -E pr=1000/noprompt -b 'DC=DOMAIN,DC=TLD' \
  '(objectCategory=group)' sAMAccountName objectSid member groupType description
ldapsearch -x -LLL -H ldap://DC_HOST:389 -D 'USER@DOMAIN' -W \
  -E pr=1000/noprompt -b 'DC=DOMAIN,DC=TLD' \
  '(objectCategory=computer)' dNSHostName operatingSystem operatingSystemVersion servicePrincipalName userAccountControl lastLogonTimestamp
9.6.1.6.2.1 SPNs, trusts and GPO/OU context
# SPN-bearing accounts: mapping only; do not request tickets in this block.
ldapsearch -x -LLL -H ldap://DC_HOST:389 -D 'USER@DOMAIN' -W \
  -E pr=1000/noprompt -b 'DC=DOMAIN,DC=TLD' \
  '(&(objectCategory=person)(objectClass=user)(servicePrincipalName=*))' \
  sAMAccountName servicePrincipalName memberOf userAccountControl pwdLastSet
# Trusted-domain objects
ldapsearch -x -LLL -H ldap://DC_HOST:389 -D 'USER@DOMAIN' -W \
  -b 'DC=DOMAIN,DC=TLD' '(objectClass=trustedDomain)' \
  cn securityIdentifier trustDirection trustType trustAttributes
# OUs and GPO containers; correlate links before inferring host effect.
ldapsearch -x -LLL -H ldap://DC_HOST:389 -D 'USER@DOMAIN' -W \
  -E pr=1000/noprompt -b 'DC=DOMAIN,DC=TLD' \
  '(|(objectClass=organizationalUnit)(objectClass=groupPolicyContainer))' \
  distinguishedName displayName name gPLink gPOptions

9.6.1.6.3 LDAP failure router

ResultInterpretationNext action
Invalid credentials (49)Bind identity/secret/context failed; subcodes may refine the causeRecheck UPN vs DOMAIN\USER, account state and exact secret; do not infer authorization
Strong(er) authentication required / confidentiality requiredServer policy rejects that bind/transportUse the permitted LDAPS/StartTLS or Kerberos/SASL path; do not disable protections
Size limit exceeded or suspiciously round countSearch is incompleteAdd paged results and narrow the base/filter
Referral/partial resultsSearch crossed a naming-context boundaryQuery the referred domain/partition or compatible Global Catalog deliberately
Bind succeeds, search emptyWrong base/filter, ACL filtering or genuinely no matchesVerify RootDSE base, test a known object and request fewer attributes
Works by IP, Kerberos failsRoute exists but name/SPN/DNS/time path is wrongUse DC FQDN, AD DNS, correct realm and synchronized time

9.6.1.7 Investigate domain objects and rights with PowerView PowerView: convenient manual breadth

Reviewed compatible PowerView loaded in the intended directory authentication context.
Import-Module .\PowerView.ps1
Get-Command -Module PowerView
Get-Domain
Get-DomainController
Get-DomainTrust
Get-DomainUser | Select-Object samaccountname,userprincipalname,description,memberof,serviceprincipalname
Get-DomainGroup
Get-DomainGroupMember -Identity 'GROUP' -Recurse
Get-DomainComputer | Select-Object dnshostname,operatingsystem,operatingsystemversion
Get-DomainUser -SPN | Select-Object samaccountname,serviceprincipalname,memberof

The original PowerSploit repository is archived. Course examples and forks may use legacy aliases such as Get-NetUser, Get-NetGroup, Get-NetComputer or Get-NetDomainTrust. Inspect Get-Command/Get-Help for the exact copy present rather than mixing generations.

9.6.1.8 Find readable domain files and configuration leads Shares, SYSVOL and NETLOGON

9.6.1.8.1 Inventory, then test the object

net view \\DC_HOST
dir \\DC_HOST\SYSVOL
dir \\DC_HOST\NETLOGON
nxc smb DC_IP -d DOMAIN -u USER -p 'PASSWORD' --shares
smbclient -L //DC_IP -U 'DOMAIN/USER'
smbclient //DC_IP/SYSVOL -U 'DOMAIN/USER' -c 'recurse ON; ls'
smbclient //DC_IP/SHARE -U 'DOMAIN/USER'

Inside smbclient, use ls, cd, get FILE and a harmless approved put only when write validation is needed. Share listing, share connection, file read and file write are separate permissions.

Inspect authorized readable policy/logon/deployment paths for scripts, configurations, backups, connection strings and legacy Group Policy Preferences XML containing cpassword. Selectively retrieve relevant files; do not bulk-copy a share merely because it is readable. A discovered secret returns to the credential-classification procedure.

9.6.1.9 Find service identities worth investigating Service accounts and SPNs

setspn -Q */*
setspn -L ACCOUNT
Get-DomainUser -SPN | Select-Object samaccountname,serviceprincipalname,memberof,useraccountcontrol,pwdlastset

Record account → service class/host/port → groups → password age/encryption/delegation clues → reachable service. An SPN means the account represents a Kerberos service identity; it does not mean the password is weak, the service is reachable or the account is privileged. Ticket acquisition/cracking is Block 11.

9.6.1.10 Identify directory objects you can control Directory ACLs and effective control

Get-DomainObjectAcl -Identity TARGET_OBJECT -ResolveGUIDs |
  Where-Object { $_.ActiveDirectoryRights -match 'GenericAll|GenericWrite|WriteDacl|WriteOwner|ExtendedRight|WriteProperty|Self' } |
  Select-Object ObjectDN,SecurityIdentifier,ActiveDirectoryRights,ObjectAceType,AceType,IsInherited,InheritanceType

PowerView normally exposes the trustee as SecurityIdentifier. Resolve that SID and trace controlled direct/nested membership. -ResolveGUIDs resolves operation GUIDs; it does not make every trustee a friendly account name. A blank projected column can mean the selected property is absent, not that an ACE has no trustee.

9.6.1.10.1 Compatible copy that actually emits IdentityReference

Use this projection only when inspecting the returned object confirms that the loaded implementation provides IdentityReference.

Get-DomainObjectAcl -Identity TARGET_OBJECT -ResolveGUIDs |
  Where-Object { $_.ActiveDirectoryRights -match 'GenericAll|GenericWrite|WriteDacl|WriteOwner|ExtendedRight|WriteProperty|Self' } |
  Select-Object ObjectDN,IdentityReference,ActiveDirectoryRights,ObjectAceType,AceType,IsInherited,InheritanceType

If the value is an unresolved SID, resolve it before applying the rule to a controlled principal.

Candidate rightPossible transition to validate laterMissing proof now
GenericAllBroad object modificationControlled trustee, target object class, applicable deny/inheritance and useful change
GenericWrite / WritePropertyChange one or more writable attributesExact attribute/object GUID and a transition that consumes it
WriteOwnerBecome ownerAbility to change the DACL afterward and use the resulting right
WriteDaclAdd an ACEEffective write-DACL right, planned narrow ACE and restoration
AllExtendedRights / ForceChangePasswordExtended operation such as reset where applicableObject class, exact extended right and downstream usefulness
Self / validated writeAdd self/member or another validated attribute where schema permitsCorrect validated-write GUID and target type
GPO/OU controlAffect linked computers/usersWritable GPO component, effective link/scope, refresh/trigger and target placement

An ACE is one rule. Effective access depends on trustee/group nesting, allow/deny semantics, inheritance, object-specific GUIDs and security descriptor scope. Do not perform the modification in this mapping block.

9.6.1.11 Find hosts where your identity may have useful rights Host-access candidates

Find-LocalAdminAccess
nxc smb TARGET -d DOMAIN -u USER -p 'PASSWORD'
nxc smb TARGET -d DOMAIN -u USER -p 'PASSWORD' --shares

Find-LocalAdminAccess is a broad candidate generator and can be noisy or blocked by firewall/RPC controls. Validate a selected host with the service you may actually use. NetExec's (Pwn3d!) indicates administrative SMB context according to that tool; it does not establish RDP, WinRM, WMI/DCOM or directory rights. RDP, WinRM, SMB/service control and WMI/DCOM each have different ports, services, policies and authorization.

9.6.1.12 Identify useful logged-on identities and verify the session evidence Sessions are volatile hints

Get-NetSession -ComputerName COMPUTER -Verbose
Get-NetLoggedon -ComputerName COMPUTER
PsLoggedOn.exe \\COMPUTER

Get-NetSession relies on workstation/session enumeration APIs that modern Windows may restrict. PsLoggedOn combines Registry profile evidence with NetSessionEnum; remote Registry access and sufficient rights are relevant, and querying can itself create a network-session entry. Therefore:

9.6.1.13 Find and validate a useful domain attack path BloodHound: collect narrowly, rank, then validate

9.6.1.13.1 Current SharpHound CE

Low-noise directory baseline that avoids contacting every workstation:

.\SharpHound.exe --CollectionMethods DCOnly --OutputDirectory .\bh --ZipFileName domain-dconly.zip

Add host facts only when they can answer the next question:

.\SharpHound.exe --CollectionMethods LocalGroup --ComputerFile .\candidate-hosts.txt --OutputDirectory .\bh --ZipFileName candidate-localgroups.zip
.\SharpHound.exe --CollectionMethods Session --ComputerFile .\candidate-hosts.txt --Loop --LoopDuration 00:10:00 --OutputDirectory .\bh --ZipFileName candidate-sessions.zip

SharpHound with no collection flag uses its broader default, including directory data plus local-group/session attempts. All performs every supported method; it is not the first response to an unanswered narrow question. Import the output ZIP into a compatible BloodHound CE deployment and verify node/edge counts and ingestion errors.

9.6.1.13.1.1 Collector variants and compatibility
# Inspect the actual collector before using copied syntax.
.\SharpHound.exe --help

For the current Kali CE collector, use the noninteractive directory-first command below. Legacy bloodhound-python is not its CE command/schema.

# Legacy/course PowerShell collector; use only with a compatible legacy deployment.
Import-Module .\SharpHound.ps1
Invoke-BloodHound -CollectionMethod All -OutputDirectory .\bh -ZipFileName legacy.zip

Use the collector version intended for the BloodHound deployment. bloodhound-python, legacy SharpHound PowerShell and current SharpHound CE are alternatives with different schemas/features, not interchangeable command spellings.

9.6.1.13.2 Noninteractive Kali first pass

Use one valid domain identity and scoped DC/SMB connectivity. Start in a fresh private directory so graph output and reports do not mix identities. DOMAIN is the DNS domain; DOMAIN_NETBIOS is its short name, DC_HOST the DC FQDN, and TARGET one approved SMB host. No menu input is required.

mkdir -p ~/oscp/work/TARGET/evidence/ad-first-pass
cd ~/oscp/work/TARGET/evidence/ad-first-pass
bloodhound-ce-python -d DOMAIN -u USER -p 'PASSWORD' -dc DC_HOST -ns DC_IP -c DCOnly --disable-autogc --zip
ldapdomaindump -u 'DOMAIN_NETBIOS\USER' -p 'PASSWORD' -o ldap-inventory ldap://DC_IP
bloodyAD --host DC_HOST --dc-ip DC_IP -d DOMAIN -u USER -p 'PASSWORD' get writable --detail --partition DOMAIN > writable.txt
nxc smb TARGET -d DOMAIN -u USER -p 'PASSWORD' --shares --no-admin-check --log shares.log

Choose: the graph covers groups, trusts, object properties, ACLs and containers; ldapdomaindump adds readable inventory; bloodyAD reports domain-partition effective writable attributes/security descriptors/child classes; NetExec checks the selected host's shares. Skip redundant inventory when the graph already answers the question.

Version gate: the NetExec line requires help documenting --file-write-check (leave it off) and --no-admin-check. Its default opens existing share roots with access masks, without creating files. The latter skips SCM administration probing. The bloodyAD line requires --partition support. Local tool databases, arguments and output contain private information.

Interpret: DCOnly bypasses member-computer enumeration, not all DC/GC/DNS discovery. LDAP inventory can follow referrals. A writable-rights result is not a write; an SMB access-mask result is not proof of actual file creation. No remote command, password change, LDAP modification, certificate enrollment or roasting feature is selected here. Logons and audit events still occur.

9.6.1.13.2.1 Older NetExec with --no-write-check, including v1.4.0
nxc smb TARGET -d DOMAIN -u USER -p 'PASSWORD' --shares --no-write-check --log shares.log

Use this only when installed help supports the older flag. Bare --shares in that release creates/deletes temporary artifacts. This form skips write testing, but the old login path can still probe SCM permissions. Filtering displayed shares to READ is not a substitute for disabling the write test.

Do not use linWinPwn --auto as a substitute for this selection: its automatic chain has additional attack behavior. Its menu-based all,LoggedOn collector adds host RPC and remote-registry access that can trigger RemoteRegistry startup. The direct baseline also removes the wrapper's startup Nmap scan and conditional password-repair prompts. Authentication-method fallback can cause multiple authentication exchanges; stop and diagnose a failed credential rather than repeatedly running all collectors.

Sources: BloodHound.py CE, ldapdomaindump, bloodyAD writable query, NetExec share enumeration. A future tool/dependency version needs renewed behavior checks; these commands are reference material, not a claim of target execution or explicit OffSec tool endorsement.

9.6.1.13.3 Analyze in this order

  1. Mark only identities/hosts actually controlled. A low-privilege session on a host does not make the host itself fully owned.
  2. Inspect the controlled principal's direct and nested group memberships and outbound object-control edges.
  3. Inspect reachable computers where it has local admin, RDP, WinRM/DCOM or other applicable rights.
  4. Inspect high-value goals and shortest paths only as hypothesis generation.
  5. Classify each selected edge:
    • directory/static-ish: group, ACL, GPO, OU, trust;
    • host-derived: local group or user right;
    • volatile: session;
    • route-dependent: the required host/service must be reachable now.
  6. Reproduce the minimum important relationship manually before handing it to Block 11 or 12.

9.6.1.14 Rank candidate paths by evidence and missing prerequisites Candidate ledger and path ranking

ID | CONTROLLED PRINCIPAL | RELATIONSHIP | TARGET | SOURCE EVIDENCE
   | EFFECTIVE? | ROUTE/SERVICE | VOLATILITY | EXPECTED TRANSITION
   | MINIMUM VALIDATION | STATUS | NEXT BLOCK

Rank candidates by:

  1. confidence that the relationship is effective;
  2. deterministic value of the resulting identity/access;
  3. route and service availability;
  4. stability versus volatile session timing;
  5. reversibility and impact;
  6. number of unsupported assumptions.

Prefer a validated readable share/credential clue or direct object right over a multi-edge path built from stale sessions and unreachable hosts.

9.6.1.15 Choose the next check from the failure you observed Failure routing

SymptomMost likely layerNext test
DC IP reachable, domain names failDNS/name layerQuery AD DNS SRV/A records; use FQDN; check source resolver
Kerberos fails while SMB/LDAP by IP worksName/SPN/time/KDC routeFQDN, realm, clock, UDP/TCP 88 and ticket state
Domain identity works locally but not from remote shell to DCCredential delegation/double hopklist, SYSVOL access, explicit/off-domain context
LDAP bind succeeds but results are incompleteSearch scope/paging/ACLRootDSE base, paging, known-object query, requested attributes
Share appears but files deny accessObject authorizationEnter share and test exact directory/file; separate read from write
Find-LocalAdminAccess returns nothingEnumeration limitation or no rightsTest one evidence-backed host/service manually
Session enumeration is empty/deniedAPI/rights/firewall/time limitationTreat inconclusive; retry only where host access/value supports it
BloodHound path exists but host is unreachableRoute/service layerMove to Stage 07 before identity attacks
BloodHound import is empty/oddCollection/schema/ingest issueInspect collector logs/ZIP, domain/DNS, method and version compatibility
ACL appears powerful but cannot be tied to current userTrustee/nesting/scope problemResolve SID, nested groups, deny/inheritance and target object GUID

9.6.1.16 Continue with the capability your result enables Handoffs

9.6.1.17 Tooling for this section

ToolChoose it whenRequirementsBaselineDecisive outputFailure cue
whoami, net, nltest, setspn, DNS/time toolsAlways on a domain Windows sourceDomain context; command availability variesSections 2–3 and 8Exact identity/domain/DC/group/SPN factsPartial output; use LDAP/ADSI for breadth
ADSI/DirectorySearcherRSAT/PowerView is absentWindows PowerShell/.NET and DC reachabilitySection 4Paged objects with requested attributes1000-ish limit/empty output: paging, base, filter or rights
ldapsearchOff-domain/raw LDAP control is usefulDC FQDN/IP, base DN, credentials for subtree queriesSection 5Successful bind and complete paged resultsError 49, stronger auth, referral or size limit
PowerViewFast manual AD relationship queriesKnown script/version and Windows PowerShellSection 6Named object/group/ACL/host candidatesArchived/fork syntax and blocked APIs require native fallback
NetExecValidate SMB identity, shares or selected admin candidateKali, route to service, credentialsnxc smb TARGET -d DOMAIN -u USER -p 'PASSWORD' --sharesAuth line, share rights, optional SMB admin markerSMB result does not prove other protocols
smbclientManually inspect a specific share/objectSMB route and credentialssmbclient //TARGET/SHARE -U 'DOMAIN/USER'Exact list/read/write resultListing and file access can differ
PsLoggedOnCheck one justified host for usersWindows binary; remote Registry/session accessPsLoggedOn.exe \\COMPUTERLocal-profile/network-session entriesAccess/Remote Registry limitations; query adds an artifact
SharpHound CE + BloodHound CEGraph directory/host relationshipsCompatible collector/deployment, DNS/DC route, authorized collectionSharpHound.exe --CollectionMethods DCOnly ...Ingested nodes/edges and candidate pathsCollection errors, stale sessions, incompatible schema
bloodhound-python / LDAPDomainDumpLinux-side fallback/reportingKali packages, LDAP/DNS route, credentials, compatible output expectationsInspect --help; use only the needed collection/reportDirectory relationships/HTML or BloodHound outputFeature/schema differences from SharpHound CE

9.6.1.18 Kerbrute — confirm candidate names before password testing

Use with the real domain and reachable KDC. Names generated from emails/wordlists remain candidates until verified.

9.6.1.18.1 kerbrute userenum -d DOMAIN --dc DC_IP --delay 1000 -o valid-users.txt users.txt

kerbrute userenum -d DOMAIN --dc DC_IP --delay 1000 -o valid-users.txt users.txt

9.6.1.18.2 A separate password test, only after reading lockout policy and attempt history

# A separate password test, only after reading lockout policy and attempt history
kerbrute passwordspray -d DOMAIN --dc DC_IP --delay 1000 --safe \
  users.txt 'PASSWORD'

Read: a valid principal is not a valid password or host access. Password pre-auth failures can count toward lockout; --safe stops on a reported lock but does not guarantee that no lockout occurs. Confirm a reported login with the relevant SMB/WinRM/LDAP client and keep the account scope explicit. DNS, time and a correct realm remain prerequisites.

Sources: upstream 1.

9.6.1.19 RustHound-CE — a cross-platform BloodHound collector

Use a compatible RustHound-CE build when collecting directory relationships from Linux or when a SharpHound binary is unsuitable. CE output belongs in BloodHound CE, not Legacy.

9.6.1.19.1 rusthound-ce -d DOMAIN -u 'USER@DOMAIN' -p 'PASSWORD' -f DC_HOST -z

rusthound-ce -d DOMAIN -u 'USER@DOMAIN' -p 'PASSWORD' -f DC_HOST -z

9.6.1.19.2 When the directory requires LDAPS and the TLS/name prerequisites are met

# When the directory requires LDAPS and the TLS/name prerequisites are met
rusthound-ce -d DOMAIN -u 'USER@DOMAIN' -p 'PASSWORD' -f DC_HOST --ldaps -z

Read: import the generated archive, identify the exact useful edge and verify its underlying permission or host access. Directory collection does not establish a live privileged session on a workstation. LDAP/TLS, DNS or credential errors must be repaired before treating an incomplete graph as evidence of no path.

Sources: upstream 1.

9.6.1.20 GPP cpassword — recover a candidate from readable SYSVOL XML

Use when an accessible preference XML contains a cpassword attribute. Search the SYSVOL files actually read/downloaded with the accepted account.

grep -Rni 'cpassword' ./sysvol
gpp-decrypt 'C_PASSWORD'

Read: keep the XML's username, host/policy scope and path beside the recovered value. Old preference files can contain stale credentials. Validate the matching account on a relevant service; a decrypted string is not proof of current domain or local-admin access. A modern domain need not contain these older preference secrets.

Sources: upstream 1.

9.6.1.21 Kerberos clock skew — compare UTC and use a working time source

Use when tickets fail with a skew error or the DC/workstation clock comparison is inconsistent. A timezone label is not the UTC clock value.

9.6.1.21.1 date -u

date -u
nmap -Pn -p 445 --script smb2-time DC_IP

9.6.1.21.2 If this DC is a confirmed reachable NTP source, correct the attack workstation

# If this DC is a confirmed reachable NTP source, correct the attack workstation
sudo ntpdate -u DC_IP
date -u

Read: retry the same ticket/service request after verifying the actual UTC difference. If the clock jumps back, identify the competing host/VM/time-sync source instead of repeatedly changing timezone settings. NTP silence can be filtering or an unavailable time service; it is not evidence that the KDC's displayed time was wrong.

Sources: upstream 1 · upstream 2.

9.6.1.22 Sources


Top of document · Reference home