Powershell vs. cmd (using psexec) for remote command execution

Further Considerations

It is important to remember that PsExec will rarely be seen as an “opening move” in an attack. The tool requires credentials and network access to target hosts. Because of this, detection of potentially malicious PsExec activity is likely one piece of a larger attack chain. Thus, if detection occurs during threat hunting, it is important to outwardly scope potential compromise using the detection event as a starting point.

It is also important to remember that the best evidence of PsExec activity lives on affected hosts. In the event of an incident involving PsExec activity host security logs are crucial. If an organization does not collect security logs from hosts on a day-to-day basis, then preserving those security logs in the event of an incident should be a priority. If possible, extracting a memory image of a compromised device before remediation activity can also provide useful indicators for scoping.

The following questions may be helpful in guiding an investigation:

  • Is PsExec normally used in this environment?
  • Are evasion indicators present (e.g. a renamed service from )?
  • What credentials did the command use?
  • What host originated the command?
  • Do the credentials and host normally perform this sort of activity?
  • Are these indicators present elsewhere in the environment?


¹ https://github.com/clong/DetectionLab ² https://docs.microsoft.com/en-us/sysinternals/downloads/psexec ³ https://attack.mitre.org/software/S0029/ ⁴ https://blog.menasec.net/2019/02/threat-hunting-3-detecting-psexec.html

Corporate Security


Tools & Techniques

Security vs usability

So how do we secure against tools that are ubiquitous within Windows networks? Especially tools for which there are a range of legitimate uses?

To some extent there’s a limit to what can be done: banning knives in your home would certainly prevent a house guest with a questionable sense of humour from shredding your wardrobe, but it would equally make cooking dinner rather difficult.

Access to administrative tools should be limited, but generally speaking this is already the case: very few corporate networks (hopefully no corporate networks) allow all users unfettered permissions on their system.

This largely leaves us with detection, and with so much administrative activity taking place at any point in time on a typical network even this is no easy task. Successful security monitoring against more advanced threats typically requires input from a number of sources and this situation is no different. While these options may not be viable for all networks, you may want to consider:

  • Monitoring for remote administration traffic from unexpected machines: While admins may often need to log in to workstations to diagnose or fix faults, they are unlikely to need (or want) to perform bulk administration tasks from a machine in the accounts department.
  • Sudden changes in the behavioural profile of an administrative account: Though it requires the development of a good baseline for the behaviour of individual users, deviations from this baseline may indicate a potential compromise. A sudden increase in login activity from a given administrative account may simply be indicative of legitimate deployment activity, but hopefully security operations are already aware of any major planned work of this type…

Behavioural monitoring of human interaction is no simple task, but Security Information & Event Management (SIEM) products can help by pulling disparate log sources together and providing both alerting and a holistic view of activity on a network. For example, while an internal IDS may be configured to detect large amounts of Remote Procedure Call (RPC) traffic, this information will likely need to be combined with other log sources such as Windows event logs to confirm the user accounts involved.

To this end, it is worth considering the architecture of new networks (or extensions of old networks). Flat networks pose almost no architectural barriers to lateral movement and rarely offer suitable ‘choke points’ for protection and monitoring devices. While not a panacea, network segmentation provides these choke points for the deployment of IPS devices and firewalls which may allow for a degree of damage limitation in the event of a compromise.

Concluding Thoughts

No matter how few or many Windows hosts you may need to administer remotely, there is always the need to connect to remote Windows systems to issue commands, perform troubleshooting, install software, and assist end-users. With this in mind, most organizations need to use tools to establish a connection to remote Windows clients and issue commands. Using Remote Desktop connections to remote Windows computers is cumbersome, time-consuming, and not very efficient.

PsExec is a powerful tool that is part of the PSTools suite of tools from SysInternals. It is a powerful utility that allows IT admins to connect to Windows hosts remotely and issue commands on the remote system. The requirements for connecting to remote Windows systems are minimal. These include credentials that allow connecting to the Admin$ share of the remote computer, File and Printer sharing enabled, and local administrator permissions if needed for configuration on the remote Windows host.

PsExec provides many different capabilities that allow you to interact with a single remote Windows host, multiple Windows computers, launching programs interactively, and even working in tandem with Windows PowerShell to pull a list of computers from Active Directory. Due to the nature of what PsExec can do, organizations need to be careful about who has access to run the utility and which locations it can be run. Malware, including many ransomware variants, can use PsExec to propagate malicious files and run specific commands on the network for compromising environments.

