Inside PsExec remote administration

By | March 24, 2004

This is a short reverse engineering review of one useful remote administration utility, originally authored by Mark Russinovich (you can download it from Microsoft web-site here). The original version of this review was published on this site in 2004, but since the utility is still very popular and users are interested about its internal design, I decided to slightly update and republish it. The short description from utility homepage: “Utilities like Telnet and remote control programs like Symantec’s PC Anywhere let you execute programs on remote systems, but they can be a pain to set up and require that you install client software on the remote systems that you wish to access. PsExec is a light-weight Telnet-replacement that lets you execute processes on other systems, complete with full interactivity for console applications, without having to manually install client software. PsExec’s most powerful uses include launching interactive command-prompts on remote systems and remote-enabling tools like IpConfig that otherwise do not have the ability to show information about remote systems.” Actually, I was questioned before by several System Administrators regarding possibility to start programs on remote system without installing any additional software on it. That’s why this tool appeared to be very interesting for me. Regretfully, Mark did not give any tips on how this utility works, so one pretty Sunday (the weather was pretty awful outside) I’ve fired up IDA and looked inside this tool.

Smart and simple

First I’ve found out that psexec.exe contains embedded binary resource PSEXESVC, which is actually a PE-executable, more exactly it’s a Win32 service binary. Some initial reversing of PSEXESVC discovered that this is a server part of the utility, responsible for starting processes and redirecting I/O to/from the client system. However, let’s start from the very beginning and describe what psexec.exe do in sequence.

As it could be expected first what utility does is checking host operating system and parameters validity, an example, it checks if the application to “copy and execute” exists on the host system. I think here is no need to describe this part in details, any programmer working over console application does the same things (again and again in an endless loop…).

After parameters are validated, psexec.exe obtains a pointer and size of PSEXESVC resource:

HRSRC hSvc = FindResource (NULL, "PSEXESVC", "BINRES" );
   if ( !hSvc ) return 0; 
HGLOBAL hGbDesc = LoadResource (NULL, hSvc); 
DWORD dwSvcSize = SizeofResource (NULL, hSvc); 
PBYTE pPsExeSvc = LockResource (hGbDesc);

Then it creates a file in \\RemoteSystemName\ADMIN$\System32 named PSEXESVC.EXE and saves the binary extracted from the resource into it. If there is no existing session with permissions to access RemoteAdmin (ADMIN$) share, then it tries to establish a new session using the username and password specified in the command line through the call to WNetAddConnection2 as the following:

DWORD
   PsExecRemoteLogon (
   LPCSTR lpComputerName,
   LPCSTR lpUserName,
   LPCSTR lpPassword
   )
   {
	char szFullPath [_MAX_PATH];
	NETRESOURCE NetResource;
	sprintf (szFullPath, "\\\\%s\\IPC$");
	// Initialize NetResource structure, omitted here
	...
	return (NO_ERROR == 
		WNetAddConnection2 (
			&NetResource, 
			lpPassword, 
			lpUserName, 
			0)
		);
   } 

If no error occurs, then we get PSEXESVC.EXE service binary in \\SystemRoot\System32 on the remote system. Note, if there is an executable to start remotely which must be copied to the remote system, then it is also placed into that folder. After this, psexec.exe install and start PSEXESVC service using SCM API (OpenSCManager, CreateService, StartService). Full description of these calls is quite ordinary and along with the source would take pretty much the place, so I don’t see real need to do this.

After start, PSEXESVC creates named pipe psexecsvc, and starts reading messages from it. By this moment, we have the server part installed and started on the remote system, which is ready to accept command messages. Everything else is typical for client/server applications (for better understanding of writing server applications I strongly recommend Jeffrey Richter, Jason D. Clark “Programming Server-Side Applications for MS Windows 2000”). So, once again in two words, psexec.exe copies executable to start to the remote system if necessary, opens a psexecsvc pipe on a remote host (CreateFile), fill in the message structure with necessary parameters (command line arguments, username & password if specified etc…) and sends it into \\RemoteSytem\pipe\psexecsvc (TransactNamedPipe API call).

On receiving this message, PSEXESVC creates three named pipe instances psexecsvc-app_name-app_instance-stdin, psexecsvc-app_name-app_instance-stdout, psexecsvc-app_name-app_instance-stderr. As you may suspect, psexec.exe connects to each of these pipes and creates separate threads to work with each one. Using console functions (GetStdHandle, ReadConsole, WriteConsole etc…) standard I/O streams (input, output, error) are redirected to/from remote systems through these named pipes.

On exiting application, psexec.exe stops and uninstall PSEXESVC service, removes its binary from remote host and removes console executable if it was also copied.

As a result, we have a Telnet like application with extensive use of Windows NT/2000 features, it can be effectively used by system administrators for common administration tasks. The only hole (mentioned on utility homepage) is security: “If you omit a username the remote process runs in the same account from which you execute PsExec, but because the remote process is impersonating it will not have access to network resources on the remote system. When you specify a username, the remote process executes in the account specified, and will have access to any network resources the account has access to. Note that the password is transmitted in clear text to the remote system”. As you can see, this tool is dangerous to use for remote administration over non-trusted networks and Internet and possibly sometimes even in corporate network (as dangerous as telnet, an example). One of the possible extension of this tool would be securing communication of psexec and PSEXESVC with some kind of encryption.

4 thoughts on “Inside PsExec remote administration

  1. RK

    which are the GPO policies which can stop psexec from executing on target machine?

    Reply
  2. Karuna Kant Mishra

    year 2018 and this article is still informative. Now I know why sometimes PSExec fails when called second time in a row.

    Reply
  3. Kostantin Shiian

    To disable psexec you can:
    – use AppLocker (if you have Enterprise or Ultimate versions of Windows)
    – use UAC LocalAccountTokenFilterPolicy
    I would prefer second method. Typically IT require using of administrative shares for administrative task so you should take a look at Powershell WinRM and JEA instead…

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *