Windows C# / SMB / Named Pipes
Author | Jean-Pierre LESUEUR (DarkCoderSc) |
Platform | Windows |
Language | C# |
Technique | SMB / Named Pipes |
Description:
This code snippet demonstrates how to use Named Pipes in .NET for sending commands and receiving their results. In this example, the named pipe client requests a list of running processes from the named pipe server, which then returns the requested list. It's important to note that this snippet combines both the client and server code for demonstration purposes. In a real-world scenario, the client and server should be separated into two distinct applications and preferably run on two remote systems.
Code
// This example demonstrates how to use named pipes to route commands to a server and retrieve the corresponding responses.
using System.Diagnostics;
using System.IO.Pipes;
using System.Text;
class Program
{
public enum Command
{
ProcessList,
Exit,
}
const string pipeName = "NamedPipeExample";
public static void Main(string[] args)
{
Thread namedPipeServerThread = new(() =>
{
try
{
// https://learn.microsoft.com/en-us/dotnet/api/system.io.pipes.namedpipeserverstream?view=net-7.0?WT_mc_id=SEC-MVP-5005282
using NamedPipeServerStream serverPipe = new(pipeName, PipeDirection.InOut);
serverPipe.WaitForConnection();
using StreamReader reader = new(serverPipe);
using StreamWriter writer = new(serverPipe) { AutoFlush = true };
///
while (true)
{
switch(Enum.Parse(typeof(Command), reader.ReadLine() ?? ""))
{
case Command.ProcessList:
{
StringBuilder sb = new();
foreach (Process process in Process.GetProcesses())
sb.AppendLine($"({process.Id.ToString().PadRight(5, ' ')}){process.ProcessName}");
// Encode as Base64 to send to whole list in one single `WriteLine`
writer.WriteLine(Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(sb.ToString())));
break;
}
default:
{
// Exit or unknown or empty string.
break;
}
}
}
}
catch { }
});
namedPipeServerThread.Start();
Thread namedPipeClientThread = new(() =>
{
try
{
// `.` means local machine, it can be replaced by the network computer name hosting a the named pipe server.
// https://learn.microsoft.com/en-us/dotnet/api/system.io.pipes.namedpipeclientstream?view=net-7.0?WT_mc_id=SEC-MVP-5005282
using NamedPipeClientStream clientPipe = new(".", pipeName, PipeDirection.InOut);
clientPipe.Connect();
using StreamReader reader = new(clientPipe);
using StreamWriter writer = new(clientPipe) { AutoFlush = true };
///
// Ask server for running process
writer.WriteLine(Command.ProcessList);
// Receive response
string? response = reader.ReadLine();
if (response != null)
Console.WriteLine(System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(response)));
// Tell server, we finished our job
writer.WriteLine(Command.Exit);
}
catch { }
});
namedPipeClientThread.Start();
///
namedPipeServerThread.Join();
namedPipeClientThread.Join();
}
}
Created
August 27, 2023
Last Revised
April 22, 2024