Written by Yehuda Smirnov
- TL;DR
- Introduction
- ADExplorer Snapshot Detections (sort of)
- Avoiding Defender for Identity Detections
- Shoutout to SoapHound
- How to Use ShadowHound
- Detection Strategies
- Final Thoughts
TL;DR
- ShadowHound is a PowerShell tool designed to map Active Directory environments for BloodHound without introducing known-malicious / foreign binaries like SharpHound or SoapHound.
- Two methods (protocols) can be used for data collection:
- Using the Active Directory module (ADWS)
- Using the native DirectorySearcher class (LDAP).
- Bonus – Avoiding Defender for Identity detections (and how to still detect such enumerations)
Find the ShadowHound GitHub repo here.
Introduction
While SharpHound has been the cornerstone for collecting data for BloodHound, deploying it in a target environment poses detection risks (even after some obfuscation and customization). EDRs are getting increasingly better at detecting and flagging such binaries, whether they are reflectively loaded, etc. ShadowHound aims to avoid this issue by utilizing native PowerShell or legitimate tools (AD Module) to obtain the BloodHound Data.
It should be noted that Domain Controllers can still flag unusual LDAP queries (with the help of Defender for Identity for example). However, by avoiding the introduction of known-malicious binaries, we can minimize our footprint on the target machine and avoid some of the common LDAP filters which trigger alerts (more on this later).
ADExplorer Snapshot Detections (sort of)
One alternative to SharpHound is using ADExplorer to create snapshots of the Active Directory and then convert those snapshots into BloodHound JSON files using tools like ADExplorerSnapshot.py. While this method can be effective, it might fail in large domains when dealing with poor connectivity (or the VPN auto disconnects after a period of time). In such cases, ADExplorer may error out due to connectivity issues, and you will be left without any snapshot data.
During a recent engagement, we also encountered detections when using ADExplorer. Specifically, when Active Directory Federation Services (ADFS) is deployed, creating a snapshot with ADExplorer can trigger an alert because it reads the ADFS LDAP container, as noted in the detections section for Microsoft Defender for Identity:

During a default install, the container exists under the Program Data container:

Faced with these challenges, we realized we needed a solution that could avoid both the detection issues and effectively handle large domains. This led us (Itay Yashar, my teammate, and I) to develop ShadowHound, turning an idea from our R&D shelf into a practical tool.
Avoiding Defender for Identity Detections
During our recent engagement and also during testing, we’ve noticed Defender for Identity detections occur for queries such as Get-ADUser -Filter * or when using pyLdapSearch with (objectClass=*) LDAP filter, which is widely known as the query performed by ADExplorer (and hence it is considered more ‘opsec’):

Upon researching we’ve discovered that the query (objectGuid=*) seemed to not raise any Defender for Identity detections (for now), and hence why we’ve opted to use this LDAP filter for the tool.
We should also note that ShadowHound is essentially just a post-processing script to convert DirectorySearcher or ADModule output to pyLdapSearch output. However, pyLdapSearch does not support ADWS (at least as of this moment), and requires Python to be installed, etc.
Shoutout to SoapHound
In the context of ADWS, it’s worth mentioning SoapHound by FalconForce, they made the initial public discovery about using ADWS for Active Directory enumeration and created a tool for the task.
While SoapHound provides valuable functionality and incredible research, it is yet another binary that we need to introduce to monitored endpoints, and unfortunately we had a bit of trouble with using it against a very large domain (hence why we created the -SplitSearch flag to split the enumeration to containers and borrowed their split search idea with the -LetterSplitSearch flag to further split the search to objects beginning with a, b, c…).
How to Use ShadowHound