Organizations may want to hesitate to whitelist PsExec and other command-line tools globally since these can be used for malicious purposes. A better approach is to use a minimal scope of allowed workstations allowed to use PsExec to connect to remote Windows clients. In this way, the attack surface is much smaller if malicious software attempts to use known, common, or built-in command-line tools. All-in-all, PsExec is the sysadmin’s Swiss Army knife of functionality for performing remote administration from the command line and provides quick and easy access for troubleshooting, configuration, and assisting end-users.

Was this helpful?

Do you want to become a member of Altaro Dojo?

How do I Detect PsExec?

Most indicators of PSExec activity are available from host-based telemetry tools. In this case, event IDs will be taken from Sysmon and Windows System/Security logs, but there are analogues available in other popular monitoring solutions.

PsExec activity always involves remote service creation. The Windows Security EventCode for this activity is 7045 and the default name is PSEXESVC.

The corresponding service creation event created by the example usage.

  • In order to run PsExec, users must accept its EULA. This creates a registry change on the source host. (Many environments might not be logging all registry changes, but this can be a useful indicator during investigation.) The registry key is: .
  • The default PsExec named pipe used for communication is .pipepsexesvc. MENASEC Applied Security Research has also noted that uniquely-named pipes are created on the target host for each use. These pipes are named according to the format ⁴. Windows Security event is logged when these pipes are accessed. (This insight can be particularly useful for identifying evasive PsExec usage, or the use of PsExec variants.)

The stdin pipe created by example PSExec usage.

How does PsExec work?

You may wonder how PsExec works under the hood and how it provides the functionality it does to execute remote commands on target Windows computers. The workflow of PsExec looks like the following:

  1. PsExec begins by extracting from its executable image an embedded Windows service called Psexesvc
  2. The service is copied to the Admin$ share of the remote system
  3. Windows Service Control Manager API is then used to have a remote interface with the target computer
  4. The Psexesvc service is started on the remote system
  5. A named pipe called psexecsvc is created to which the PsExec utility connects to and sends commands to the remote target
  6. The remote executable you specify is launched along with the options you specify

Controlling the Psexesvc service

As mentioned, the Psexesvc service is installed on the remote computer. You can control the behaviour of the service on the remote target. The default behaviour of the Psexesvc looks like this:

  • The service waits for the executable to terminate then sends the exit code back to PsExec for printing out to the local console
  • Using the -d parameter (don’t wait), the service will exit after starting the executable

Understanding the workflow and how PsExec interacts with remote systems will help from a troubleshooting perspective and keep security in mind.

Installing things under a SYSTEM account eg via SCCM

Sample batch file,

Note using «psexec -s» to emulate a SYSTEM account install on local machine, this would be removed on a live one.

