PSExec is a SysInternals tool that enables remote execution of processes. One of the really neat aspects of the tool is that it can execute processes interactively in user sessions and on systems that may not expose another way of remotely executing processes. PSExec works much differently than PowerShell remoting or WMI. PSExec manages all the remote management by actually installing a service on the remote machine and communicating via remote named pipes. The process is as follows.
- Copy the PSExecSvc executable to the computer’s $Admin share
- Install the service using Service Control Manager
- Start the service
- Send the intended command line via named pipes to the service
- The service starts and manages the life cycle of the process, depending on command line options
- Stop and remove the service
Obviously, PSExec requires administrator access but it doesn’t rely on additional configuration like WinRM and PowerShell remoting do.This makes it unique in this sense.
PoshExec is currently a single cmdlet; Start-RemoteProcess. It uses the same set of steps that PSExec uses to install a service on the remote machine and communicate via named pipes. What’s cool about PoshExec is the entire tool is wrapped in a single PS1 file. The service code is written in C#. It’s a simple service that inherits from ServiceBase that runs a message loop, waiting for communications via the PoshExecSvc named pipe.
The message sent across the wire is a simple XML serialized object. It contains all the options exposed by Start-RemoteProcess. Once the service receives the message it deserializes and begins starting the process.
At the moment, interactive execution is not working. PoshExec also requires the process exist on the remote machine. It can run the process as a separate user from the one executing Start-RemoteProcess. The framework is in place to begin working out feature parity between the two tools.
The Start-RemoteProcess cmdlet has to set the whole process in motion. It follows the same process as PSExec. First, it maps a drive and copies the service over to the machine. Next, it uses the sc command line tool to create the remote service.
After the service is up and running, Start-RemoteProcess, calls the new Send-NamedPipeMessage cmdlet to send a message via the PoshExecSvc named pipe to the remote machine. The contents of the message is the XML serialized start info that was mentioned earlier in the post.
Finally, the cmdlet cleans up by stopping and removing the service and removing the mapped drive.
Although a very rough first cut, it was an interesting experiment to look into how PSExec worked. Feel free to star or fork my repo on Github. The script for PoshExec is currently in the dev branch.