In part II of this three-part series, we dive deeper into hands on examples of identifying usage of named pipe servers within applications using a custom vulnerable application. The methods covered to achieve this goal is through usage of both dynamic and static analysis.
Before starting the analysis of the vulnerable named pipe application, it is important to become familiar with how to analyze named pipes using dynamic and static analysis techniques.
The following sections will discuss the differences between these two techniques and how different tools can be utilized to accurately gain information about named pipe behavior in an application.
Dynamic analysis is beneficial for a quick and somewhat accurate initial analysis of what a process or application is doing during runtime. Several tools are available for performing dynamic analysis on named pipes, some of which can be seen in the list below:
SysInternals Suite of Tools
A common tool that is utilized by VS-Labs during initial analysis is
Process Explorer from the
Process Explorer is a versatile tool that provides great insight into the current runtime activities of a process and or application.
Upon initially starting
Process Explorer, a graphical user interface (GUI) is shown, as can be seen below in Figure 3:
Next, the option to view open handles that a process or application has created is enabled by navigating to
View followed by
Lower Pane view and then
Handles. This sequence of events can be seen in Figure 4 shown below.
After enabling the
Handles option, navigate to the new window that has been opened and look for the object type called
Note that not every
File object is considered a named pipe; some of these objects are handles to real files on the system. Therefore, it is advisable to review the output from
Process Explorer carefully.
An example of the type of information that is presented from
Process Explorer can be seen in Figure 5 below, which demonstrates how users can quickly and efficiently identify processes that are utilizing named pipes.
Another tool commonly used for dynamic analysis of named pipes is
Accesschk. This tool is also a part of the
SysInternals Suite and it allows the effective enumeration of every active
named pipe on the system along with the permissions associated with these pipes.
To gather this information, pass the string
Accesschk via the command-line interface. An example of the output from running this tool can be seen in Figure 6 below.
Reviewing the output reveals information about the permissions assigned to various named pipes.
Note that some results may hold the value of
Error getting security: All pipe instances are busy. This response indicates that the maximum allowed number of instances for these specific pipes has been reached.
All other named pipes that have not reached the maximum allocated instances have their respective permissions displayed as can be seen with the
InitShutdown named pipe.
Static analysis allows researchers to analyze a program without running it. Some examples of tools that can perform static analysis are
IDA Pro from
Ghidra from the
NSA. This post will utilize
IDA Pro as it is the most mature platform for static analysis on Windows.
When performing static analysis to identify if a program is utilizing named pipes it is useful to examine several functions. These functions fall under three categories: creation, retrieving data, and writing data.
These categories can be seen in the tables below:
One important thing to note about the tables above is that both client and server related code use the same functions for retrieving data from and writing data to named pipes.
This occurs because named pipes are treated as files, so Windows API functions such as
WriteFile() can operate on named pipes as they would a normal file.
Although reading and writing to a pipe involves similar calls for both client and server code, pipe creation is a different matter. For server code, there is
CreateNamedPipe(), which will create a named pipe, and
ConnectNamedPipe(), which is used to start communication over a named pipe.
For client code, there is
CreateFile(), which is used to connect to a pipe and start communications, and
CallNamedPipe(), which connects to a named pipe, conducts a read or write operation, and then closes the pipe.
An example of how
CreateNamedPipe() is utilized can be seen in the image below (note that the Unicode variant of
CreateNamedPipe() is being called here, hence why the function name is
Now that the basics of named pipes have been covered, it is now time to analyze VS-Labs vulnerable named pipe server.
This vulnerable named pipe server currently implements four logic-based vulnerabilities.
This section will discuss how to identify the utilization of named pipes within this server, as well as how to read and write data to the named pipe that the program creates.
Interested readers can follow along by downloading the vulnerable named pipe server code from this GitHub link.
It is recommended to review the
README file to ensure proper deployment of the vulnerable named pipe server.With the server set up, the next step is to perform initial reconnaissance to gather information about the application.
To start off the analysis,
SysInternals Suite will be utilized. After running
Procexp64.exe as an
Administrator, enable the
Handles view option.
Next, search inside of the main window that lists all the active processes, select and highlight the name
If everything is set up correctly, then the target executable should be highlighted and the handles view should be visible.
This should look something like the following screenshot:
By reviewing Figure 8 shown above, it is possible to observe the presence of a potential named pipe called
NinjaReally. To discover what users and/or groups have access to read or write data to this pipe, utilize
The complete named pipe name,
\Pipe\NinjaReally, is passed in as the argument to
accesschk.exe to specify the specific pipe to enumerate (note that if
\Pipe\ was used instead, then every single active named pipe would be enumerated).
The output from this command can be seen below.
CMD> accesschk.exe \Pipe\NinjaReally Accesschk v6.12 - Reports effective permissions for securable objects Copyright (C) 2006-2017 Mark Russinovich Sysinternals - www.sysinternals.com \.\Pipe\NinjaReally RW NT AUTHORITY\SYSTEM RW BUILTIN\Administrators RW DESKTOP-XXXXXX\TEST R Everyone R NT AUTHORITY\ANONYMOUS LOGON
Reviewing the output reveals that that the user
(W)rite to this named pipe.
The other groups such as
Everyone can only
(R)ead from the named pipe.
Now that the named pipe
NinjaReally has been identified within
NamedPipe_Examples.exe using dynamic analysis, let’s examine how the same steps can be performed with static analysis using
NamedPipe_Examples.exe is loaded into
IDA Pro, the first task is locating the function responsible for creating a named pipe.
This function is called
CreateNamedPipeW() and can be located by navigating to the
Import window of
IDA Pro, which shows the functions that a program imports from other modules and DLLs. Figure 9 below shows
Import window after a filter on
CreateNamedPipe was applied.
In order to reference where
CreateNamedPipeW() is being used within
NamedPipe_Examples.exe, one can use
IDA Pro's cross-referencing feature to view all instances in the code where
CreateNamedPipeW() is called.
To utilize this feature, double click with the left mouse button on the
CreateNamedPipeW() function inside of the
The view should change to the
IDA View-A window, and the function name should be visible.
Next, double click (highlight) the function name and hit the
X key whilst the function name is highlighted. A new dialog box should be displayed, showing all the cross-references to the
CreateNamedPipeW() function; it should look similar to Figure 10 shown below.
Please note that offset inside of the
Address column is subject to change depending on the version of
NamedPipe_Examples.exe that is being disassembled.
Next, navigate to an entry in the xrefs popup window and double click it. After double-clicking an entry,
IDA Pro will open up a disassembly view of the exact location in
NamedPipe_Examples.exe where the selected call was made. This behavior can be seen in Figure 11 shown below.
The disassembly reveals that the named pipe
NinjaReally, which was found earlier with
ProcExp64.exe, is indeed being created within
NamedPipe_Examples.exe via a call to
Now that the code responsible for creating the named pipe server has been identified, the final step is a sanity check to make sure that the
TEST user can write data to the
NinjaReally named pipe server.
To check that the
TEST user can write data to the
NinjaReally named pipe, it is necessary to create a named pipe client. This can be accomplished using a multitude of languages; for the purposes of this post C++ will be utilized.
Using the knowledge that named pipes are treated as
file objects, it is possible to write up appropriate code by utilizing the functions
The code will first call
CreateFile() with the string
\\\\.\\pipe\\NinjaReally as the first argument to establish a handle to the named pipe server. A handle is an integer value data type declared and referenced as
HANDLE within the Windows API, and it is used to reference a specific instance of an object within the windows operating system.
After obtaining the handle, the next step is to send data to the named pipe server. To do this the named pipe is treated as a file and the
WriteFile() function is used to write the desired data to the named pipe.
As the server may respond to data sent to its named pipe, the code also calls
ReadFile() on the named pipe to read responses sent by the server into a local buffer in the client code.
When all operations are complete, a call to
CloseHandle() is made to destroy the active
HANDLE that was being used to interact with the named pipe. Figure 12 shown below illustrates how all these operations work and how they interact with one another.
Note that in the diagram displayed above the server’s response, and the client’s parsing of the server’s response, are marked with the
*OPTIONAL* tag, as these steps are not performed with
Half-duplex named pipes.
Additionally, it is important to note that this outline is only an overview of the communication cycle based off what VS-Labs researchers have observed in real world applications. It is possible that an application could deviate from this behavior in some manner, so it is advisable to take care when researching targets.
Now that a proper understanding of how a client communicates to a named pipe server has been acquired, one final approach that can be used to perform reconnaissance is to use the tool
IO Ninja from
Tibbo Technology Inc.
IO Ninja is capable of monitoring data sent between named pipe servers and clients accurately. Using
IO Ninja, it is possible to record the communication between the client and the server, which will consist of the following operations:
IO Ninja to record the events listed above one can gain a visual understanding of the communications between the client and the server. A short video depicting
IO Ninja recording the communications between the client application and the named pipe server can be seen below. This video demonstrates that it is possible for the client to write data to the named pipe server successfully as the
Please keep the following points in mind whilst reviewing the video:
By reviewing the video, one can see that the data which was sent from the client to the server was recorded by
Pipe Monitor successfully. Because data sent from the client to the server was successful and the server did not reject the client’s request to
WRITE data, one can verify that the output from
accesschk.exe was correct: lower privileged users such as
TEST can indeed write data to the named pipe, which is running at a higher privilege level. This can lead to privilege escalation depending on the type of functionality exposed by the named pipe server.
Improper permission assignment on critical resources is a common finding during VerSprite’s engagements. The impact of improper permissions assignment can range from information leakage to code execution.
To counter this, when handling the access control’s around named pipe servers, it is essential to apply proper controls. By applying proper access controls, and proper checks on potentially malicious data, the vulnerabilities in this intentionally vulnerable named pipe server would not be exploitable.
In this part II of this three-part series, we covered a detailed a hands-on approach to performing both static and dynamic analysis for discovering usage of named pipe servers within applications.
Stay tuned for the final blog post in this part-three series: An In-Depth Exploration of How to Reverse Engineer a Custom Protocol and Exploit a Vulnerable Named Pipe Server. Subscribe and receive notifications on this three-part blog series →
Maintain awareness regarding unknown threats to your products, technologies, and enterprise networks. Organizations that are willing to take the next step in proactively securing their flagship product or environment can leverage our zero-day vulnerability research offering. Our subscription-based capability provides your organization with immediate access to zero-day vulnerabilities affecting products and software. Learn More →