BloodHound Deep Dive Part 2: SharpHound and What It Actually Collects
Part 1 covered what BloodHound Community Edition is and where it sits in an engagement. This post covers the piece that actually touches Active Directory: SharpHound, the C# collector that walks the domain and produces the JSON that everything downstream depends on. Everything below is taken directly from SharpHound Community Edition’s own flag reference, not from memory or a secondhand cheat sheet, because getting collection scope wrong is either a wasted trip (too narrow) or a loud one (too broad).
Collection methods
SharpHound’s --CollectionMethods flag (short form -c) controls what gets collected. The two that matter most:
Default, used automatically if no method is specified, collects Active Directory security group membership, domain trusts, abusable permissions on AD objects including ADCS objects, the OU tree structure, Group Policy links, the most relevant AD object properties, local groups from every domain-joined Windows system, and user sessions. It touches every reachable computer in the domain, not just the domain controller.
DCOnly collects almost the same set, security group memberships, domain trusts, abusable permissions, OU structure, GPO links, object properties, and it attempts to correlate GPO-enforced local groups to the computers they apply to, but does all of it by talking only to the domain controller. It never connects to a member server or workstation directly.
Beyond those two, SharpHound exposes over a dozen narrower methods for when only one kind of data is needed: Group (just memberships), ACL (just abusable permissions), Trusts, Container (OU tree and GPO links only), LocalGroup (equivalent to LocalAdmin + RDP + DCOM + PSRemote combined), Session (just user sessions, typically paired with --Loop), ObjectProps, SPNTargets, UserRights (needs admin rights on the target), and four methods specifically aimed at NTLM relay path data: WebClientService, LdapServices, SmbInfo, and NTLMRegistry. All runs every method there is.
Against CONTOSO.LOCAL
CONTOSO.LOCAL is a single-DC, three-computer lab. Run as CONTOSO\j.reyes from WKS01, a DCOnly collection is the obvious choice:
C:\> SharpHound.exe --CollectionMethods DCOnly --Domain CONTOSO.LOCAL --OutputDirectory C:\temp\
That run gets everything needed for Parts 4 through 6 of this series: group memberships (j.reyes in IT-HELPDESK, svc-backup in Backup Operators, a.oyelaran in Domain Admins), the GenericAll ACE IT-HELPDESK holds over Backup Operators, and object properties including the hasspn and dontreqpreauth flags Part 5 depends on. What it doesn’t get: local administrator group membership on FS01 and WKS01, and active user sessions. Getting either of those means running Default or the narrower LocalGroup and Session methods, which means touching FS01 and WKS01 directly rather than only the DC. On a three-computer lab the difference is academic. On a domain with thousands of workstations, DCOnly is the difference between one connection and thousands.
Stealth collection
The --Stealth flag doesn’t add a new collection method, it modifies the set of methods Default or All would otherwise run, specifically to reduce SharpHound’s footprint on defended networks:
C:\> SharpHound.exe --CollectionMethods Session --Stealth
Stealth collection drops LoggedOn, RDP, DCOM, PSRemote, LocalAdmin, CARegistry, and DCRegistry, and adds GPOLocalGroup in their place, since GPO-to-computer correlation for local group membership can be derived entirely from the domain controller without ever touching the target computers. That trade, less accurate local-group data for a much smaller network footprint, is exactly the kind of tuning knob this series’ Sn1per coverage kept surfacing: broader collection finds more, narrower collection gets caught less, and the right answer depends entirely on what stage of the engagement this is.
Scope, output, and pacing flags
A handful of other real flags shape a collection run beyond which methods it uses. --SearchForest (or -s) extends collection to every domain in the current forest instead of just one. --DistinguishedName limits the search base to a specific OU, for example --DistinguishedName "OU=New York,DC=Contoso,DC=Local". --LDAPFilter (or -f) restricts collection to principals matching an arbitrary LDAP filter. --ExcludeDCs skips the domain controller entirely, sacrificing everything DCOnly would have provided in exchange for avoiding whatever monitoring, Microsoft Defender for Identity among it, sits closest to the DC.
On the output side, --OutputDirectory and --OutputPrefix control where the zipped JSON lands and what it’s named, --ZipPassword encrypts the archive (unencrypted by default), and --RandomFileNames and --NoZip exist for cases where a predictable *_BloodHound.zip filename or a compressed archive would themselves be a detectable pattern.
On pacing, --Throttle adds a delay in milliseconds after each request to a computer, --Jitter randomizes that delay by a percentage, and --PortCheckTimeout controls how long SharpHound waits for a response on port 445 before deciding a host is unreachable and moving on, a check that runs before most of the computer-touching collection methods and is itself part of the footprint Part 7 of this series covers from the defender’s side.
What comes next
A finished SharpHound run produces zipped JSON, one file per node type and edge type it collected. That output means nothing until it’s parsed into a graph. Next: Part 3, where that JSON goes in through BloodHound Community Edition’s own ingestion pipeline, and where this series’ verification approach shifts from documentation to a real, running graph database.