ShadowHound comes in two flavors:
- ADModule Based: This script leverages the Active Directory module (
Get-ADObjectcmdlet) in PowerShell, which communicates via the Active Directory Web Services (ADWS) protocol over port 9389. - DirectorySearcher Based: This script uses the
DirectorySearcherclass, performing LDAP queries directly.
Getting started with ShadowHound is straightforward. Here’s a basic example using the ADModule-based version:
Import-Module .\ShadowHound-ADM.ps1
# Example 1: Basic usage with required parameter
ShadowHound-ADM -OutputFilePath "C:\Results\ldap_output.txt"
# Example 2: Specify a domain controller and custom LDAP filter
ShadowHound-ADM -Server "dc.domain.local" -OutputFilePath "C:\Results\ldap_output.txt" -LdapFilter "(objectClass=user)"
# Example 3: Use alternate credentials and specify a search base
$cred = Get-Credential
ShadowHound-ADM -OutputFilePath "C:\Results\ldap_output.txt" -Credential $cred -SearchBase "CN=Infrastructure,DC=sevenkingdoms,DC=local"
# Example 4: Split the search across top-level containers with split letter search
ShadowHound-ADM -OutputFilePath "C:\Results\ldap_output.txt" -SplitSearch -LetterSplitSearch
# Example 5: Enumerate certificates
ShadowHound-ADM -OutputFilePath "C:\Results\output.txt" -Certificates
# Example 6: Exclude a container (such as the ADFS container) from the enumeration
ShadowHound-ADM -OutputFilePath "C:\Results\output.txt" -SplitSearch -ParsedContainers "./parsed.txt"
# parsed.txt contains a new-line seprated list of containers' Distinguished Name
# CN=Program Data,DC=sevenkingdoms,DC=local
And using the DirectorySearcher-based version:
Import-Module .\ShadowHound-DS.ps1
# Example 1: Basic usage with required parameter
ShadowHound-DS -OutputFile "C:\Results\ldap_output.txt"
# Example 2: Specify a domain controller
ShadowHound-DS -Server "dc.domain.local" -OutputFile "C:\Results\ldap_output.txt"
# Example 3: Use a custom LDAP filter
ShadowHound-DS -OutputFile "C:\Results\ldap_output.txt" -LdapFilter "(objectClass=computer)"
# Example 4: Specify a search base
ShadowHound-DS -OutputFile "C:\Results\ldap_output.txt" -SearchBase "CN=Infrastructure,DC=sevenkingdoms,DC=local"
# Example 5: Enumerate certificate-related objects
ShadowHound-DS -OutputFile "C:\Results\cert_output.txt" -Certificates
# Example 6: Use alternate credentials
$cred = Get-Credential
ShadowHound-DS -OutputFile "C:\Results\ldap_output.txt" -Credential $cred
After running the script, you’ll have an output file containing LDAP search results formatted for processing:

Handling Large Domains with ADWS
One of the challenges when dealing with extensive Active Directory environments is the potential for queries to time out using ADWS (generate the invalid enumeration context error). The ADModule version of ShadowHound addresses this with the SplitSearch, Recurse and LetterSplitSearch functionalities:
** Once again thanks to FalconForce for the research and for coming up with a solution!
- SplitSearch: When enabled, ShadowHound will split the search across top-level containers within the domain root or the within the provided container distinguished name (if you have those pesky ginormous containers), querying each one individually. This approach helps manage large datasets by breaking them into more manageable chunks.
- Recurse: If a container fails to return results within a 30-minute window (the point at which the enumeration context expires due to ADWS limitations), ShadowHound will automatically split that container into its sub-containers and attempt to retrieve the data again. This recursive approach ensures we (hopefully) do not miss data.
- LetterSplitSearch: Like SoapHound, if this flag is provided, the queries will be split into
(cn=a**),(cn=b**), etc. If that query fails, the query will split yet again –(cn=aa**),(cn=ab**),(cn==ac**).
This flag can be combined with the SplitSearch flag to split each container into smaller queries.
Converting Data with BofHound
Once you’ve collected the data (which should look like ldapsearch output), the next step is to convert it into BloodHound-compatible JSON files using BofHound, which was recently updated:
python3 bofhound.py -i ldap_output.txt -p All --parser ldapsearch
BofHound will process the LDAP output and generate the JSON files you can import into BloodHound CE for analysis.
Splitting the JSON files
Depending on the file size (>100MB), you may want to split the output JSON file using tools like ShredHound or mgeeky’s snippet.
From our experience, for large domains, even when BloodHound CE says the data was ingested, you should double check and try to query some data from the JSONs to confirm they were ingested properly.
If the data was not digested properly, you should use one the tools above to split it, even if it seems like a small amount of computers.
Detection Strategies
The effective method to detect ShadowHound (and the likes which perform AD enumeration) is to track identities that read an exceptionally high number of LDAP records within a specific time frame, as this behavior can indicate malicious enumeration similar to SharpHound’s activities. Elastic’s detection rule, for instance, flag such anomalies by identifying excessive directory object attribute requests. This was also noted by FalconForce’s blog under the “Detecting SOAPHound” section.
Another interesting idea might be to setup honeypots in LDAP containers which trigger upon read access. This could be an indicator of attack.
Final Thoughts
ShadowHound offers an alternative approach to gather Bloodhound data by eliminating the need to deploy SharpHound or other binaries on the target endpoint. By leveraging the AD module or the DirectorySearcher class, we can reduce our the chance of detection on the endpoint itself.
While ShadowHound might minimize endpoint level detection, network activity should always remain a consideration. Be mindful of the queries you’re performing and be aware that DCs (with the help of MDI and the likes) can flag unusual or suspicious LDAP activity (and with Machine Learning becoming more of a thing, we expect this to happen sooner than later).
Give ShadowHound a try and see how it works for your engagements. If you have any questions, run into issues, or have feedback—whether it’s about something that might be off or ideas for improvement—don’t hesitate to reach out. You can find me on X – @yudasm_ or send an email to info@fndsec.net.




