Original text by s3cur3th1ssh1t
This post will cover a little project I did last week and is about Named pipe Impersonation in combination with Pass-the-Hash (PTH) to execute binaries as another user. Both techniques used are not new and often used, the
2.05.2021: Update
Unfortunately I learned, that my technique can only be used for local actions, but not for network authentication, as Impersonation Tokens are restricted to that.
Introduction — why another PTH tool?
I faced certain Offensive Security project situations in the past, where I already had the NTLM-Hash of a
So I thought: Other people in the field obviously have the same limitations in existing tools.
My personal goals for a tool/technique were:
- Fully featured shell or C2-connection as the victim user-account
- It must to able to also Impersonate
accounts — depending on engagement goals it might be needed to access a system with a specific user such as the CEO, HR-accounts, SAP-administrators or otherslow privileged
- The tool has to be used on a fully compromised system without another for example linux box under control in the network, so that it can be used as C2-module for example
The Tweet above therefore inspired me, to again search for existing tools/techniques. There are plenty of tools for network authentication via Pass-the-Hash. Most of them have the primary goal of code execution on remote systems — which needs a privileged users Hash. Some of those are:
- SMB (CrackMapExec, smbexec.py, Invoke-SMBExec.ps1)
- WMI (Invoke-WMIExec.ps1, wmiexec.py)
- DCOM (dcomexec.py)
- WinRM (evil-winrm)
If we want to have access to an administrative account and a shell for that account, we can easily use the WMI, DCOM and WinRM PTH-tools, as commands are executed in the users context. The python tools could be executed over a SOCKS tunnel via C2 for example, the Powershell scripts work out-of-the-box locally. SMB PTH tools execute commands as
The best results for local PTH actions are in my opinion indeed Mimikatz’s
Mimikatz’s sekurlsa::pth feature
This part will only give some background information to the
- https://www.praetorian.com/blog/inside-mimikatz-part1/
- https://www.praetorian.com/blog/inside-mimikatz-part2/
A really short high-level overview of the process is as follows:
- MSV1_0 and Kerberos are Windows two Authentication providers, which handle authentication using provided credential material
- The LSASS process on a Windows Operating System contains a structure with MSV1_0 and Kerberos credential material
- Mimikatz
creates a new process with a dummy password for the PTH user. The process is first created in the SUSPENDED statesekurlsa::pth
- Afterwards it creates a new MSV and Kerberos structure with the user provided NTLM hash and overwrites the original structure for the given user
- The newly created process is RESUMED, so that the specified binary like for example
is executedcmd.exe
This part is copy & paste from the part II blog: Overwriting these structures does not change the security information or user information for the local user account. The credentials stored in LSASS are associated with the logon session used for network authentication and not for identifying the local user account associated with a process.
Those of you, who read my other blog posts know, that C/C++ is not my favorite language. Therefore I decided to work with @b4rtik’s SharpKatz code, which is a C# port of the in my opinion most important and most used Mimikatz functions. Normally, I don’t like blog posts explaining a topic with code. Don’t ask me why, but this time I did it myself here. The PTH module first creates a structure for the credential material called
The NtlmHash of this new structure is filled with our given Hash:
if (!string.IsNullOrEmpty(rc4))
ntlmHashbytes = Utility.StringToByteArray(rc4);
if (!string.IsNullOrEmpty(ntlmHash))
ntlmHashbytes = Utility.StringToByteArray(ntlmHash);
if (ntlmHashbytes.Length != Msv1.LM_NTLM_HASH_LENGTH)
throw new System.ArgumentException();
data.NtlmHash = ntlmHashbytes;
A new process in the
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
if(CreateProcessWithLogonW(user, "", domain, @"C:\Windows\System32", binary, arguments, CreationFlags.CREATE_SUSPENDED, ref pi))
In the next step, the process is opened and the
Afterwards, the function
If that resulted in success, the process is resumed via
Named Pipe Impersonation
Thinking about alternative ways for PTH user Impersonation I asked @EthicalChaos about my approach/ideas and the use-case. Brainstorming with you is always a pleasure, thanks for that! Some ideas for the use-case were:
- NTLM challenge response locally via InitializeSecurityContext / AcceptSecurityContext
- Impersonation via process token
- Impersonation via named pipe identity
- Impersonation via RPC Identity
I excluded the first one, because I simply had no idea about that and never worked with it before. Impersonation via process token or RPC Identity required an existing process for the target user to steal the token from. A process for the target user doesn’t exist in my szenario, so only Named Pipe Impersonation was left. And I thought cool, I already worked with that to build a script to get a
For everyone out there, who doesn’t know about Named Pipe Impersonation I can recommend the following blog post by @decoder_it:
Again, I will give a short high-level overview for it. Named Pipes are ment to be used for asynchronous or synchronous communication between processes. It’s possible to send or receive data via Named Pipes locally or over the network. Named Pipes on a Windows Operating System are accessible over the
My first thought about Named Pipe Impersonation in combination with PTH was, that I could spawn a new
.\SharpKatz.exe --Command pth --User testing --Domain iPad --NtlmHash 7C53CFA5EA7D0F9B3B968AA0FB51A3F5 --Binary "\WindowsPowerShell\v1.0\powershell.exe"
What happens in the background? That is explained above. To test, that we are really using the credentials for the user
smbserver.py -ip 192.168.126.131 -smb2support testshare /mnt/share
After opening up the server we can connect to it via simply echoing into the share:
And voila, the authentication as
@decoder_it’s wrote a Powershell script — pipeserverimpersonate.ps1 — which let’s us easily open up a Named Pipe Server for user Impersonation and to open
I tried to access the Pipe via
I also tried using a NamedPipeClient via Powershell — maybe this would result in network authentication with the user
At this point I had no clue on how I could trigger network authentication to localhost for the Named Pipe access. So I gave up on Mimikatz and SharpKatz — but still learned something by doing that. And maybe some of you also learned something in this section. This was a dead end for me.
But what happens exactly when network authentication is triggered? To check that, I monitored the network interface for SMB access from one Windows System to another one:
- The TCP/IP Three-way-handshake is done (SYN,SYN/ACK,ACK)
- Two Negotiate Protocol Requests and Responses
- Session Setup Request,
+NTLMSSP_NEGOTIATENTLMSSP_AUTH
- Tree Connect Request to
IPC$
- Create Request File
testpipe
During my tool research I took a look at @kevin_robertson’s Invoke-SMBExec.ps1 code and found, that this script contains exactly the same packets and sends them manually. So by modifying this script, it could be possible to skip the Windows default behaviour and just send exactly those packets manually. This would simulate a remote system authenticating to our Pipe with the user
I went through the SMB documentation for some hours, but that did not help me much to be honest. But than I had the idea to just monitor the default
Comparing those two packet captures results in only one very small difference.
$SMB_named_pipe_bytes = 0x74,0x00,0x65,0x00,0x73,0x00,0x74,0x00,0x70,0x00,0x69,0x00,0x70,0x00,0x65,0x00 # \testpipe
The result is an local authentication to the Named Pipe as the user
To get rid of the error message and the resulting timeout we have to do some further changes to the
But there still was one more thing to fix. I got the following error from

