Hunting Down AD Objects with PowerShell – The Fast and Furious Way

Ever felt like searching for something in Active Directory is like looking for a needle in a haystack? Well, put away your magnifying glass, because PowerShell and LDAP queries are here to save the day. Whether you’re tracking down rogue admin groups, forgotten Exchange attributes, inactive users, or just trying to make your life easier, this method gets the job done – and fast. No extra AD modules needed, no unnecessary waiting. Just pure, efficient querying.

Why Use LDAP Queries?

LDAP (Lightweight Directory Access Protocol) allows structured searches in Active Directory, making it more efficient than looping through all objects manually. By leveraging System.DirectoryServices.DirectorySearcher, we can perform these queries directly in PowerShell. A key advantage of this approach is that it operates at the LDAP level, meaning it does not rely on the Active Directory module (RSAT-AD-PowerShell).

Performance Boost with Global Catalog

By querying the Global Catalog (GC), we achieve significantly faster search results because the GC contains a partial replica of all directory objects, optimized for searches across domains. This is particularly useful in multi-domain environments, where querying the GC reduces query time and load on domain controllers.

Setting Up the Search

Below is a PowerShell script that searches for AD objects (groups, users, or computers) based on different attributes:

PowerShell
# Define variables
$SearchPattern = '*Admin*'  # Change this to your desired search pattern
$Attribute = 'displayName'   # Choose an attribute to filter on
$ObjectClass = 'group'       # Change this to 'user' or 'computer' for different searches
$Domain = 'your.domain.com'  # Replace with your AD domain

# Connect to the Global Catalog (ensuring faster queries)
$RootDSE = [ADSI]"GC://$Domain"
$Searcher = New-Object System.DirectoryServices.DirectorySearcher($RootDSE)

# Build LDAP filter dynamically
$Searcher.Filter = "(&(objectClass=$ObjectClass)($Attribute=$SearchPattern))"

# Define attributes to return
$Properties = @('cn', 'displayName', 'distinguishedName', 'sAMAccountName')
foreach ($Property in $Properties) {
    $Searcher.PropertiesToLoad.Add($Property) > $null
}

# Execute search
$Results = $Searcher.FindAll()

# Display results
if ($Results.Count -gt 0) {
    Write-Output "Found Objects ($ObjectClass):"
    foreach ($Result in $Results) {
        foreach ($Property in $Properties) {
            Write-Output "$Property: $($Result.Properties[$Property])"
        }
        Write-Output '--------------------------------------'
    }
} else {
    Write-Output "No objects found matching '$SearchPattern' in attribute '$Attribute'."
}

Customizing the Search

This script allows flexibility by modifying:

  • $SearchPattern: The search term (e.g., *Admin* will match any object with “Admin” in the attribute).
  • $Attribute: The LDAP attribute to search against (displayName, sAMAccountName, etc.).
  • $ObjectClass: Defines whether to search for group, user, or computer objects.

Example Use Cases

Find all groups containing ‘Admin’ in their displayname

PowerShell
$SearchPattern = '*Admin*'
$Attribute = 'displayName'
$ObjectClass = 'group'

Find users by a custom attribute (employeedID)

PowerShell
$SearchPattern = '12345'
$Attribute = 'employeeID'
$ObjectClass = 'user'

Find computers by sAMAccountName

PowerShell
$SearchPattern = '*Workstation*'
$Attribute = 'sAMAccountName'
$ObjectClass = 'computer'

Conclusion

Using PowerShell and LDAP queries, we can efficiently search for any Active Directory object without manually iterating through thousands of entries. By directly querying the Global Catalog, we gain a speed advantage, especially in large AD environments. Additionally, this approach does not require the Active Directory module, making it highly versatile for administrators who work in restricted environments or need a lightweight solution.