Extending C2 Lateral Movement – Invoke-Pbind

Invoke-Pbind is a mini post exploitation framework written in PowerShell, which builds C2 communications over SMB named pipes using a push rather than a pull mechanism. Pbind was initially created to overcome lateral movement problems, specifically in restricted environments where the server VLAN could not directly talk to the user VLAN (as it should be in every environment). The tool was designed to be integrated with any C2 framework or run as a standalone PowerShell script.

Video Demonstration

If you just want to skip to the video tutorial, then you can find that here and at the end of this post.

The Problem: Segregation and Strict Firewalling

This is useful when you have compromised an organisation and have C2 comms over HTTPS, traversing the corporate proxy server out of the network from user’s workstations, but the target dataset that you are looking to obtain is located down server VLAN with a firewall restricting both inbound and outbound traffic. In that scenario, firewall rules are always going to allow for specific traffic to traverse over pre-approved services. The following diagram illustrates one such situation, where the environment allows limited services from the user VLAN to the server VLAN, but allows no ports in the reverse direction.

What options exist for C2 comms

The following are some options for C2 comms and their mitigations, resulting in failure.

Method Mitigation Result
Direct Internet Access Blocked by Firewall Outbound Fail
Traverse Through HTTP Proxy Blocked by Firewall Outbound Fail
TCP Reverse Shell Blocked or likely detected scanning for open ports Fail
TCP Bind Shell Blocked by Firewall Inbound or service running on open ports, no closed ports detected Fail
ICMP Blocked by Firewall Outbound Fail
Daisy over SMB in User VLAN TCP port 445 blocked from servers to workstations Fail
Daisy over HTTP in User VLAN Same as standard reverse all blocked ports Fail
DNS Authoritive DNS is only permitted by the Proxy server, thus not possible for C2 comms from the server VLAN. Fail

To be clear, at this point the problem isn’t about getting execution, it’s about having reliable C2 comms that afford the user output for all commands executed and to use the implant as a foothold or staging point to further attacks against servers in the restricted environment.

The Solution

“A named pipe is a logical connection, similar to a Transmission Control Protocol (TCP) session, between the client and server that are involved in the CIFS/SMB connection. The name of the pipe serves as the endpoint for the communication, in the same manner as a port number serves as the endpoint for TCP sessions. This is called a named pipe endpoint.” – https://msdn.microsoft.com/en-us/library/cc239733.aspx.

.NET has a class for creating and interacting with named pipes:

Where TCP port 445 is open into a server environment, we can overlay the SMB protocol and use a named pipe to share data between the workstation and server, providing a method for exchanging data (comms). The following commands make up the basis of creating a named pipe with an access rule that allows “everyone” access:

Since the days of abusing IPC$ with anonymous access (CVE-199-0519), and RID cycling your way to a plethora of goodies, Microsoft have said “no – though shall not pass” – non Microsoft direct quote. In a domain environment, any user can create a domain authenticated session to the $IPC share, which can then be piggy backed to gain access to the named pipe. Here is a simple script in PowerShell to create an authenticated session. One quick problem to overcome: While the ‘AccessRule’ applied to the pipe may look like it allows “everyone” access to the named pipe, this is not actually the case.

Interacting with a named pipe is also fairly straight forward as long as you know the data type of what is being read; as we create the server we know how to handle to pipe as shown by using a simple StreamReader:


When we came up with Invoke-Pbind, the following principles were implemented.

Client/Server Model

To allow for inclusion in a C2 framework, two script blocks were created, client and server. The server starts and sets up the named pipe on a remote target (server). The client then connects to the named pipe and exchanges messages over TCP port 445 (SMB). The client runs through an existing C2 implant and by using script blocks and run spaces, it is possible to use the client non-interactively for better interaction with most C2 frameworks.

Token Passing

When sharing a common space such as a named pipe, it is imperative that messages exchanged between the client and server are not overwritten prior to being picked up by their counterpart. Control messages are used in combination with TRY and IF statements to create rules for when a client or server should read or write from the named pipe.


During the generation of the script blocks, at run time, a unique key is generated and used to encrypt messages between client and server. Pbind supports AES 256 encryption. To initiate a connection to the named pipe from a client, a shared secret is also supported to stop tampering with the named pipe. If the client does not provide the correct secret, the named pipe will close.