This error didn’t pop up, when a
Googling this error results in many many crap answers ranging from
Modifying RoguePotato & building one script as PoC
Taking a look at the
Testing the server in combination with our modified Invoke-SMBExec script resulted in no shell at first. The
Still — this is not a perfect solution. Dropping PipeServerImpersonate to disk and executing the script in another session is one option, but a single script doing everything is much better in my opinion. Therefore I build a single script, which leverages Invoke-ReflectivePEInjection.ps1 to execute PipeServerImpersonate from memory. This is done in the background via
This enables us to use it from a C2-Server as module. You could also specify a C2-Stager as binary, so that you will get a new agent with the credentials of the PTH user.
Further ideas & improvements
I see my code still as PoC, because it is far away from being OPSEC safe and I didn’t test that much possible use-cases. Using Syscalls for PipeServerImpersonate and PE-Injection instead of Windows API functions would further improve this for example.
For those of you looking for a C# solution: Sharp-SMBExec is a C# port of
2.05.2021: Update
I also wrote a C# version based on this idea. It can be found here:
The whole project gave me the idea, that it would be really cool to also add an option to impacket’s
2.05.2021: Update
This idea was nice with the background thought, that we have local
Having @itm4n’s article about PrintSpoofer — https://itm4n.github.io/printspoofer-abusing-impersonate-privileges/ — in mind, I also had the idea, if it’s possible to relay a Domain Controllers Computer-Account Hash to our Named Pipe via Spoolsample. This can be done with the MS-RPRN part of the https://github.com/leechristensen/SpoolSample/tree/master/MS-RPRN by using
MS-RPRN.exe \\DomainControllerFQDN \\OutCompromisedSystemFQDN/pipe/pipename
This works perfectly fine, and we therefore can get a shell as Domain Controller computer account:

