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 Perez 

OPTIONS:

    -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 The command differs from the rest in that it lets you build your query and you can specify the fields. This can get tricky if you have no previous experience with LDAP and AD. You can check in MSDN, user PowerShell [adsisearcher] accelerator or use ADSI Edit on a lab Domain to figure the fields.

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 all module start with enum_ad_.

As always I hope you found the blog post useful.