There are two main methods included that inject the implant into target hosts. These are modified versions of Invoke-WMIExec and Invoke-SMBExec (credit to Kevin Robertson for these scripts); both scripts have been updated to support passing passwords, where previously they only accepted hashes for authentication. The implant is a self-executing script block that is passed as the payload. The script runs WMIExec by default but contains a switch parameter to invoke SMBExec:

To provide additional deployment flexibility the script also includes an exe method. This method uses CSC and Windows .Net automation DLL to compile the implant into an executable that can then be deployed and executed through any means.

NOTE: Creating a named pipe does not require administrator credentials so the executable can be run as a non-privileged user. On the other hand, WMIExec and SMBExec require administrator privileges.

The exe option continues to generate unique variables that are hardcoded into the executable, for use in cryptography and such like. The exe option can be used offline to create an executable implant and is not tied to an interactive session through a C2. To talk to the implant, the script supports a CLIENT option that is used to interact with a deployed implant, the options for which are provided when the implant is compiled:

This flexibility allows for the deployment through any means:

  • DCOM
  • RDP
  • Shared Folders
  • WinRM
  • SCCM
  • Anything……

There are a number of options that are configurable. If no options are selected, the script reverts to pre-set or randomly generated values. The following options are configurable:

  • KEY – Defaults to a randomly generated AES 256 Key – Allows for a key to be specified, commonly used in client mode.
  • SECRET – Defaults to random 5 character value – Allows for specific secret to be used.
  • PNAME – Defaults to random 8 character value – Allows for specific pipe name to be chosen.
  • TIMEOUT – Defaults to 60 second – Used to change the wait time for the client to connect to the Implant, used in slow networks.
  • EXE – Generates a stand-alone executable;
  • CLIENT – Runs the script in client mode to connect to a deployed Executable;
  • TARGET – used to specify a remote IP Address.
  • Domain/User/Password/Hash – used to provide credentials for authentication.
  • Domain2/User2/Password2 – used to map a drive to the target system, when a hash is being used as the primary authentication mechanism.
  • Dir – used in EXE mode to output the generate executable.
  • Automation – used in EXE mode, directory location of the Automation DLL.


There are 3 main functions that have been created to interact with the implant from a client. The first and probably the most useful, especially when we introduce templates, is Pbind-Command. This simply registers a command in a variable that is read in by the client and passed to the implant (server) before being executed. A simple example is shown below:

Pbind-module c:\folder\powerup.ps1The second is Pbind-Module, which allows you to read in any other ps1 file and have it injected into memory on the implanted host. Pbind-Command can then be used to execute any of the functions in the ps1 script. This has a limitation and does not work well within a C2 setup, because all scripts have to be local to the client. In most cases the client is already running on a target workstation and would require all scripts to be uploaded to the client before being sent on to the implant.

Pbind-Squirt was a designed to help resolve the limitations of Pbind-Module. The idea for this function was to embed a number of scripts as base64 objects into the script that can then be called and auto executed into memory on the client. The only one that has been embedded is PowerUp, to assist with asset review on newly implanted hosts.

However, in practice neither Pbind-module nor Pbind-squirt were optimal and instead a new solution was constructed, called ‘Templates’. Effectively this was just a better way to interact with the Pbind-Command function. It was decided that by creating a number of small scripts which can automate tasks, it is possible to carry out similar ideas to Pbind-module and Pbind-squirt. Tasks such uploading mimikatz and extracting passwords, uploading PowerView and running queries or uploading invoke-SMBExec and attacking other machines, can all be scripted using a similar template to the one below:

The best way to see how the script runs is to download the script and have a go. The screenshot below shows a simple example of running the script locally under the context of another user, while also executing commands.

Video Tutorial

We have created a video tutorial to help illustrate the use of Invoke-Pbind.


github GitHub: https://github.com/nettitude/PoshC2/blob/master/Modules/Invoke-Pbind.ps1

Using PoolTags to Fingerprint Hosts

Commonly, malware will fingerprint the host it executes on, in an attempt to discover more about its environment and act accordingly.

Part of this process is quite often dedicated to analyzing specific data in order to figure out if the malware is running inside a VM, which could just be a honeypot or an analysis environment, and also for detecting the presence of other software.  For example, malware will quite often try to find out if a system monitoring tool is running (procmon, sysmon, etc.) and which AV software is installed.