Using TokenViewer gives us the possibility to see, which Token Type and Impersonation Level we have:

I learned after writing this post and fiddling around with the new impersonated users shells, that
Until someone finds a way to get an
Conclusion
This is the first time, that I created somehow a new technique. At least I didn’t see anyone else using a combination of PTH and Named Pipe Impersonation with the same goal. For me, this was a pretty exciting experience and I learned a lot again.
I hope, that you also learned something from that or at least can use the resulting tool in some engagements whenever you are stuck in a situation described above. The script/tool is released with this post, and feedback is as always very welcome!
20.04.2021: Update
I’m pretty sure, that I before publication of the tool tested the content of Start-Job Scriptblocks for AMSI scans/blocks. And it was not scanned neither blocked. After the publication, Microsoft obviously decided to activate this feature, because the standalone script didn’t work anymore with Defender enabled even after patching

Therefore, I decided to switch from the native
If this description is true,
Links & Resources
- Crackmapexec — https://github.com/byt3bl33d3r/CrackMapExec
- Impacket — https://github.com/SecureAuthCorp/impacket/
- Invoke-TheHash — https://github.com/Kevin-Robertson/Invoke-TheHash/
- evil-winrm — https://github.com/Hackplayers/evil-winrm
- mimikatz — https://github.com/gentilkiwi/mimikatz
- Rubeus — https://github.com/GhostPack/Rubeus
- Inside Mimikatz part I — https://www.praetorian.com/blog/inside-mimikatz-part1/
- Inside Mimikatz part II — https://www.praetorian.com/blog/inside-mimikatz-part2/
- SharpKatz — https://github.com/b4rtik/SharpKatz/
- NamedPipeSystem — https://github.com/S3cur3Th1sSh1t/Get-System-Techniques/blob/master/NamedPipe/NamedPipeSystem.ps1
- Windows Named Pipes Impersonation — https://decoder.cloud/2019/03/06/windows-named-pipes-impersonation/
- PipeServerImpersonate.ps1 — https://github.com/decoder-it/pipeserverimpersonate/blob/master/pipeserverimpersonate.ps1
- SMB Documentation — https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/5606ad47-5ee0-437a-817e-70c366052962
- RoguePotato — https://github.com/antonioCoco/RoguePotato
- Invoke-ReflectivePEInjection — https://github.com/PowerShellMafia/PowerSploit/blob/master/CodeExecution/Invoke-ReflectivePEInjection.ps1
- Sharp-SMBExec — https://github.com/checkymander/Sharp-SMBExec
- NamedPipePTH — https://github.com/S3cur3Th1sSh1t/NamedPipePTH
- PSThreadJob — https://github.com/PaulHigin/PSThreadJob