Skip to main content

Lab 10.1: Windows Named Pipes

Learning Objectives​

By the end of this lab, you will be able to:

  • Understand the mechanism of Windows named pipes
  • Create a pipe server and client in PowerShell
  • Enumerate existing pipes on a system
  • Understand impersonation risks via pipes
  • Detect attacks using pipes

Estimated Duration​

45 minutes

Prerequisites​

  • Windows 10/11 VM
  • Basic PowerShell knowledge
  • Administrator rights

Professional Context​

Named pipes are used by:

  • Windows applications for local communication
  • Services to receive commands
  • Malware for stealthy communication (Cobalt Strike, etc.)
  • Privilege escalation techniques (Potato attacks)

Part 1: Enumerating Named Pipes​

Step 1.1: List active pipes​

PowerShell:

# Method 1: Get-ChildItem
Get-ChildItem \\.\pipe\ | Select-Object Name

# Method 2: .NET
[System.IO.Directory]::GetFiles("\\.\pipe\")

Questions:

  1. How many pipes are active on your system?
  2. Do you recognize any pipe names?

Step 1.2: Identify system pipes​

The following pipes are normal on Windows:

PipeService
lsarpcLocal Security Authority
samrSecurity Account Manager
netlogonDomain Authentication
srvsvcServer Service
wkssvcWorkstation Service
spoolssPrint Service

Compare your list with these standard pipes.

Step 1.3: Use PipeList (Sysinternals)​

If available:

pipelist.exe /accepteula

Questions: 3. Does PipeList show more information than PowerShell? 4. Can you see which process uses each pipe?


Part 2: Creating a Pipe Server​

Step 2.1: Understand the flow​

[Pipe Server]          [Pipe Client]
| |
|<-- 1. Create pipe -->|
| |
|<-- 2. Wait for connection|
| |
|<-- 3. Client connects
| |
|<-- 4. Data exchange -->|
| |
|<-- 5. Close |

Step 2.2: Server script​

Create a file pipe_server.ps1:

# Named Pipe Server
$pipeName = "TestLabPipe"

Write-Host "=== NAMED PIPE SERVER ===" -ForegroundColor Cyan
Write-Host "Creating pipe: \\.\pipe\$pipeName" -ForegroundColor Yellow

# Create the server pipe
Add-Type -AssemblyName System.Core
$pipe = New-Object System.IO.Pipes.NamedPipeServerStream(
$pipeName,
[System.IO.Pipes.PipeDirection]::InOut
)

Write-Host "Waiting for a client connection..." -ForegroundColor Yellow
$pipe.WaitForConnection()
Write-Host "Client connected!" -ForegroundColor Green

# Create read/write streams
$reader = New-Object System.IO.StreamReader($pipe)
$writer = New-Object System.IO.StreamWriter($pipe)
$writer.AutoFlush = $true

# Communication loop
Write-Host "Ready to receive messages (type 'exit' to quit)" -ForegroundColor Yellow
Write-Host ""

while ($true) {
# Read message from client
$message = $reader.ReadLine()

if ($message -eq "exit" -or $message -eq $null) {
Write-Host "Closing connection..." -ForegroundColor Red
break
}

Write-Host "Received: $message" -ForegroundColor White

# Send a response
$response = "Echo: $message"
$writer.WriteLine($response)
Write-Host "Sent: $response" -ForegroundColor Gray
}

# Cleanup
$reader.Close()
$writer.Close()
$pipe.Close()
Write-Host "Pipe closed." -ForegroundColor Red

Step 2.3: Run the server​

.\pipe_server.ps1

The server is now waiting for a connection.


Part 3: Creating a Pipe Client​

Step 3.1: Client script​

Create a file pipe_client.ps1:

# Named Pipe Client
$pipeName = "TestLabPipe"
$serverName = "." # Local

Write-Host "=== NAMED PIPE CLIENT ===" -ForegroundColor Cyan
Write-Host "Connecting to: \\$serverName\pipe\$pipeName" -ForegroundColor Yellow

# Create the client pipe
Add-Type -AssemblyName System.Core
$pipe = New-Object System.IO.Pipes.NamedPipeClientStream(
$serverName,
$pipeName,
[System.IO.Pipes.PipeDirection]::InOut
)

try {
# Connect with 5-second timeout
$pipe.Connect(5000)
Write-Host "Connected to server!" -ForegroundColor Green

# Create streams
$reader = New-Object System.IO.StreamReader($pipe)
$writer = New-Object System.IO.StreamWriter($pipe)
$writer.AutoFlush = $true

# Sending loop
Write-Host "Type your messages (type 'exit' to quit):" -ForegroundColor Yellow
Write-Host ""

while ($true) {
$message = Read-Host ">"

if ($message -eq "exit") {
$writer.WriteLine("exit")
break
}

# Send the message
$writer.WriteLine($message)

# Read the response
$response = $reader.ReadLine()
Write-Host "Response: $response" -ForegroundColor Gray
}

# Cleanup
$reader.Close()
$writer.Close()
$pipe.Close()

} catch {
Write-Host "Error: $_" -ForegroundColor Red
}

Write-Host "Connection closed." -ForegroundColor Red

Step 3.2: Test communication​

  1. Terminal 1: Run the server

    .\pipe_server.ps1
  2. Terminal 2: Run the client

    .\pipe_client.ps1
  3. Send messages from the client

Questions: 5. Does the communication work? 6. Verify that the pipe appears in the list while it is active


Part 4: Security Analysis​

Step 4.1: Pipe permissions​

By default, pipes inherit permissions from the creating process.

Check permissions (requires Sysinternals accesschk):

accesschk.exe -accepteula \\.\pipe\TestLabPipe

Step 4.2: Impersonation risk​

Concept: A pipe server can "impersonate" the connecting client, meaning it can use its security token.

Why it's dangerous:

  • If a privileged user connects to a malicious pipe
  • The server can steal its token
  • And execute commands with its privileges

Step 4.3: Impersonation demonstration (read-only)​

# This code shows how a server COULD impersonate a client
# DO NOT USE IN PRODUCTION - FOR EDUCATIONAL PURPOSES

# In the server, after WaitForConnection():
# $pipe.RunAsClient({
# whoami # Would display the client's identity
# })

Questions: 7. Why is impersonation dangerous? 8. How could an attacker exploit this?


Part 5: Detection and Defense​

Step 5.1: Detect suspicious pipes​

# Script to detect unusual pipes
$knownPipes = @(
"lsarpc", "samr", "netlogon", "srvsvc", "wkssvc",
"spoolss", "browser", "eventlog", "ntsvcs"
)

$currentPipes = Get-ChildItem \\.\pipe\ | Select-Object -ExpandProperty Name

$suspiciousPipes = $currentPipes | Where-Object {
$pipe = $_
-not ($knownPipes | Where-Object { $pipe -like "*$_*" })
}

if ($suspiciousPipes) {
Write-Host "Potentially suspicious pipes:" -ForegroundColor Yellow
$suspiciousPipes | ForEach-Object {
Write-Host " - $_" -ForegroundColor Red
}
} else {
Write-Host "No suspicious pipes detected." -ForegroundColor Green
}

Step 5.2: Monitoring with Sysmon​

If Sysmon is installed:

  • Event ID 17: Pipe Created
  • Event ID 18: Pipe Connected
# View recent pipe events
Get-WinEvent -FilterHashtable @{
LogName = 'Microsoft-Windows-Sysmon/Operational'
ID = 17, 18
} -MaxEvents 20 | Format-Table TimeCreated, Message -Wrap

Questions: 9. Was your test pipe logged? 10. What information does Sysmon capture?


Deliverables​

  1. Screenshots:

    • List of your system's pipes
    • Server and client in communication
    • Detection script executed
  2. Answers to the 10 questions

  3. Analysis: (1 page)

    • Explain how named pipes work
    • Describe associated security risks
    • Propose detection measures

Evaluation Criteria​

CriteriaPoints
Pipe enumeration20%
Functional server/client30%
Security analysis25%
Detection script25%

Reference Commands​

# Enumeration
Get-ChildItem \\.\pipe\
[System.IO.Directory]::GetFiles("\\.\pipe\")

# Sysinternals
pipelist.exe /accepteula
accesschk.exe \\.\pipe\PipeName

# Sysmon
Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Sysmon/Operational';ID=17,18}

Troubleshooting​

Pipe does not create​

  • Ensure the name is unique
  • Run as administrator

Client cannot connect​

  • Ensure the server is started first
  • Check the pipe name (case-sensitive)
  • Check the firewall

Connection timeout​

  • Server must be waiting BEFORE the client connects
  • Increase timeout if necessary

Lab developed as part of the Operating Systems course - MODULE 10