In this article, we will introduce another method of fingerprinting a host that could be potentially abused by malware.

Common ways of host fingerprinting

In this section we provide a short list of well-known ways of detecting a VM environment, and the presence of other security software, that are often applied by malware. Note that the following list is not exhaustive.

  • Process Enumeration
  • Loaded modules Enumeration
  • File Enumeration
  • Data Extracted from Windows Registry (Hard disk, BIOS etc…)
  • Loaded drivers enumeration
  • Open a handle to specific named device object
  • System Resources Enumeration (CPU cores, RAM, Screen Resolution, etc…)

The PoolTag way

If you have some experience with Windows kernel drivers development & analysis, you should be familiar with the ExAllocatePoolWithTag [1] function that is used in order to allocate memory chunks at kernel level.  The key part here is the ‘Tag’ parameter that is used in order to provide some sort of identification for a specific allocation.

If something goes wrong, for example because of a memory corruption issue, we can use the specified Tag (up to four characters) in order to associate a buffer with a code path in the kernel driver that allocated that memory chunk. This method is adequate for detecting the presence of kernel drivers, and thus software that loads modules in the kernel that could potentially circumvent the fingerprinting methods mentioned above, which rely on information that a driver could potentially alter.  In other words, it is ideal for detecting the stuff that really matters from the malware author’s point of view.

For example, security/monitoring software might try to hide its processes and files by registering callback filters at kernel level.  An analyst might try to harden their VM environment by removing artefacts from the registry and other things that malware is usually searching for.

However, what a security software vendor and/or analyst probably won’t do, is modify specific kernel drivers used by their own program and/or system/VM environment to constantly alter the Tags of their kernel pool allocations.

Getting PoolTag Information

This information can be obtained by calling the  NtQuerySystemInformation [2] function and selecting SystemPoolTagInformation (0x16) [3] for the SysteminformationClass parameter.

The aforementioned function and the associated SysteminformationClass possible values are partially documented on MSDN, but fortunately with some online research we can find some documentation done by researchers. In particular, Alex Ionescu has documented a lot of otherwise undocumented stuff about Windows internals in his NDK [3] project.

For this proof of concept, we wrote our own version of getting and parsing PoolTag information, but if you want to go the GUI way to experiment with the results, then PoolMonEx [4] is a really nice tool to play with.

For instance, the following is a screenshot of our tool’s output.  Source code below.

Which you can compare with regards to the Nbtk tagged allocations results from PoolMonEx as shown below.



Targetting PoolTag Information

In order to give some sense to the acquired PoolTag information, it is necessary to analyse those drivers that we are interested in. By searching for calls to ExAllocatePoolWithTag we can log specific tags used by those drivers and keep them in our list.

At this point, you should be aware that any driver can use any tag at will, and for that reason it makes sense to try to find some tags that appear to be less common and not otherwise used by standard Windows kernel drivers and/or objects.

With that being said, this method of detecting specific drivers might produce false positives if not used with extra care.

A PoolTag Example List

For the sake of demonstrating a proof of concept we have collected some PoolTag information from specific drivers.

  • VMWare (Guest OS)
    • vm3dmp.sys (Tag: VM3D)
    • vmci.sys (Tags: CTGC, CTMM, QPMM, etc…)
    • vmhgfs.sys (Tags: HGCC, HGAC, HGVS, HGCD etc…)
    • vmmemctl.sys (Tag: VMBL)
    • vsock.sys (Tags: vskg, vskd, vsks, etc…)
  • Process Explorer
    • procexp152.sys (Tags: PEOT, PrcX, etc…)
  • Process Monitor
    • procmon23.sys (Tag: Pmn)
  • Sysmon
    • sysmondrv.sys (Tags: Sys1, Sys2, Sys3, SysA, SysD, SysE, etc…)
  • Avast Internet Security
    • aswsnx.sys (Tags: ‘Snx ‘, Aw++) (We used single quotes in the first because it ends with a space character)
    • aswsp.sys (Tags: pSsA, AsDr)


Just like every other method, this one has its strengths and weaknesses.

This method cannot be easily circumvented, especially in 64-bit Windows where the Kernel Patch Protection (Patch Guard) does not allow us to modify kernel functions among other things, and thus directly hooking those such as NtQuerySystemInformation is not a solution anymore for security and monitoring tools.

