Enumeration using the Meterpreter ADSI Extended API Commands
Windows Meterpreter recently got some new capabilities thru the Extended API module by OJ Reeves also known as TheColonial. He added support for:
- Interacting with the Clipboard
- Query services
- Window enumeration
- Executing ADSI Queries
The one that interest me the most is the second one because of many reasons, among them:
I can query Active Directory for information on:
- Users
- Groups
- Policies
- Hosts
I can query most of the information without the need of having Administrator privileges, just domain membership is enough for most or be running as SYSTEM on a machine joined to the domain.
Lets start with the basics, when we get a Meterpreter session we need to check 2 things:
- Is the machine and user I'm running under a member of the Domain?
- Is the current session inside the network with access to a Domain Controller so it can query AD?
There are several methods you can do by hand for this like checking list of processes and running getuid to see if we see Domain Membership under the users, but I prefer to automate any small tasks like that and for that Meterpreter Scripts are wonderful since they do not have that added typing and complexity of a post module for a simple task. For this I wrote a simple script I called get_domain name that can be found at
meterpreter > run get_domain_name -h Meterpreter Script for showing the domain name and prefered domain a host is a member of and the prefered DC. Author: Carlos PerezOPTIONS: -h Help menu. meterpreter >
NOTE: IF you see anyone writing a Meterpreter script without a help block slap him for me :)
The script will do 2 things:
- Check if the machine is part of a domain.
- Identify the preferred domain controller and try to resolve its name to IP.
By trying to resolve the Domain Controller IP I can check if I'm in the domain or not. Execution is simple with the Run command:
meterpreter > run get_domain_name [+] Domain: ACMELAB1 [+] Domain Controller: DC2.acmelab1.com [+] IPv4: 10.10.10.3 [*] Could not resolve IPv6 for DC2.acmelab1.com
Here we can see the host is in a domain named ACMELAB1 and that we can resolve the IP Address of the Domain Controller.
To query ADSI we need to fist load the Extended API extension, for this like with any other extension we use the Load command:
meterpreter > load extapi Loading extension extapi...success.
If we use the help command or its alias ? we can see the commands are now available inside of the Meterpreter session:
meterpreter > ? .... Extapi: Window Management Commands ================================== Command Description ------- ----------- window_enum Enumerate all current open windows Extapi: Service Management Commands =================================== Command Description ------- ----------- service_enum Enumerate all registered Windows services service_query Query more detail about a specific Windows service Extapi: Clipboard Management Commands ===================================== Command Description ------- ----------- clipboard_get_data Read the victim's current clipboard (text, files, images) clipboard_set_text Write text to the victim's clipboard Extapi: ADSI Management Commands ================================ Command Description ------- ----------- adsi_computer_enum Enumerate all computers on the specified domain. adsi_domain_query Enumerate all objects on the specified domain that match a filter. adsi_user_enum Enumerate all users on the specified domain.
2 of the ADSI commands simplify the process of enumeration using it, these are: * adsicomputerenum - does basic computer account enumeration. * adsiuserenum - this one does basic user enumeration.
If we look at the help options for one of the commands we will see they all have a Page Size and a Maximun number of results to get, this is becase AD can be very big and it can overwhelm Meterpreter.
meterpreter > adsi_computer_enum -h Usage: adsi_computer_enum[-h] [-m maxresults] [-p pagesize] Enumerate the computers on the target domain. Enumeration returns information such as the computer name, desc, and comment. OPTIONS: -h Help banner -m Maximum results to return. -p Result set page size.
Lets enumerate computer account:
meterpreter > adsi_computer_enum acmelab1 acmelab1 Objects ================ name distinguishedname description comment ---- ----------------- ----------- ------- CLIEN01 CN=CLIEN01,CN=Computers,DC=acmelab1,DC=com COLLECTOR CN=COLLECTOR,OU=International Marketing,OU=Marketing,DC=acmelab1,DC=com DC1 CN=DC1,OU=Domain Controllers,DC=acmelab1,DC=com DC2 CN=DC2,OU=Domain Controllers,DC=acmelab1,DC=com DC3 CN=DC3,OU=Domain Controllers,DC=acmelab1,DC=com Total objects: 5
In the domain field we can also provide a LDAP Distinguished name also to control the scope of the query:
meterpreter > adsi_computer_enum 'OU=Domain Controllers,DC=acmelab1,DC=com' OU=Domain Controllers,DC=acmelab1,DC=com Objects ================================================ name distinguishedname description comment ---- ----------------- ----------- ------- DC1 CN=DC1,OU=Domain Controllers,DC=acmelab1,DC=com DC2 CN=DC2,OU=Domain Controllers,DC=acmelab1,DC=com DC3 CN=DC3,OU=Domain Controllers,DC=acmelab1,DC=com Total objects: 3
For user accounts it functions in the same manner:
meterpreter > adsi_user_enum acmelab1 -m 10 -p 10 acmelab1 Objects ================ samaccountname name distinguishedname description comment -------------- ---- ----------------- ----------- ------- Administrator Administrator CN=Administrator,CN=Users,DC=acmelab1,DC=com Built-in account for administering the computer/domain CLIEN01$ CLIEN01 CN=CLIEN01,CN=Computers,DC=acmelab1,DC=com DC1$ DC1 CN=DC1,OU=Domain Controllers,DC=acmelab1,DC=com DC2$ DC2 CN=DC2,OU=Domain Controllers,DC=acmelab1,DC=com DC3$ DC3 CN=DC3,OU=Domain Controllers,DC=acmelab1,DC=com Guest Guest CN=Guest,CN=Users,DC=acmelab1,DC=com Built-in account for guest access to the computer/domain cperez carlos Perez CN=carlos Perez,CN=Users,DC=acmelab1,DC=com helpdesk IT Helpdesk CN=IT Helpdesk,CN=Users,DC=acmelab1,DC=com krbtgt krbtgt CN=krbtgt,CN=Users,DC=acmelab1,DC=com Key Distribution Center Service Account krbtgt_28732 krbtgt_28732 CN=krbtgt_28732,CN=Users,DC=acmelab1,DC=com Key Distribution Center service account for read-only domain controller Total objects: 10
Now the command that provides the greatest flexibility is the the adsi_domain_query command since this one lets you craft your own queries and specify what fields you want. For these we need to use the LDAP Filtering Syntax, one of the best resources I have found for this is the SelfADSI page
Lets look for disabled accounts, get their name, disguishedname and description:
meterpreter > adsi_domain_query acmelab1 (&(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=2)) name distinguishedname description acmelab1 Objects ================ name distinguishedname description ---- ----------------- ----------- Guest CN=Guest,CN=Users,DC=acmelab1,DC=com Built-in account for guest access to the computer/domain User15 CN=User15,CN=Users,DC=acmelab1,DC=com User28 CN=User28,CN=Users,DC=acmelab1,DC=com User36 CN=User36,CN=Users,DC=acmelab1,DC=com krbtgt CN=krbtgt,CN=Users,DC=acmelab1,DC=com Key Distribution Center Service Account krbtgt_28732 CN=krbtgt_28732,CN=Users,DC=acmelab1,DC=com Key Distribution Center service account for read-only domain controller Total objects: 6
Lets find all OUs in the Domain:
meterpreter > adsi_domain_query acmelab1 (objectclass=organizationalunit) name distinguishedname acmelab1 Objects ================ name distinguishedname ---- ----------------- Domain Controllers OU=Domain Controllers,DC=acmelab1,DC=com ITS OU=ITS,DC=acmelab1,DC=com International Marketing OU=International Marketing,OU=Marketing,DC=acmelab1,DC=com Local Marketing OU=Local Marketing,OU=Marketing,DC=acmelab1,DC=com Marketing OU=Marketing,DC=acmelab1,DC=com Sales OU=Sales,DC=acmelab1,DC=com Total objects: 6
On tip when always testing queries is to use the name and disguishedname fields since these are present in most objects you query for and are useful for quick test.
Based on the module and work from Metasploit contributor MearBalls on the enum_ad_computers module I wrote several post modules that I maintain in my own GitHub repo for enumerating AD information so as to not have to remember the queries and it saves to DB and Loot the info depending on the module. They can be found at
As always I hope you found the blog post useful.