There are numerous techniques available for enumerating data via LDAP. In the context of a Red Team engagement – where operational security (OPSEC) is critical to avoid detection by the Blue Team – directly running LDAP queries from a PowerShell console has become increasingly impractical in recent years due to improved monitoring and detection capabilities.
That said, there are still viable methods to perform LDAP enumeration under these constraints. One such approach is outlined in the LDAP obfuscation research by Sabajete Elezaj and Daniel Bohannon, published in August 2024 [1]. Their work demonstrates how LDAP queries can be obfuscated using various techniques to evade detection. However, even with obfuscation, executing PowerShell commands from within a C2 beacon may still pose significant OPSEC risks.
Over the years, the community has published a wealth of content on this topic. One of the blogs I can recommend is “Active Directory Enumeration for Red Teams” by @domchell of MDSec, published in February 2024 [2]. It’s highly recommended for anyone looking to deepen their understanding of stealthy AD enumeration tactics.
In the spring of 2025, I conducted tests using several LDAP enumeration techniques to evaluate what actions would trigger alerts in Microsoft Defender for Identity (MDI) and Microsoft Defender for Endpoint (MDE). Some of these tests were run directly from a PowerShell console on a client machine, while others were executed through a Cobalt Strike beacon using the ldapsearch Beacon Object File (BOF) from TrustedSec’s Situational Awareness toolkit [3].
When leveraging the ldapsearch BOF, output can be retrieved from Cobalt Strike’s log files and parsed using BOFHound [4], a tool that converts results into JSON format suitable for ingestion into BloodHound for post-exploitation analysis. The BOFHound repository also links to blog posts with all the technical details needed to replicate this workflow.
As a third method, for added variety in this blog post, I also explored executing LDAP queries directly from Microsoft Excel using the OleDB provider – a less conventional, but interesting vector for stealthy enumeration.
The victim client used for these tests was a fully patched Windows 11 client with MDE P2 license enabled. The MDI threshold level configuration was set to the lowest for all settings:

MDI threshold settings
In the test results below, each entry includes the LDAP query command that was executed, followed by the corresponding detection outcome from Microsoft Defender for Identity (MDI). For each test, I evaluated two key aspects:
- Did MDI trigger an alert as a result of the query?
- Was the query logged in MDI’s IdentityQueryEvents table, accessible via the Advanced Hunting section in the Microsoft Defender portal [5]?
Most of the queries were executed using various LDAP obfuscation techniques, aiming to reduce the likelihood of detection or logging by MDI.
LDAP Enumeration using native PowerShell
The initial tests were conducted using native ADSI PowerShell queries, incorporating basic LDAP query obfuscation techniques. These queries were executed directly from a PowerShell console on a Windows client, without any connection to a command-and-control (C2) framework.
List Domain Admins Group
The following query lists the Domain Admins builtin group (without it’s members) by using ambiguous name resolution and hex encoding as well as ComparisonOperator obfuscation:
([adsisearcher]'(&(aNR=\64\6F\6D\61\69\6E Admi*asdfasdfasdf)(samaccounttype>=268435455)(samaccounttype<=268435457)(!(samaccounttype=268435455))(!(samaccounttype=268435457)))').FindAll()
Note: The string \64\6F\6D\61\69\6E Admi*asdfasdfasdf translates to Domain Admi*, where the hexadecimal values represent ASCII characters. A random string was appended after the wildcard. As highlighted in the 2024 research by Daniel Bohannon and Sabajete Elezaj, when using Ambiguous Name Resolution (ANR) in LDAP queries, any characters following a wildcard (*) are ignored during query execution. This behavior can be leveraged to obfuscate search terms while still retrieving valid results.
MDI alert triggered: No
Data in IdentityQueryEvents: Yes