@echo off
:Run from UNC share, will need SYSTEM Account access
"%~dp0psexec.exe" -s msiexec /i "%~dp0The Raisers Edge.msi" TRANSFORMS="%~dp0raiser.mst" /q
"%~dp0psexec.exe" -s cmd /c ("%~dp0owc11.exe" /quiet)
"%~dp0psexec.exe" -s cmd /c (^
copy /y "%~dp0Patchpackage.msp" ^%%temp^%% ^
& copy /y "%~dp0BBPatch.exe" ^%%temp^%% ^
& pushd ^%%temp^%% ^
& msiexec /p ^"^%%temp^%%\Patchpackage.msp^" /q ^


  1. running from a UNC, %~dp0 will be the path. (Dont use a mapped drive as the system account wont have it mapped)
  2. command processor shell (cmd /c) needed to run non ‘core’ programs.
  3. the escaped ^%%temp^%% variable is the SYSTEM’s account temp folder. (It would be ^%temp^% if running directly on command line rather than batch)
  4. patch needs files copying to a local location to run (hence copy and push). IF NOT you will get a «One of the files has an invalid certificate, File: c:\Windows\system32\BBPatch.exe Invalid or no signature» (1602 error)


RPC stands for Remote Procedure Call and is a way of running a procedure remotely but is coded like it would when running locally. Unfortunately the whole part of calling a procedure remotely like it would be done locally is lost when it comes to this process. This is because the usual RPC layer that handles this abstraction does not support the Windows specific functions. This means that the library needs to implement that RPC layer when calling the functions that are required. For , we use RPC to interact with the Windows Service Control Manager Remote (SCMR) API so that we can manage the Windows service that runs our remote payload. The RPC process is as follows;

  • A new SMB Open is created on the tree for the pipe
  • An SMB Write packet is sent to the opened pipe that contains the DCE/RPC Bind PDU structure
  • The Bind Acknowledgement response is parsed to ensure the Bind didn’t fail
  • Any SCMR calls will then send an SMB IOCTL request that contains the method and parameters to invoke on the remote host
  • Once all the SCMR tasks are complete, the SMB Open is closed which also closes the binding

This was a complicated protocol to understand and I only really just scratched the surface to get the Python library working with SCMR. I’m sure there are a lot of major details I am missing or misunderstood but so far it is working and I don’t have a full need to move past it.

By what help?

As with WannaCry, the what and where parts of the analysis have been thoroughly covered by this point, albeit with some tug-of-war over semantics: whether the malware was released in an unfinished state or what a piece of malware incapable – at least under certain circumstances – of restoring a victim’s files should be called are matters of speculation and debate.

Any answers to who and why are similarly speculative until a smoking gun can be found: the former is attribution and the latter is inextricably tied to attribution.

The excitement in Petya stemmed from its ability to self-propagate. While this behaviour was apparently limited to the local network (unlike WannaCry it didn’t attempt to spread itself to external, Internet addresses) it had multiple methods of completing this goal.

Assuming that all of the systems on an affected network are patched and up-to-date, propagation via EternalBlue shouldn’t be viable. That leaves us with the rather less discussed (and less glamorous) PsExec and WMIC approaches to spreading.

The use of these tools is of note because they are both legitimate administrative tools in use across almost all Windows environments (indeed, WMIC has been pre-installed in all versions of Windows from 2000 onwards). As a result, when combined with valid credentials and malicious intent they can be used to do a large amount of damage.

To understand how, we need to appreciate what these tools actually do. Through this we can also see why their usage is preferable to exploits such as EternalBlue for more skilled attackers.


PsExec dates back to 2001 and while its name (these days, at least) could imply an association with PowerShell, that is not the case. Rather than being a built-in component of Windows, it is part of the PsTools suite that allows properly authenticated users to both run commands on remote machines and redirect their output to the local machine.

Despite the fact that it isn’t a component that ships with Windows and therefore needs ‘dropping’ on a target system before it can be used, it has been popular with the authors of malicious code for well over a decade, with its author noting in an article from 2004 that…


WMIC is the command-line interface to WMI (Windows Management Instrumentation) and older still than PsExec, having been an optional download during the Windows NT 4.0 era before coming preinstalled from Windows 2000 onwards.

WMI provides a huge amount of functionality for the administration of Windows-based networks allowing users with the right credentials to do anything from launch processes to modify the security settings on the remote machine. These capabilities can and have been used by APTs including Fancy Bear and Cozy Bear to implement fileless persistence mechanisms on compromised systems.

Abuse of privilege

Both of these tools require administrative credentials to do real damage. In the case of the June 2017 Petya outbreak this was gathered through the use of built-in credential stealing code, although in more targeted attacks there’s every chance that the credentials will have been stolen during an earlier phase of the attack.

Given this need for valid login details, it may initially seem odd that malicious actors choose to use these tools when an exploit would likely get the job done more quickly and easily. In reality, this is far more reflective of the behaviour of skilled hackers and penetration testers: exploits are ‘unnatural’ traffic on a network and using them significantly increases the risk of detection.

Abusing administrative tools, on the other hand, results in malicious activity blending into the background noise of a big network allowing attackers to maximise their dwell time on networks.


SCMR stands for Service Control Manager Remote and is a protocol that is used to remotely manage Windows services. It can do things remotely like;

  • Enumerate services
  • Start/stop services
  • Create/delete services
  • Modify services
  • Lots and lots more, see the MS-SCMR docs for a full list of functions available

It is run over RPC which in turn is run over SMB pipes and on a typical Windows setup, this is all abstracted with the local RPC implementation on that host. This implementation would marshal the data that is used in the function into a byte structure and send that through the network as well as parse and marshal the responses back to the client. As mentioned in the RPC section, this is unavailable on a non-Windows host and so we have to do all this work ourselves. The current code only has to deal with 2 different types of variables, integers and strings. Integers are packed like normally in Python as a little-endian byte but strings are a bit more complex. String have a structure like

Now that the basic data marshaling is covered, must add support for invoking the required functions in SCMR. This is done by creating a Request PDU as defined in the RCP/DCE 1.1 documentation and send that over as a SMB IOCTL Request. Each function has a particular operation number (opnum) that is set on the Request PDU and the data is just the marshaled bytes of the function’s input parameters. The response contains at least the return code that identifies the result of the invocation and can also contain other return values based on the function that was called.

As an example, let’s dive into the ROpenServiceW function and show what happens with the data being passed to and from the client. The function is defined in MS-SCMR as;

This means it takes in 3 input parameters , , and return 2 values; and a that indicates the function result. If we wanted to open a handle to the service called with the rights to query, start, and stop a service here is what it would look like;

The was created as a unique handle as part of a previous call to , in this example we will just pretend it is 20 bytes of . The string does not need a unique/referent ID and the marshaled string structure would look like

The and is equal to which is 13 in decimal form while the string is encoded as a UTF-16-LE string with a null terminator. Because the UTF-16-LE encoded string is 26 bytes long, we need to pad it with 2 null bytes so it is aligned to the 4-byte boundary.

The requires 3 flags that are set to get the query, start, and stop rights which are;

  • : 0x00000004
  • : 0x00000010
  • : 0x00000020

When combined this results in an integer of 52 and the packed bytes value for this is . Putting this all together, the byte structure that is sent with the RPC is;

When sent with the RPC Request PDU, the opnum is set to and that packed as a Int16 is . The server would then receive the request, unpack the data and execute the function and finally return the result under an RPC Response PDU. This response would look like;

The first 20 bytes is the handle for the service , in this case is 20 bytes of while the return code is 0 which means it was successful.


In a IF THEN statement you can use delayed expansion to get around variables with parenthesis in.

(This matters if say you had reference to a path variable with c:\Program Files (x86) in it)


set a=is () a

if  ==  (
	echo this %a% test
a was unexpected at this time.

if  ==  (
	echo this !a! test
this is "()" a test

:BUT this doesn't work in psexec because it isn't double escaped? 

psexec -hes \\gl-test cmd /c ( echo this %a% test )
a was unexpected at this time.

psexec -hes \\gl-test cmd /c ( echo this !a! test )
a was unexpected at this time.

:quoting the echo does work though (can then use %a% or !a!)
set a=is "()" a
psexec -hes \\gl-test cmd /c ( echo this %a% test )
this is "()" a test

Remotely installing Office 2010 language packs

This was quite a fun little challenge , I made a little .bat menu system to pick the office 2010 language, then it copied and ran it remotely.

1)copy file
2)extract pack
3)create the xml
4)setup the language pack.

