Pentest Limited logo


Researching Remote Procedure Call (RPC) vulnerabilities


Ibai Castells


In the past few years, several high and critical severity vulnerabilities have been found in Windows RPC by individuals and professional research teams. Windows RPC allows clients to call functions on remote hosts. This opens the doors to potential vulnerabilities that could be exploited remotely to cause denial of service issues, elevate privileges and even remote code execution (RCE). For these reasons, RPC is an interesting area of research.

Throughout this post, we will explain:

– What RPC is and how it works
– History of past RPC vulnerabilities found
– How to setup your research environment and start hunting for bugs

What is RPC and How Does it Work?

Remote Procedure Call (RPC) is a protocol that allows one program to request a service from another program located on another computer on a network without having to understand the network’s details. RPC is used by many Windows services and applications to communicate with other systems on the network. It works on a client-server basis where the client connects to the target interface and calls procedures of that interface which are executed on the server host.

RPC interfaces are defined using an Interface Definition Language (IDL), which defines the interface’s function signatures. A binding handle is used to connect to the target interface and invoke functions of that interface.

There are multiple types of binding handles, each one defining how much work must be done by the client to interact with the interface. These include automatic, implicit, and explicit binding handles.

Additionally, every interface has a few properties that define them and are needed to connect to them. These are:

protocol: the communication method being either TCP/UDP, named pipes or local RPC
provider: The exe or DLL which exposes the interface and its procedures
UUID: A unique identifier in the form of an alphanumeric string
binding string: Equivalent to an IP address or FQDN but for the interface and the server host

Once we have all those pieces of information, we can begin to create our RPC clients and start calling procedures for the interfaces we connect to.

We can find these bits of information using tools like RPCView or impacket’s rpcdump as shown below.

With this information, we can connect to the interface, by passing them to our client, and a **binding handle** will be created which is then used to communicate with the interface.

History of RPC vulnerabilities

RPC interfaces have been the source of many vulnerabilities in Windows over the years. Here are some well-known bugs that have been found somewhat recently:

CVE-2022-26809: A heap buffer overflow in the rpcrt4.dll DLL leading to RCE
PetitPotam: A coercion bug on the MS_EFSR interface
PrintNightmare: A bug that gives attackers RCE by setting an arbitrary printer driver via RPC procedures.

CVE-2022-26809 is a critical remote code execution vulnerability in the Remote Procedure Call Runtime Library. A remote, unauthenticated attacker could exploit this vulnerability to take control of an affected system.

PetitPotam is a vulnerability that allows attackers to take over Windows domains and servers by abusing the MS-EFSRPC protocol. This protocol is used by Windows for encrypting files on disk and can be abused by causing coercion bugs to capture machine account hashes which can then be used in NTLM relay attacks for movement across a network.

PrintNightmare is a vulnerability that allows attackers to execute code remotely with SYSTEM privileges by abusing the Windows Print Spooler service. This service is used for managing print jobs on Windows systems and can be abused by attackers to gain access to sensitive data and executing commands with high privileges.

Research Methodology

There are multiple workflows and setups to start hunting for vulnerabilities in RPC interfaces. Throughout this section, one method will be explained which we considered to be the fastest, however, it was found that deviating and using different tools in different situations was sometimes a better option than sticking to a strict toolset.

In order to find vulnerabilities with a realistic impact, a realistic environment was necessary. In our case, we used a minimalistic Snaplabs template that included:

– Windows Domain Controller
– Kali host on the internal network
– Windows Server 2019

All hosts were fully up to date and in their default configuration. Additionally, a few domain users with different privileges were created. This specific Snaplabs template also incorporated simulated user activity which was convenient as it created processes as expected in a real network which expanded the attack surface giving us more to explore.

The next step was to setup the tooling. Several tools were used during the research.

First, RPCView was used to understand what interfaces were being used by what processes and what protocols these interfaces used to transfer data (LRPC, TCP/UDP, named pipes). For a reference on how to set RPCView up, refer to itm4n’s blog post in the references section. The most important part of the setup is to ensure that one loads the symbols for all the Windows DLLs. As a quick summary on how to setup RPCView:

1) Download RPCView

2) Download and Install the Windows 10 SDK

3) In PowerShell, run:

					cd "C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\"

symchk /s srv*c:\SYMBOLS* C:\Windows\System32\*.dll


4) In RPCView got to Options > Configure Symbols and in the textbox set it to:


then click “Ok”

5) Finally, change the refresh speed to a slower one to make the output more manageable. 10 seconds for example.

					Options -> Refresh Speed -> 10 seconds

As processes are executed, RPCView will show you which interfaces are being used and what procedures those interfaces offer. The next useful tool to progress in the research is Process Monitor.

Process Monitor (aka ProcMon) is useful in two ways. First, it allows the researcher to map file, network and registry operations with the process that initiated them. When an RPC procedure is executed, ProcMon will show what files, registry keys and hosts the process is interacting with as well as properties of the operation such as the user that initiated the task. This helps us as we can see if a procedure that was called as a low privilege user performs operations as a high privilege one such as `NT AUTHORITY\SYSTEM`. Additionally, ProcMon allows us to look at the process call stack which reveals the functions that are being called and which DLL they are stored in.

Ghidra or IDA Pro, with imported Windows exe and DLL symbols, is also a good tool to combine with procmon in order to decompile and debug relevant DLLs for the interface we are testing.

Lastly, we had to figure out a way to interact with the RPC interfaces. NtObjectManager was the preferred tool for this as it is able to parse RPC interfaces and create clients for them with ease. Additionally, it includes several helper functions to create objects with specific data types which are often necessary to pass to procedures for valid calls. To setup NtObjectManager, the following steps should be carried out.

First install NtObjectManager via Powershell on the host.

					Install-Module -Name NtObjectManager -RequiredVersion 1.1.32

Then bypass script execution and import NtObjectManager module. Additionally, set the dbghelp.dll path.

					Set-ExecutionPolicy Bypass -Scope Process

Import-Module NtObjectManager

Set-GlobalSymbolResolver -DbgHelpPath 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\dbghelp.dll'

Discover RPC servers in default Windows installs. This stores them all in a variable called allrpc which holds the DLL name, UUID, running state, version, etc… in table format.

					$allrpc = ls "C:\Windows\system32\*" -Include "*.dll","*.exe" | Get-RpcServer

We are now set up to start searching for interesting procedures and connecting to their interfaces by creating an RPC client.

As an example, we can try to connect to the MS_EFSR interface which is where the PetitPotam coercion bug originates from.

					$efsrpc = $allrpc | ? { $_.InterfaceId -eq 'c681d488-d850-11d0-8c52-00c04fd90f7e' }

We know that this interface offers a named pipe for communication so in order to create our RPC client to connect to it we run the following command.

					Connect-RpcClient -Client $Client -StringBinding "ncacn_np:[\\pipe\\lsass]" -AuthenticationLevel PacketPrivacy -AuthenticationType WinNT -Credentials $(Get-LsaCredential -UserName "kreep" -Domain "domain" -Password "password123")

We can check if the client connected successfully as follows:

					PS C:\Users\kreep> $client.Connected


This process is significantly faster than creating an RPC client from scratch in .NET, C or even in Python using impacket.

We can now check what procedures the interface offers now that we are connected to it.

					PS C:\Users\kreep> $client | gm

TypeName: Client

Name                                        MemberType Definition

----                                        ---------- ----------

Connect                                     Method     void Connect(NtApiDotNet.Win32.RpcEndpoint endpoint, NtApiDotNet.Win32.Rpc.Transport.RpcTransportSecurity transport_security), vo...

Disconnect                                  Method     void Disconnect()

Dispose                                     Method     void Dispose(), void IDisposable.Dispose()

EfsRpcAddUsersToFileEx_Downlevel            Method     int EfsRpcAddUsersToFileEx_Downlevel(int p0, System.Nullable[Struct_8] p1, string p2, Struct_5 p3)

EfsRpcAddUsersToFile_Downlevel              Method     int EfsRpcAddUsersToFile_Downlevel(string p0, Struct_5 p1)

EfsRpcCloseRaw_Downlevel                    Method     EfsRpcCloseRaw_Downlevel_RetVal EfsRpcCloseRaw_Downlevel(NtApiDotNet.Ndr.Marshal.NdrContextHandle p0)

EfsRpcDecryptFileSrv_Downlevel              Method     int EfsRpcDecryptFileSrv_Downlevel(string p0, int p1)

To complete the example, we can call one of the procedures used in PetitPotam being `EfsRpcEncryptFileSrv_Downlevel` to issue an NTLM authentication to our attacker controlled Kali machine with Responder listening.


Once the call is completed, we will see the machine account hash for the target host in our Responder terminal on our attacker host.

This is essentially the process undertaken for this research. NtObjectManager contains useful functionality to help us search procedures by name or even check for procedures that take files, impersonation tokens, sockets, etc. as parameters. Ideally, in future iterations of research, it would be best to automate the process using PowerShell scripts to fuzz different procedures and log the output. This will be the next step in the research.

Low hanging fruit vulnerabilities

Despite the many vulnerabilities that have been found in RPC interfaces over the years, there are still many low hanging fruit vulnerabilities that can have a high impact. For instance, it’s always worth investigating when low-privileged users initiate file operations that are then performed by privileged processes like services running as SYSTEM as they can uncover privilege escalation primitives. Additionally, coercion bugs and denial of service vulnerabilities are still being discovered on a semi-regular basis.

Closing Notes

In this blog post, we’ve discussed how RPC works and how it’s used in Windows services and applications. We’ve also discussed some well-known bugs related to Windows RPC, as well as some tools and techniques for identifying vulnerabilities in RPC interfaces.


Looking for more than just a test provider?

Get in touch with our team and find out how our tailored services can provide you with the information security confidence you need.