Skip to content

AD enumeration

PingCastle

Quickly identify misconfigurations, vulnerabilities, and risks within Active Directory and Entra ID environments using PingCastle.

  1. Download the Syslifters compiled version of PingCastle.exe
  2. Add license into appsettings.console.json file next to the PingCastle.exe file to run the program with the correct license. Retrieve the file or license key from your password manager / internal vault.
  3. Run pingcastle.exe in a terminal.

Bloodhound

Map and assess Active Directory related attack paths in Active Directory and Entra ID environments.

  1. Download the Syslifters compiled Sharphound.exe collector

  2. Collect data

  • Cheatsheet: SharpHound cheat sheet (external link)

  • For non-admin users:
    ./SharpHound.exe

  • With domain admin, we will also want to collect sessions:
    ./SharpHound.exe --c All

  • Collect data with all attributes:
    sharphound.exe -c all --collectallproperties

  1. Import the .zip file into the hosted BloodHound instance. Credentials and host info should be stored in your password manager / internal vault.

Pyldap

If BloodHound is unavailable or fails, you can achieve similar results using pyldap, a tool for manual LDAP queries that supports BloodHound-compatible output.

  1. Download pyldap
  2. Run an LDAP query, e.g.:
    .\--main--.exe operation\user:<password> '(objectClass=*)'
  3. Transform with bofhound to ingest into a BloodHound instance.

Cipher queries

Here are some practical BloodHound Cypher queries for extracting valuable information about the target environment or handling nodes.

Use these in the Neo4j web interface after data ingestion (credentials available in your password manager / internal vault).

Some queries were based on Handy BloodHound Cypher queries.

Bulk mark as owned

Tags one or more users as compromised by appending owned to their system_tags, which surfaces them as starting points in attack-path queries. The CASE block keeps the operation idempotent: it avoids duplicate tags and handles a NULL system_tags value.

powershell
MATCH (u:User)
WHERE u.samaccountname IN ["user1", "user2"]
SET u.system_tags =
CASE
    WHEN u.system_tags IS NULL THEN ["owned"]
    WHEN "owned" IN u.system_tags THEN u.system_tags
    ELSE u.system_tags + ["owned"]
END
RETURN u.samaccountname AS updated_users, u.system_tags AS new_tags;

Delete a single computer

Removes a node and all of its incoming and outgoing relationships from the graph via DETACH DELETE. Handy for cleaning up decommissioned hosts, duplicate entries or unwanted nodes. Adjust the label (:User, :Computer, :Group, ...) to match the object you want to drop.

powershell
MATCH p=(c:User)
WHERE c.name = "COMPUTER@DOMAIN.LOCAL"
detach delete p

Delete a relationship between a user and another object

Useful for pruning false positives or unwanted edges (e.g. stale HasSession, irrelevant MemberOf) from the graph. Replace the edge type after r: with the relationship you want to remove, or omit it (-[r]->) to delete every relationship between the two nodes.

powershell
MATCH (u:User {name: "USER@DOMAIN.LOCAL"})-[r:HasSession]->(o)
WHERE o.name = "TARGET@DOMAIN.LOCAL"
DELETE r

Get all sensitive users

Lists user accounts flagged as Account is sensitive and cannot be delegated. These are typically high-value identities (admins, service accounts handling secrets) and good candidates for further enumeration or targeting.

powershell
match (u:User) where u.sensitive = True return u

Get owned users

Returns every user already marked as owned (u.owned = True), together with any captured password stored in u.pw and their distinguished name. Useful for a quick recap of which accounts you have credentials for during an engagement.

powershell
MATCH (u:User)
WHERE u.owned = True
RETURN u.samaccountname, u.pw, u.distinguishedname
ORDER BY u.name

Get all users with outbound object control

Counts, per enabled user, how many objects they can directly control via dangerous AD/ADCS rights, both directly and transitively through group membership (up to 10 hops). Results are bucketed by target type (computers, users, groups, OUs, GPOs, domains, containers, ADCS objects) and ordered by total, making it easy to spot over-privileged accounts or the best escalation candidates.

powershell
CYPHER runtime=parallel
CALL {
    MATCH (u:User)-[:Owns|OwnsLimitedRights|WriteDacl|WriteOwner|WriteOwnerLimitedRights|GenericAll|GenericWrite|AllExtendedRights|ForceChangePassword|AddMembers|AddSelf|WriteSPN|AddKeyCredentialLink|ReadLAPSPassword|SyncLAPSPassword|ReadGMSAPassword|AddAllowedToAct|WriteAccountRestrictions|HasSIDHistory|WriteGPLink|DCSync|GetChanges|GetChangesAll|GetChangesInFilteredSet|ManageCA|ManageCertificates|Enroll|AutoEnroll|EnrollOnBehalfOf|WritePKIEnrollmentFlag|WritePKINameFlag|WriteCertificateMappingAccess|WriteCertificateEnrollmentFlag]->(tgt)
    WHERE u <> tgt
      AND coalesce(u.enabled, true) = true
    RETURN u, tgt
  UNION
    MATCH (u:User)-[:MemberOf*1..10]->(:Group)-[:Owns|OwnsLimitedRights|WriteDacl|WriteOwner|WriteOwnerLimitedRights|GenericAll|GenericWrite|AllExtendedRights|ForceChangePassword|AddMembers|AddSelf|WriteSPN|AddKeyCredentialLink|ReadLAPSPassword|SyncLAPSPassword|ReadGMSAPassword|AddAllowedToAct|WriteAccountRestrictions|HasSIDHistory|WriteGPLink|DCSync|GetChanges|GetChangesAll|GetChangesInFilteredSet|ManageCA|ManageCertificates|Enroll|AutoEnroll|EnrollOnBehalfOf|WritePKIEnrollmentFlag|WritePKINameFlag|WriteCertificateMappingAccess|WriteCertificateEnrollmentFlag]->(tgt)
    WHERE u <> tgt
      AND coalesce(u.enabled, true) = true
    RETURN u, tgt
}
WITH u,
     COUNT(DISTINCT tgt)                                                 AS total,
     COUNT(DISTINCT CASE WHEN tgt:Computer     THEN tgt END)             AS computers,
     COUNT(DISTINCT CASE WHEN tgt:User         THEN tgt END)             AS users,
     COUNT(DISTINCT CASE WHEN tgt:Group        THEN tgt END)             AS groups,
     COUNT(DISTINCT CASE WHEN tgt:OU           THEN tgt END)             AS ous,
     COUNT(DISTINCT CASE WHEN tgt:GPO          THEN tgt END)             AS gpos,
     COUNT(DISTINCT CASE WHEN tgt:Domain       THEN tgt END)             AS domains,
     COUNT(DISTINCT CASE WHEN tgt:Container    THEN tgt END)             AS containers,
     COUNT(DISTINCT CASE WHEN tgt:CertTemplate OR tgt:EnterpriseCA
                           OR tgt:RootCA OR tgt:AIACA
                           OR tgt:NTAuthStore  THEN tgt END)             AS adcs
RETURN u.name AS user, total, computers, users, groups, ous, gpos, domains, containers, adcs
ORDER BY total DESC

Get all certificates with modification rights other than DA / EA / Built-In Administrators

Finds non-administrative principals that have Owns, WriteOwner, WriteDacl, GenericAll or GenericWrite over objects under the Public Key Services container (certificate templates, CAs, NTAuthStore, ...). Domain Admins (-512), Enterprise Admins (-519) and Built-in Administrators (-544) are filtered out so only unexpected privileges remain. These are common starting points for AD CS abuse (ESC1 to ESC13).

powershell
MATCH p = (n:Base)-[:Owns|WriteOwner|WriteDacl|GenericAll|GenericWrite]->(m:Base)
WHERE m.distinguishedname CONTAINS "PUBLIC KEY SERVICES"
AND NOT n.objectid ENDS WITH "-512" // Domain Admins
AND NOT n.objectid ENDS WITH "-519" // Enterprise Admins
AND NOT n.objectid ENDS WITH "-544" // Administrators
RETURN p
LIMIT 1000

Shortest path from owned users to DA (GUI functional)

Returns the shortest attack path from any owned user (system_tags CONTAINS "owned") to the Domain Admins group (SID ending in -512). The edge list mirrors what the BloodHound GUI understands, so the result can be opened and explored visually instead of just printed as raw paths.

powershell
MATCH p=shortestPath((n:User)-[:Owns|GenericAll|GenericWrite|WriteOwner|WriteDacl|MemberOf|ForceChangePassword|AllExtendedRights|AddMember|HasSession|Contains|GPLink|AllowedToDelegate|TrustedBy|AllowedToAct|AdminTo|CanPSRemote|CanRDP|ExecuteDCOM|HasSIDHistory|AddSelf|DCSync|ReadLAPSPassword|ReadGMSAPassword|DumpSMSAPassword|SQLAdmin|AddAllowedToAct|WriteSPN|AddKeyCredentialLink|SyncLAPSPassword|WriteAccountRestrictions|GoldenCert|ADCSESC1|ADCSESC3|ADCSESC4|ADCSESC5|ADCSESC6a|ADCSESC6b|ADCSESC7|ADCSESC9a|ADCSESC9b|ADCSESC10a|ADCSESC10b|ADCSESC13|DCFor*1..]->(m:Group))
WHERE n.system_tags CONTAINS "owned" AND m.objectid ENDS WITH "-512"
RETURN p

Shortest path from owned computers to DA (GUI functional)

Same as the previous query but starting from owned computers instead of users. Useful for visualizing escalation paths reachable through compromised hosts (e.g. via machine-account abuse, sessions or delegation) up to Domain Admins.

powershell
MATCH p=shortestPath((n:Computer)-[:Owns|GenericAll|GenericWrite|WriteOwner|WriteDacl|MemberOf|ForceChangePassword|AllExtendedRights|AddMember|HasSession|Contains|GPLink|AllowedToDelegate|TrustedBy|AllowedToAct|AdminTo|CanPSRemote|CanRDP|ExecuteDCOM|HasSIDHistory|AddSelf|DCSync|ReadLAPSPassword|ReadGMSAPassword|DumpSMSAPassword|SQLAdmin|AddAllowedToAct|WriteSPN|AddKeyCredentialLink|SyncLAPSPassword|WriteAccountRestrictions|GoldenCert|ADCSESC1|ADCSESC3|ADCSESC4|ADCSESC5|ADCSESC6a|ADCSESC6b|ADCSESC7|ADCSESC9a|ADCSESC9b|ADCSESC10a|ADCSESC10b|ADCSESC13|DCFor*1..]->(m:Group))
WHERE n.system_tags CONTAINS "owned" AND m.objectid ENDS WITH "-512"
RETURN p

ADRecon

Use ADRecon to gather comprehensive details about the Active Directory environment and generate an Excel (.xlsx) report for a holistic overview of the target environment.

  1. Execute .\ADRecon.ps1 in PowerShell. An Excel report will be generated automatically if Microsoft Office is installed.
  2. If Office is not available, create an Excel report from the CSV files on another host using:
    .\ADRecon.ps1 -GenExcel C:\ADRecon-Report-<timestamp>

Kerberoasting

Identify all service accounts with Service Principal Names (SPNs) configured that are vulnerable to Kerberoasting. Check for accounts with RC4 enabled.

powershell
# Kerberoast and write hashes to file
Rubeus.exe kerberoast /outfile:hashes.txt /nowrap

AS-Rep Roasting

Find all user accounts with pre-authentication disabled, making them vulnerable to AS-Rep Roasting.

powershell
Rubeus.exe asreproast /outfile:asrephashes.txt /format:hashcat /nowrap

RSAT tools

The Remote Server Administration Tools (RSAT) ship the PowerShell modules and MMC snap-ins used throughout AD enumeration: the ActiveDirectory module (Get-ADUser, Get-ADComputer, ...), DNSServer, DHCPServer, GroupPolicy, the AD CS console, and more.

  • On modern Windows 10/11 clients they are optional capabilities and must be added before most Get-AD* cmdlets will work.
  • On Windows servers, they are optional features. Use Get-WindowsFeature instead of Get-WindowsCapability there.
    • E.g., Get-WindowsFeature RSAT-AD-PowerShell

Run PowerShell as Administrator for all commands.

List installed / available RSAT capabilities:

powershell
Get-WindowsCapability -Name RSAT* -Online

Install everything at once:

powershell
Get-WindowsCapability -Name RSAT* -Online | Add-WindowsCapability -Online

Install only what you need. The AD, DNS, DHCP, Group Policy and AD CS modules cover the vast majority of engagements:

powershell
Add-WindowsCapability -Online -Name Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0
Add-WindowsCapability -Online -Name Rsat.Dns.Tools~~~~0.0.1.0
Add-WindowsCapability -Online -Name Rsat.DHCP.Tools~~~~0.0.1.0
Add-WindowsCapability -Online -Name Rsat.GroupPolicy.Management.Tools~~~~0.0.1.0
Add-WindowsCapability -Online -Name Rsat.CertificateServices.Tools~~~~0.0.1.0
Add-WindowsCapability -Online -Name Rsat.FileServices.Tools~~~~0.0.1.0
Add-WindowsCapability -Online -Name Rsat.ServerManager.Tools~~~~0.0.1.0