Enumerating AD with ADSI Searcher
At times during engagements you can find yourself in a situation that sees you without a lovely set of tools that can quickly enumerate the domain for you.
Utilising PowerShell with ADSI searcher will aid you in enumeration without any pre-requisites. The [adsisearcher]
is a shortcut for the .Net object system.directoryservices.directorysearcher. The ADSI searcher was introduced for PowerShell 2.0, which should work on Windows 7/Windows Server 2008 R2 or higher, providing PowerShell hasn't been removed.
This guide assumes you have some basic understanding of PowerShell, if not I highly recommend watching "Learn Windows PowerShell in a Month of Lunches" by Don Jones.
LDAP Queries
In order to use ADSI searcher effectively you need to understand and have knowledge of the LDAP query structure. Here is some of the basics:
- Equal to
(givenName=Bob)
- Logical equal to AND
(&(givenName=Bob)(l=Smith))
- Logical equal to OR
(|(givenName=Bob)(l=Smith))
- Not equal to
(!givenName=Bob)
- Wilcard
(givenName=*Bob*)
Some great guidance and examples can be found on ldapwiki.com. Additionally you can find some great information on the attributes used in Active Directory on SelfADSI.
ADSI Searcher Basics
The below examples assume you have logged on to a domain joined computer that is a member of the domain you are targeting.
Combining an LDAP query with ADSI searcher can quickly enable you to identify many AD objects of interest.
Lets take an example; you need to find all the users who have the word pass within their notes, you could perform the following query:
([adsisearcher]"(info=*pass*)").FindAll()
Now that would return all the results for you to work with but wouldn't give you the finer detail, such as username or the what the note said in full. So you could expand it a little:
([adsisearcher]"(info=*pass*)").FindAll() | %{ $_.GetDirectoryEntry() } | Select-Object sAMAccountName, info
This will now return the sAMAccountName and the corresponding info, should they contain the phrase pass within them.
This giving you a good insight to any objects of interest, in our example above if we had results returned it might have returned a useful password for us to use!
Advanced ADSI Searcher
The above example showed a very basic example of how to enumerate the current domain with information. However if you wanted to query a foreign domain, say for example you found a domain trust, then you need to include an LDAP path with your query.
Take this example, we have a trusted domain named example.com, as the domain is in a 2 way trust our currently logged on user has permissions so no additional authentication is required, this means we can simply do this:
(New-Object adsisearcher([adsi]"LDAP://example.com","(info=*pass*)")).FindAll()
By calling adsisearcher as an object we can pass it 2 parameters, the first being the system.directoryservices.directoryentry object and the second being our query.
The directoryentry detailed above, can be called by its shortcut [adsi]
allowing us a little less typing. If you read the directoryentry objects details, you will notice you can also pass authentication to it as well, this is great if you find yourself with credentials for a domain and you have network access to it, but not able to actually find a machine to logon to. Using the credentials obtained you could remotely authenticate against the domain.
So lets now connect to example.com with credentials against the remote domain from our test machine:
(New-Object adsisearcher((New-Object adsi("LDAP://example.com","domain\username","password")),"(info=*pass*)")).FindAll()
Putting it all Together
Using standard PowerShell cmdlets you can export the information or save it to a variable to work further with it. Lets simply output the results to a GUI grid using the cmdlet Out-GridView
, this allows us to use its simple filters to further narrow down our search and visually see the results. We could also store it to a variable to work with the data further just by prefixing something like this $Result = ...
and then we could call a single result back by issuing $Result[0].GetDirectoryEntry()
where [0]
is the first item in the results returned.
You now have learned the basics of the ADSI searcher object and should have an understanding on how to perform some queries. Next time you run into a situation where you can't use a third party tool or you are trying to discreetly garner information on the target domain, remember to use [adsisearcher]
.