Playing With Named Pipe and NotPetya
A long time ago, in a galaxy far far away, I was having fun reversing NotPetya.
Files dropped by NotPetya
During the dynamical analysis, I identified some files dropped on the disk by the sample.

Files dropped in the disk
An executed file using named pipe
One of them caught my eye: it is executed by the sample with a named pipe argument.

A binary executed with named pipe argument
Finding named pipe in NotPetya
I’ve never played with named pipe before and I was curious about the data that will potentially be exchanged through it. I searched for references of an API using named pipe in the sample.

API related to named pipe in the sample import table
And I found some: CreateNamedPipeW
, ConnectNamedPipe
and so on. I searched through the code calls to these functions and found a section calling:
CreateNamedPipeW
ConnectNamedPipe
PeekNamedPipe

Calls to API related named pipes
Stealing the data exchanged through the named pipe!
During the analysis, I noticed that the binary using named pipe was always dropped in the same directory: C:\Users\%USERNAME%\AppData\Local\Temp
. The file name followed a pattern: 4 alpha-numeric characters and a .tmp
extension.
I managed to retrieve the target binary dropped by the sample to perform some tests.
To access the data exchange between the sample and this binary, I needed to emulate the “named pipe server” set up by the sample. I gathered from the assembly code:
- The sample is creating a named pipe set up as a server on its side
- Waits for a connection on it
- One connection is made, gets all the data in the named pipe.
I coded something reproducing this part of the sample code:
// Emulation of the NotPetya named pipe server
// By Alice Climent-Pommeret
// To compile on linux
// sudo apt install g++-mingw-w64
// i686-w64-mingw32-g++ -static NamedPipeServerNotPetya.cpp -o NamedPipeServerNotPetya.exe
#include <iostream>
#include <windows.h>
using namespace std;
int main(int argc, const char **argv)
{
wcout << "" << endl;
wcout << "Creation of a named pipe called \\\\.\\pipe\\my_pipe" << endl;
//pipe creation
HANDLE pipe = CreateNamedPipe(
"\\\\.\\pipe\\my_pipe", // name of the pipe
3, // PIPE_ACCESS_DUPLEX
6, // PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE
1, // only one instance of the named pipe
0, // no outbound buffer
0, // no inbound buffer
0, // use default wait time
NULL // use default security attributes
);
if (pipe == NULL || pipe == INVALID_HANDLE_VALUE) {
wcout << "The named pipe creation failed";
return 1;
}
wcout << "Waiting for a client connection" << endl;
if (ConnectNamedPipe(pipe, NULL)){// This call blocks the process here until a client connection to the pipe
wcout << "Reading data from the named pipe" << endl;
wchar_t buffer[2048];
DWORD numBytesRead = 0;
// Read data from the pipe
while (ReadFile(pipe, buffer, 2048 * sizeof(wchar_t), &numBytesRead, NULL)){
wcout << "Credentials sent by the NotPetya dropped binary: " << buffer << endl;
}
}
//Close the pipe
CloseHandle(pipe);
wcout << "Done !" << endl;
return 0;
}
To test it, I ran the “named pipe server” in a terminal. At first, the server waits for incoming connections. Then I ran, in an administrator terminal, the dropped binary.
Since the “named pipe server” creates a named pipe called \\.\pipe\my_pipe
, give this as a parameter to the dropped binary.
Annnnnnd…

Calls to API related named pipes
User creds are sent by the mysterious dropped binary… It may be some kind of Mimikatz like…
But this is another topic :)
You can find the C++ source code in this article in my GitHub repository