Also, this method is not affected by drivers that attempt to hide/block access to specific processes, files, and registry keys, from userland processes.

In addition, this method could be potentially used to fingerprint the host further.

By searching for specific tags of Windows objects that are being introduced in the OS, we can determine its major version.

For example, by comparing the poolTag information (pooltag.txt) that comes with different versions of Windbg, in this case Windows 8.1 x64 and Windows 10 x64 (Build 10.0.15063), we were able to find PoolTags that are used in Windows 10 by the  netio.sys kernel driver such as Nrsd, Nrtr, Nrtw, but not in Windows 8.1

We later did a quick verification by using two VMs, and we could indeed find pool allocations with at least two of the aforementioned tags in Windows 10, while there were none of those in our Windows 8.1 VM.

That being said, it is a common and good practice for kernel driver development to use tags that make some sense based on the module that allocates them and their purpose.

On the other hand, as mentioned already, PoolTags can be used at will and for that reason we have to be careful about which ones we are targeting.

One last thing to mention is that PoolTag information changes all the time, in other words chunks of memory are constantly allocated and de-allocated, and for this reason we should keep this in mind when choosing the PoolTag to search for.

Even though this method might look more experimental than practical, in reality when malware is searching for specific monitoring and security software, PoolTag information can be very reliable.


  1. https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/nf-wdm-exallocatepoolwithtag
  2. https://msdn.microsoft.com/en-us/library/windows/desktop/ms724509(v=vs.85).aspx
  3. https://github.com/arizvisa/ndk
  4. http://blogs.microsoft.co.il/pavely/2016/09/14/kernel-pool-monitor-the-gui-version/

CVE-2018-13442: SolarWinds NPM SQL Injection

A SQL injection vulnerability has been discovered in SolarWinds’ Network Performance Monitor (NPM).  This vulnerability has been designated CVE-2018-13442.

SolarWinds NPM is one of the most widely used network monitoring tools available in the current market. It provides features such as availability monitoring, network discovery, health status, performance monitoring, and bandwidth analysis in order to help reduce network outages and improve overall performance.

Affected Versions

The SQL injection described by CVE-2018-13442 exists in Network Performance Monitor (NPM) versions 12.3 and prior.


The SQL injection vulnerability is exploited by injecting queries to the TriggeringObjectEntityNames parameter in a POST request to /api/ActiveAlertsOnThisEntity/GetActiveAlerts.

This vulnerability allows a would-be threat actor the ability to inject code to the application’s database, which would provide access to all of the data housed within. This would include the login credentials for SolarWinds NPM, which could open up the possibility for privilege escalation in the event of administrator password hashes being cracked. Depending on the configuration of the database, such as the privilege level of the database user, access to the underlying file system or the achievement of command execution may also be possible. Authentication to SolarWinds NPM is required in order to exploit this vulnerability, and as registration is approved by administrators, a user account would first have to be compromised.


SolarWinds have acknowledged the existence of the vulnerability and have confirmed they have been able to replicate it. A fix was issued on the 2nd of August, 2018 as part of Orion Platform 2018.2 Hotfix 4 (HF4):



  • Vulnerability discovered: 19 June 2018
  • SolarWinds informed: 19 June 2018
  • SolarWinds technical team response: 26 June 2018
  • SolarWinds hotfix (2018.2 HF4) released: 02 August 2018
  • Nettitude public disclosure: 02 August 2018

CVE-2017-16245 & CVE-2017-16246: Avecto Defendpoint Multiple Vulnerabilities

Avecto Defendpoint is an endpoint protection product which, according to the Avecto website, will:

“Prevent breaches without hindering productivity. Avecto combines best-in-class privilege management and application control, making admin rights removal simple and scalable across desktops and servers to ensure security and compliance.”

This post focuses on the “application control” aspect of Avecto. Last year I discovered two vulnerabilities in the way that application control is implemented, leading to the possibility of a breakout from the application control policy.

Both vulnerabilities were trivial to find and exploit. An exploit could easily be written into a Microsoft Word or Excel macro, for example.

Discovery and analysis

An initial investigation was carried out using Process Hacker. Examining any process running on a machine with Avecto installed, it could be seen that a DLL PGHook.dll had been injected into every process on the machine.


The name PGHook.dll gives away that this DLL might be a user mode hooking library. The next step was to load PGHook.dll into IDA pro and have a poke around.

PGHook.dll applies hooks to several Windows API calls. The hooks are used to communicate with an Avecto system service, which then applies Avecto Group Policy settings.

Looking at the entrypoint of the DLL in IDA pro, an issue was immediately apparent:


A global mutex is created “Global\PGHOOK<pid>” where <pid> is the current process id. If this mutex already exists, then the rest of the entrypoint code is skipped and PGHook.dll does not install any hooks!

From here, it is easy to exploit this. If an attacker can create a lot of mutexes in the Global namespace for a whole bunch of process id’s, then they can force hooking to be disabled for new processes with those id’s. This method of mutex “squatting” is exactly how CVE-2017-16245 can be exploited.

After finding this, it was time for me to poke around a little further.

When executing a process that is not permitted in the security policy, a dialog box is displayed to the user; in this case wscript.exe was blocked:


However, using ProcMon to monitor process creation, we can see that the blocked process wscript.exe does actually execute, and then exits:


This is quite interesting; if the process is being executed and then terminates, can we block the process termination?

In Process Hacker, examining any running process again, we can see that there is a named pipe handle to \\.\pipe\PGMessagePipe being created and destroyed, quite regularly in each process.

Monitoring this pipe using API Monitor shows that it is used to communicate with a listening SYSTEM process, using the Windows API function TransactNamedPipe:


In the API monitor output, we can see the content of these messages:

<MSG ID=”2″ PID=”184 ” TID=”568″ ParentPID=”2880″ SessionID=”2″ CmdLine=”&quot;C:\Windows\system32\wscript.exe&quot;” CurrentDir=”C:\temp” InheritHandles=”1″ StartSuspended=”1″ MessageTime=”131771712686951286″ />

<MSG DisplayedMsg=”1″ Block=”1″ Status=”0″ />

You will also notice that there is a call to TerminateProcess in the API monitor output. I initially thought this may be the source of the process termination. I verified that this is not the case, by patching the TerminateProcess function with a two byte infinite loop 0xEB 0xFE (jmp -2). The process was still terminated, so this could not be the culprit.

So, each process that attempts to spawn a child process not only creates the actual child, but also tips off the SYSTEM service to the existence of the new process; this is how the new child process is terminated.

The next thing I tried was to prohibit comms with the SYSTEM service over the named pipe, which I achieved by editing the memory of PGHook.DLL in ProcessHacker on a running process.

It turned out that if comms are down, then any child process runs as normal, as it doesn’t get terminated. That is the basis for CVE-2017-16245. There are many other ways to prohibit the named pipe comms from within a process; the example source code provided below (note: will be published in the coming weeks) simply changes the name of the pipe in the process data section.

Proof Of Concept Video

In the following video, the two CVE executables have been white-listed in the Avecto application control policy.

This is an unrealistic scenario; in an ideal world the System Administrator will have locked down the endpoints so that only a curated list of applications are allowed to execute.

The CVE’s are, however, so trivial to exploit, that is it’s not difficult to imagine an attacker or inside threat using a Word macro, browser exploit or other code execution method in combination with these vulnerabilities in order to breakout of the application control policy.

It can be seen that while the two vulnerabilities are quite powerful in their own right, combining them provides a complete break-out solution.

Proof of Concept Source Code

We have opted to keep sample exploit code out of this blog for now.  Once we’re confident that enough time has elapsed for a significant majority of affected users to have patched, we will release sample code as an educational resource.


These two vulnerabilities really illustrate why user mode hooking is not a particularly good method of controlling process creation on Microsoft Windows. If you want to modify process permissions or deny process execution, then a kernel module is the way to go. Several kernel mode callbacks are available that allow you to intercept process creation.

Malicious code will always run with the same privileges as user mode hooks and, given enough time and access to the security product for reverse engineering, they can be bypassed.

CVE Numbers

The following CVE’s have been issued by MITRE:

  • CVE-2017-16245
  • CVE-2017-16246

Affected Versions

All versions up to and including 4.4 are affected.

Disclosure Timeline

  • Vulnerability discovered –  November 2017
  • Vendor notified – November 2017
  • Vendor acknowledged issues – November 2017
  • Vendor fixed issues – February 2018
  • Vendor notified that advisory is now public – 27 July 2018