IdentityQueryEvents entry of Domain Admins group query
Listing of all Service Principal Names (SPN)
The following query lists all accounts with ServicePrincipalNames configured and uses the ComparisonOperator obfuscation:
([adsisearcher]'(&(&(samaccounttype>=805306367)(samaccounttype<=805306369)(!(samaccounttype=805306367))(!(samaccounttype=805306369)))(serviceprincipalname<=zzz))').FindAll()
MDI alert triggered: No
Data in IdentityQueryEvents: No
List users
The following query gets all User accounts which were created after a specific date and uses oid notation with prefixed zeroes:
([adsisearcher]'(&(1.2.840.113556.1.2.2>=20240101000000.0Z)(oId.001.02.000840.00113556.000001.04.302=805306368))').FindAll()
MDI alert triggered: No
Data in IdentityQueryEvents: No
Enumeration using the ldapsearch BOF
Next, some LDAP enumeration was done via a C2 beacon on our Windows 11 machine. As mentioned earlier, MDE was enabled on this system with a P2 license.
Get information about specific user
The following query lists a user’s details by the given samaccountname:
ldapsearch "(&(objectCategory=person)(objectClass=user)(samaccountname=jdoe))"
MDI alert triggered: No
Data in IdentityQueryEvents: No
Listing of all enabled users
The following query lists all enabled users:
ldapsearch "(&(samAccountType=805306368)(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))" *,ntsecuritydescriptor
MDI alert triggered: No
Data in IdentityQueryEvents: Yes

IdentityQueryEvents entry of the query which lists all enabled users
Querying all enabled Users (with basic LDAP obfuscation)
The following query lists all enabled users and uses ComparisonOperator obfuscation:
ldapsearch "(&(&(samaccounttype>=805306367)(samaccounttype<=805306369)(!(samaccounttype=805306367))(!(samaccounttype=805306369)))(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))" *,ntsecuritydescriptor
MDI alert triggered: No
Data in IdentityQueryEvents: No
Querying the Domain
The following query lists the domain object:
ldapsearch (objectclass=domain) *,ntsecuritydescriptor
MDI alert triggered: No
Data in IdentityQueryEvents: Yes

IdentityQueryEvents entry of the query which lists the domain object
Querying the Domain (with basic obfuscation)
The following query lists the domain object and uses logical AND and NOT operator:
ldapsearch "(&(objectClass=domain)(!(objectClass=notdomain)))" *,ntsecuritydescriptor
MDI alert triggered: No
Data in IdentityQueryEvents: No
Listing all computers (using OID)
The following query lists all computers and uses the OID number instead of the object name:
ldapsearch "(2.5.4.0=computer)" *,ntsecuritydescriptor
MDI alert triggered: No
Data in IdentityQueryEvents: Yes

IdentityQueryEvents entry of the query which lists all computers
Listing all Computers (with basic obfuscation)
The following query lists all computers and uses HEX encoding and the OR operator for basic obfuscation:
ldapsearch "(|(objectClass=\63\6f\6d\70\75\74\65\72)(objectClass=\63\6f\6d\70\75\74\65\72))" *,ntsecuritydescriptor
MDI alert triggered: No
Data in IdentityQueryEvents: Yes

IdentityQueryEvents entry of the query which lists all computers
Listing all computers (with more obfuscation)
The following query lists all computers and combines HEX encoding, AND, OR and NOT operators, OID and ComparisonOperator for obfuscation:
ldapsearch "(&(name<=zzzz)(!(UserAccountControl:1.2.840.113556.1.4.803:=2))(!(objectCategory=contact))(|(2.5.4.0=\63\6f\6d\70\75\74\65\72)(2.5.4.0=\63\6f\6d\70\75\74\65\72)))" *,ntsecuritydescriptor
MDI alert triggered: No
Data in IdentityQueryEvents: No
Enumerating LDAP via Excel OleDB
In Microsoft Excel, you can use the OleDB provider to connect to LDAP and query data directly from Active Directory. To set this up, open a new Excel workbook and navigate to the Data tab. From there, select:
Get Data → From Other Sources → Blank Query
This opens the Power Query editor, where you can define and run LDAP queries using OleDB connection strings.
Listing all users
The following query lists all users:
= OleDb.DataSource("provider=ADsDSOObject;Data Source=ldap://testlab.local;mode=Read", [Query="SELECT name,samaccountname,useraccountcontrol From 'LDAP://DC=testlab,DC=local' WHERE #(lf)objectClass='user' AND objectCategory='Person'" ])
The resulting list in Excel:

