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:
- How many pipes are active on your system?
- Do you recognize any pipe names?
Step 1.2: Identify system pipes
The following pipes are normal on Windows:
| Pipe | Service |
|---|---|
| lsarpc | Local Security Authority |
| samr | Security Account Manager |
| netlogon | Domain Authentication |
| srvsvc | Server Service |
| wkssvc | Workstation Service |
| spoolss | Print 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
-
Terminal 1: Run the server
.\pipe_server.ps1 -
Terminal 2: Run the client
.\pipe_client.ps1 -
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
-
Screenshots:
- List of your system's pipes
- Server and client in communication
- Detection script executed
-
Answers to the 10 questions
-
Analysis: (1 page)
- Explain how named pipes work
- Describe associated security risks
- Propose detection measures
Evaluation Criteria
| Criteria | Points |
|---|---|
| Pipe enumeration | 20% |
| Functional server/client | 30% |
| Security analysis | 25% |
| Detection script | 25% |
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