Analyzing network packets with Wireshark – AD and User Enumeration

It has been a while that I decided to blog, but I’ve been lately into Reverse Engineering. Today, I would like to start my blog series on how I approach a technical topic with the goal to understand the implementation details as much as possible.

This will be a two-series blog post. First, we will start with doing packet capture with Wireshark to learn more about how a binary works on the ‘wire’. The second blog post will be loading the binary into a disassembler and walk through the code, instead of the network packets.

However, for today. This blog post is primary focused on doing packet capture. We will compile C++ code and perform dynamic analysis with Wireshark to see how the activities look on the wire. The goal of this blog post is to make it reproduceable for others, so the same steps can be repeated.

I’d believe that having an understanding of network protocols to some extend can only be beneficial in understanding the implementation details of the overall topic.

How to get started?

First, we have to make sure that we download Microsoft Visual Studio and install C++. Once we have done that, we can start download and compile the binary. https://github.com/fcccode/hunter-1

Select the ‘Release’ build

At Runtime Library, select ‘Multi-threaded (/MT)’

This is how it will look like once we compile the code.

Follow the exact same steps, but for this open-source project: https://github.com/mubix/netview

Network Traffic Analysis

Now that we have compiled the binary. The second step that I’d like to do is analyzing network packets through Wireshark. I have a lab with a few servers and two Domain Controllers. The binary itself contains different parameter options, so what we can do is perform dynamic analysis with Wireshark to see how it looks on the wire. In my lab setup. I have Wireshark installed on every server.

SAMR

Let’s start capturing network packets on a Domain Controller, and in the meantime. Run the following command in Hunter.exe

Enumerating accounts:

Hunter.exe -a 

Now go back to the Domain Controller and see what Wireshark has captured.

Let’s cover the basic flow of the SAMR protocol by analyzing the associated network packets. First, we are establishing an SMB connection to the remote machine.

The second phase is to connect to the IPC$ share on the remote machine. The IPC$ share is used for Inter Proces Communication by using RPC over SMB to allow clients to send different commands to the server to listen users, shares, etc. The third phase is to open the SAMR named pipe.

Fourth phase is to connect to the SAMR interface, which can be recognized by its UUID: 12345778-1234-abcd-ef00-0123456789ac

Once all of these steps have been completed, we can start interacting with the SAMR protocol.

At the connect request, we can see two SAMR Connect specific rights with the likes of SAMR_ACCESS_LOOKUP_DOMAIN to lookup what the domain is, and SAMR_ACCESS_ENUM_DOMAINS to enumerate the domains.

Here we can see what the domain name turns out to be in the request, which happens to be ‘CONTOSO’.

Now we’re requesting to open the domain. This will show us a few SAMR Domain specific rights and includes the SID of the domain.

At the final part, we can see that we’re calling EnumDomainUsers. This is the operation that is responsible for enumerating Domain Users in AD.

Let’s move on to the following option in Hunter. If we specify the -A option (capital A), we will enumerate all the Domain Users with the associated AD attributes.

Hunter.exe -A

There is not much of a difference besides of the following operations QueryUserInfo, GetAliasMembership and OpenUser.

OpenUser will query specific fields that are set on a user. The RID that ends with 502 belongs to the KRBTGT security principal in this case.

QueryUserInfo will query the Domain Users, but this will include the associated AD attributes. We can see an account name with information, such as last logon and the date and time when the password was last changed.

If we scroll a bit down, we even can see what AD attributes have been set on the account. As we can see here, the ACB_PWNOEXP field indicates that the flag ‘Password never expires’ has been set.

GetAliasMembership will retrieve the groups that an account is a member of.

Enumerating groups:

The -g option will enumerate all the AD groups.

Hunter.exe -g

We will see a QueryDisplayInfo2 operation in a packet. Let’s look inside and see what information we get.

QueryDisplayInfo2 will show us the AD group name.

Let’s now use the -m option to enumerate memberships of a specific group.

Hunter.exe -m "Domain Admins"

We can see a few different operations with the likes of LookupNames, OpenGroup, QueryGroupMember, and LookupRids.

LookupNames will look up what the name is for the group that we have queried. In this example, we were querying the Domain Admins group.

OpenGroup will open the group that we are querying and displaying the RID of it. It will also show the SAMR Group specific right, which is set to SAMR_GROUP_ACCESS_GET_MEMBERS. This field will be set to 1, because we were enumerating the Domain Admins group to get a list of members that are part of it.

QueryGroupMember will query all the members that are part of Domain Admin but will only display the RID.

LookupRids will show the account name of each RID that is a member of Domain Admins.

Enumerating Domain Controllers:

The following option -e will enumerate all the Domain Controllers.

Hunter.exe -e

As we can see here. We are generating DNS traffic when we are enumerating Domain Controllers. There is a field indicating ‘Authoritative: Server is an authority for domain’, which indicates that it is very likely a Domain Controller.

SMB

Final command will be the -f option. This allows us to enumerate host information, shares and whether we have local admin access or not. The host.txt is a file that includes the hostnames we’re going to enumerate.

Hunter.exe -f host.txt

We can see that we have enumerated the specified servers. We were able to obtain information about the servers, the readable shares, the IP address of the hostname, and so on.

First, we are connecting over SMB to the remote machine and then connect to the IPC$ share. Furthermore, we are connecting to the \PIPE\srvsvc named pipe, and then connect to the SRVSVC UUID: 4b324fc8-1670-01d3-1278-5a47bf6ee188

After we made a connection to the SRVSVC UUID, we can see that we are calling the NetSrvGetInfo operation.

Let’s expand this packet and see what details we can get. As we can see, we are able to get the server’s name and the type of the server. Indicating that it is a server for example, and not a Domain Controller.

After we have obtained the server information through NetSrvGetInfo. We are attempting to connect to different network shares.

If we expand the network packet that contains the response. We can see the access masks that are associated with the request to access the C$ share.

Last, but not least. How is Hunter.exe able to find where we are a local admin? In short, we are connecting to a remote machine over SMB -> Connecting to the IPC$ share -> Connecting to the \pipe\ntsvcs named pipe -> Connecting to the SVCCTL UUID: 367abb81-9844-35f1-ad32-98f038001003 -> Calling OpenSCManagerW and see if we can request access to the Service Control Manager on the remote server.

When we expand the network packet. We can see both standard and specific rights being set in the request.

Final Part

At the final part, we are going to use a different tool. It can be downloaded here: https://github.com/mubix/netview.

Run the following command:

Netview.exe -f host.txt

Netview does pretty much the same as Hunter, but we are more interested in enumerating users that have a session established with a remote system and the logged-on users.

Let’s focus on the ‘Enumerating Session Info’ first. We can see that Colby has an active session on the AADConnect server. It is calling the NetSessionEnum function to retrieve active sessions on the remote machine.

We first start with connecting to the \PIPE\srvsvc named pipe that is accessible via the IPC$ share over SMB. Furthermore, it is using the SRVS (Server Service Remote Protocol), which is an RPC based protocol that is used for remotely enabling file and printer sharing and named pipe access to the server through SMB.

If we look at the TCP stream, we can see that one user has currently an active session on the machine.

Let’s now take a look at the ‘Enumerated logged-on users’ and see how this works. In order to enumerate the logged-on users on a remote machine. Netview is calling the NetWkastaEnumUsers function.

This works by connecting to the \PIPE\wkssvc named pipe, which is accessible via the IPC$ share over SMB. Furthermore, it is using Workstation Service Remote Protocol. The Workstation Service Remote Protocol (WKSSVC) is used to perform tasks on a computer remotely on a network, including:

Source: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wkst/6793e33e-19fe-4f31-9b1a-e42f389fa790

If we follow the TCP stream, we can see the logged-on users.

Summary

We have used tools like Hunter.exe and Netview.exe to perform dynamic analysis with Wireshark. This allows us to view the activities on the wire and understand how everything flows. Being able to understand to some extend how network protocols work can benefit a lot. The next step is to do something similar, but then understand how it works from a code-level perspective. Stay tuned!

Reference

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s