main run loop

xcopy /i /c /r /s /y "%~dp0%pack%.exe" "\\%h%\c$\temp\"
psexec -e \\%h% cmd /c (^
"c:\temp\%pack%.exe" /extract:"c:\temp\%pack%" /quiet /passive ^
& echo ^^^<Configuration Product="OMUI.%lang%"^^^>^^^<Display Level="none" CompletionNotice="no" SuppressModal="yes" AcceptEula="yes" /^^^>^^^</Configuration^^^> ^> "c:\temp\%pack%\Config.xml" ^
& "c:\temp\%pack%\setup.exe" /config "c:\temp\%pack%\Config.xml" ^
  • Note, the triple ^’d escapes on an enclosed echo to escape the left and right angle brackets (<>’s) from the xml and single escaped redirect angle bracket.
  • Note the SPACE prefix on the line after the «cmd /c (^» line, i.e. » c:\temp» . I don’t understand why this was needed but you get errocode 1 if not. If anyone knows post a comment please!

Exploring PsExec functionality

One of the first things you will want to do is explore the functionality of the PsExec utility. You can easily see the capabilities provided by the tool when you issue the psexec command without switches. As shown, PsExec has a healthy number of command-line switches to interact with the remote target and control the behaviour.

Usage: psexec | @file]]]]] cmd

-a Separate processors on which the application can run with

commas where 1 is the lowest numbered CPU. For example,

to run the application on CPU 2 and CPU 4, enter:

“-a 2,4”

-c Copy the specified program to the remote system for

execution. If you omit this option the application

must be in the system path on the remote system.

-d Don’t wait for process to terminate (non-interactive).

-e Does not load the specified account’s profile.

-f Copy the specified program even if the file already