Excel containing list of all AD users
MDI alert triggered: No
Data in IdentityQueryEvents: Yes

IdentityQueryEvents entry for the OleDB query listing users
List all groups with Basic Obfuscation
The following query lists all groups and uses HEX encoding for basic obfuscation:
= OleDb.DataSource("provider=ADsDSOObject;Data Source=ldap://testlab.local;mode=Read", [Query="SELECT name, samAccountName, distinguishedName FROM 'LDAP://DC=testlab,DC=local' WHERE objectClass='g\72\6f\75\70'" ])
MDI alert triggered: No
Data in IdentityQueryEvents: Yes
List Domain Admins with Basic Obfuscation
The following query lists the members of the Domain Admins group and uses HEX encoding for basic obfuscation:
= OleDb.DataSource("provider=ADsDSOObject;Data Source=ldap://testlab.local;mode=Read", [Query="SELECT name, samAccountName FROM 'LDAP://DC=testlab,DC=local' WHERE objectClass='user' AND objectCategory='Person' AND memberOf='CN=\44\6F\6D\61\69\6E\20\41\64\6D\69\6E\73,CN=Users,DC=testlab,DC=local'" ])
MDI alert triggered: No
Data in IdentityQueryEvents: No
Limiting Results
In larger environments, it’s often advisable to limit the amount of data returned from LDAP queries to avoid generating excessive or suspicious telemetry that could trigger detection mechanisms.
This can be achieved in some tools through paging, if supported. Alternatively, you can control the query scope manually by crafting more specific LDAP filters. For instance, using the ComparisonOperator allows you to apply conditions that narrow down results – such as querying only for objects modified after a certain date, or filtering based on a specific attribute value.
Example 1
One way to achieve this is to e.g. get all users with samAccountName starting with the letter A
:
(&(samAccountName>=A)(samAccountName<=Azzzzzzz)(samaccounttype=805306368))
You can use the >=
and <=
operators to define a range in your LDAP filter. Since the letter “z” is at the end of the ASCII sort order, appending several “z” characters (e.g., zzzzzz
) to the upper bound can help ensure that entries like “Azz…” are also included in the result set.
Example 2
whenCreated
property, e.g. accounts created between January 1st and February 1st 2020:(&(whenCreated>=20200101000000.0Z)(whenCreated<=20200201000000.0Z)(samaccounttype=805306368))
Adding Custom Detection Rules (Defender for Identity)
When analyzing the MDI-related tables in the Advanced Hunting section of the Microsoft Defender portal, it’s possible to create custom detections that cover LDAP queries which do not trigger built-in MDI alerts.
To determine whether MDI has logged evidence of a specific LDAP query, I typically use the following Kusto Query Language (KQL) query:
IdentityQueryEvents | where Timestamp > ago(24h) | project Timestamp,QueryType,Query,DeviceName,DestinationDeviceName,AdditionalFields | sort by Timestamp desc
The Advanced Hunting interface also includes a convenient “Create detection rule” button, which allows you to directly convert your KQL query into a custom detection rule.
Detecting LDAP Enumeration with Defender for Endpoint
Microsoft Defender for Endpoint (MDE) can also be leveraged to create custom detections based on LDAP activity. For example, the following KQL query retrieves all LDAP queries executed within the last 12 hours:
DeviceEvents | where ingestion_time() >= ago(12h) | where ActionType =~ "LdapSearch" | extend AdditionalFields=parse_json(AdditionalFields) | extend SearchFilter=tostring(AdditionalFields.SearchFilter) | project-reorder DeviceName, InitiatingProcessCommandLine, SearchFilter
References:
- [1] – https://github.com/MaLDAPtive/Invoke-Maldaptive
- [2] – https://www.mdsec.co.uk/2024/02/active-directory-enumeration-for-red-teams/
- [3] – https://github.com/trustedsec/CS-Situational-Awareness-BOF
- [4] – https://github.com/coffeegist/bofhound
- [5] – https://learn.microsoft.com/en-us/defender-xdr/advanced-hunting-identityqueryevents-table