exists on the remote system.

-i Run the program so that it interacts with the desktop of the

specified session on the remote system. If no session is

specified the process runs in the console session.

-h If the target system is Vista or higher, has the process

run with the account’s elevated token, if available.

-l Run process as limited user (strips the Administrators group

and allows only privileges assigned to the Users group).

On Windows Vista the process runs with Low Integrity.

-n Specifies timeout in seconds connecting to remote computers.

-p Specifies optional password for user name. If you omit this

you will be prompted to enter a hidden password.

-r Specifies the name of the remote service to create or interact.


-s Run the remote process in the System account.

-u Specifies optional user name for login to remote


-v Copy the specified file only if it has a higher version number

or is newer on than the one on the remote system.

-w Set the working directory of the process (relative to

remote computer).

-x Display the UI on the Winlogon secure desktop (local system


-arm Specifies the remote computer is of ARM architecture.

-priority Specifies -low, -belownormal, -abovenormal, -high or

-realtime to run the process at a different priority. Use

-background to run at low memory and I/O priority on Vista.

computer Direct PsExec to run the application on the remote

computer or computers specified. If you omit the computer

name PsExec runs the application on the local system,

and if you specify a wildcard (\*), PsExec runs the

command on all computers in the current domain.

@file PsExec will execute the command on each of the computers listed

in the file.

cmd Name of application to execute.

arguments Arguments to pass (note that file paths must be

absolute paths on the target system).

-accepteula This flag suppresses the display of the license dialog.

-nobanner Do not display the startup banner and copyright message.

You can enclose applications that have spaces in their name with

quotation marks e.g. psexec \marklap “c:long name app.exe”.

Input is only passed to the remote system when you press the enter

key, and typing Ctrl-C terminates the remote process.

If you omit a user name the process will run in the context of your

account on the remote system, but will not have access to network

resources (because it is impersonating). Specify a valid user name

in the DomainUser syntax if the remote process requires access

to network resources or to run in a different account. Note that

the password and command is encrypted in transit to the remote system.

Error codes returned by PsExec are specific to the applications you

execute, not PsExec.

Detection Logic

Basic detection of PsExec activity can be accomplished by monitoring for remote service creation using the well-known “PSEXESVC” name:

If telemetry is available, the optimal solution is to monitor for the uniquely-named pipes that are created as part of the process⁴:

Finally, changes to the EULA registry key could be a useful addition to any of the above:

Proper whitelisting and baselining are critical to identifying anomalous and potentially malicious activity. Sysinternals PsExec is a legitimate systems administration utility, and may be used as such day-to-day in an environment. Some legitimate monitoring solutions, vulnerability scanners, or asset management systems might also exhibit this activity pattern. Knowing your allow lists and baseline profile can help differentiate between common benign activity and potentially malicious behavior.

Multiple commands split over multiple lines

This will run locally — opens a new shell, echo a b c and pause. (To use remotely add \\hostname and remove the & pause ^ line.)

psexec -e cmd /c (echo a ^
& echo b ^
& echo c ^
& pause ^

Note, the ^ escapes the end of the line and the next character, so it is the same as the above example (becomes just ^&)

Multiple commands, lines, escapes

Correctly grant Everyone Modify access to a folder on a remote machine with hostname «mymachine», in this case used inside a batch file.

psexec -e \\mymachine cmd /c (^
mkdir c:\localapp\Common ^
& mkdir c:\localdata\Common ^
& c:\temp\icacls.exe c:\localapp\common /grant Everyone:^^(OI^^)^^(CI^^)^^(M^^) ^
& c:\temp\icacls.exe c:\localdata\common /grant Everyone:^^(OI^^)^^(CI^^)^^(M^^) ^

Single line FOR loop

Batch FOR loop with psexec, this is remotely registering 32bit .OCX files in 64bit Windows 7’s syswow64 folder for backwards compatability with old apps.

  • Note escaped brackets
  • Note double percentage %% , not single % (as batch)
psexec -e \\mymachine cmd /c (FOR /F "delims=" %%f IN ^('dir /b c:\windows\syswow64\MSC*.OCX'^) DO ^( c:\windows\syswow64\regsvr32.exe /s "c:\windows\syswow64\%%f" ^))
( Пока оценок нет )
Editor/ автор статьи

Давно интересуюсь темой. Мне нравится писать о том, в чём разбираюсь.

Понравилась статья? Поделиться с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: