In this article, we’ll discuss some of the different ways we can execute arbitrary code or commands when we have already obtained Windows domain credentials, either in their plaintext form (user + password) or NTLM hashes.

Even though the techniques described here are heavily focused on offensive tooling and use cases (e.g. lateral movement), system administrators and blue team operators can also find this article useful, because these techniques are primarily legitimate instruments that are, in most cases provided by the operating system itself to ease administrative tasks. 

Additionally, we provide some indicators of compromise (forensic evidence of a potential intrusion) for every specific attack routine that can serve as a starting point to blue team operators when investigating a potential breach.

SMB-based

The following techniques rely on the SMB protocol to ultimately achieve remote execution. 

PsExec

PsExec is a technique to run code on a remote machine via SMB. Despite its slightly misleading name, it has nothing to do with PowerShell (but it has with execution). The original PsExec is a tool included in the Sysinternals suite. Released in late 90s/early 00s, it was meant to make system administrators’ lives easier by providing a quick and reliable method of executing commands on remote Windows systems.

To do so, the original tool performs the following actions:

  1. Uploads an executable file to the $ADMIN shared folder of the target remote computer
  2. Remotely creates a service that will run that file
  3. Remotely starts the service, which runs the desired command
  4. Input/output/error streams are redirected back using Named Pipes

In other words, it can be used to obtain a shell on a given Windows system, with some caveats:

  • SMB access to the remote is needed
  • Valid domain credentials to the remote machine are required
  • Write permissions to a network shared folder
  • Permission to create and start services on the remote machine:
    • SC_MANAGER_CREATE_SERVICE
    • SERVICE_QUERY_STATUS
    • SERVICE_START

Due to the fact that SERVICE_START and SC_MANAGER_CREATE_SERVICE are by default only granted to Administrators, it is unlikely that lesser accounts can successfully leverage this technique to obtain code execution.

In addition, the original tool has even tighter restrictions, because the executable file will be uploaded to $ADMIN (which is accessible to Administrators only), and also only allows users to authenticate with username and password to the remote system. Other alternatives, more attack-focused, such as the one included on Impacket or the Metasploit psexec module, give the user more flexibility by granting more fine-grained controls over:

  • Authentication: Pass-the-hash (sending an NTLM hash instead of the cleartext password) is supported in addition to username/password and Kerberos.
  • Service: Customizable service and the remote executable parameters. The binary itself can be also user-chosen, by default Impacket uses RemCom 

For instance, the following command can get you a shell using Impacket psexec example with username and password:

python3 psexec.py <domain>/<user>:<pass>@<target_host>

If we have captured an NTLM hash instead, the following command will do the trick:

python3 psexec.py -hashes <lmhash>:<ntlmhash> <domain>/<user>@<target_host>

Note: Windows 10 deprecated LM hashes, but since Impacket’s PSExec requires it anyway we can use a string of 32 zeros instead:

python3 psexec.py -hashes 00000000000000000000000000000000:<ntlmhash> <domain>/<user>@<target_host>

SMBExec

Similarly to PsExec, SMBExec is a technique originally developed by Brav0Hax & PureHate which also uses SMB and remote services to execute commands on a remote computer. Impacket’s implementation supports using a local SMB server (‘server mode’) to receive the command output, useful when the target computer does not have a writable share available.

Unlike psexec, SMBExec avoids sending out a binary to the target computer. Instead, it creates a temporary remote service which runs a Windows command shell (“%COMSPEC%“) and redirects output to a file, granting the attacker a semi-interactive shell.

In share mode, the command output will be piped to a file on the user-specified remote share, where SMBExec will retrieve it from.

In server mode, however, there is no need for the remote computer to have a share accessible, because SMBExec will launch a local SMB server where the remote command output will be redirected.

The following commands can get you a shell using Impacket SMBexec example with plaintext credentials and NTLM hashes respectively:

python3 smbexec.py "<domain>/<user>:<password>"@<target_host>

python3 smbexec.py -hashes <lmhash>:<ntlmhash> <domain>/<user>@<target_host>

SMB-based execution: indicators of compromise

  • Windows Event ID 7045 (“A service was installed in the system”)
  • Windows Event ID 4697 (“A service was installed in the system”)
  • The original PsExec requires users to accept the EULA, which creates a new registry entry on HKCU\Software\Sysinternals\PSexec.
  • The original PsExec also uses named pipes with predictable names on the target host (<psexecsvc_name>-<machine_name>-<5_random_digits>-<stdin|stdout|stderr>).
  • Probing named pipes for access also results in Windows Event ID 5145 (“A network share object was checked to see whether client can be granted desired access”)
  • (smbexec) services.exe spawning cmd.exe

DCOM-based

DCOM (Distributed Component Object Model) is a programming construct that allows a computer to run programs over the network on a different computer as if the program was running locally.

DCOM Exec

DCOM (Distributed Component Object Model) allows applications to instantiate and access the properties and methods of COM objects on a remote computer using a DCERPC-based protocol. Some of these objects expose functionality that can be abused to achieve arbitrary command execution.

For instance, the dcomexec Impacket module currently supports the following objects:

  • MMC20.Application
  • ShellWindows
  • ShellBrowserWindow

A more comprehensive list of suitable DCOM objects can be found here.

The following shows an example of dcomexec with MMC20, using cleartext credentials:

python3 dcomexec.py "<domain>/<user>:<pass>"@<target_host> -object MMC20

Or passing the hash instead:

python3 dcomexec.py -hashes 00000000000000000000000000000000:<ntlmhash> "<domain>/<user>"@<target_host> -object MMC20

WMIExec

WMI (Windows Management Instrumentation) can also be used to execute commands on remote systems, no disk interaction or new service creation needed.

On Windows, the Invoke-WmiMethod PowerShell cmdlet can be used to call WMI methods. Scripts like WmiExec are built around this cmdlet, executing the given command and retrieving its output:

.\wmiexec.ps1 -ComputerName <target_host> -Command "<command>"

We can also get a semi-interactive shell from Linux using Impacket’s wmiexec.py:

python3 wmiexec.py "<domain>/<user>:<pass>"@<target_host>

python3 wmiexec.py -hashes 00000000000000000000000000000000:<ntlmhash> "<domain>/<user>"@<target_host>

DCOM-based execution: indicators of compromise

  • Network traffic fingerprinting: DCOM/DCERPC analysis (e.g. detecting typical compromise indicator strings such as Win32_ProcessStartup, Win32_Process or ExecuteShellCommand)
  • (dcomexec with MMC20) mmc.exe spawning cmd.exe
  • (dcomexec with ShellBrowserWindow) explorer.exe spawning cmd.exe
  • (wmiexec) WmiPrvSE.exe spawning cmd.exe
  • (wmiexec) output redirection: cmd.exe /Q /c  1> \\127.0.0.1\ADMIN$\ 2>&1

WinRM-based

Windows Remote Management (WinRM) is the Microsoft implementation of the WS-Management Protocol, which is a standard protocol that defines a SOAP-based protocol for managing servers, devices and applications. HTTP (5985) or HTTPS SOAP (5986) ports need to be reachable.

Supported authentication methods are Kerberos and NTLM authentication by default and Basic authentication. It also requires Administrator access.

Before we can use WinRM, we need to configure the remote computer to accept connections if it does not already (it does by default on server operating systems). We can do this is by using the Enable-PSRemoting cmdlet, which automatically performs the following operations:

  • Runs the Set-WSManQuickConfig cmdlet, which performs the following tasks:
    • Starts the WinRM service
    • Sets the startup type on the WinRM service to Automatic
    • Creates a listener to accept requests on any IP address
    • Enables a firewall exception for WS-Management communications
    • Creates the simple and long name session endpoint configurations if needed
    • Enables all session configurations
    • Changes the security descriptor of all session configurations to allow remote access
  • Restarts the WinRM service to make the preceding changes effective

From an Administrator PowerShell session we just need to do:

Enable-PSRemoting -Force

Note: The -Force flag suppresses any user prompts.

WinRS

Windows Remote Shell (WinRS) can be used to execute single commands:

winrs -r:http://<target_host>/wsman <command>

Or establish a fully interactive remote shell:

winrs -r:http://<target_host>/wsman "cmd.exe"

PowerShell Remoting

To connect from a Windows host to a remote machine with Powershell remoting enabled, it’s required to enable Remoting on the local host first:

winrm quickconfig

Then we create a remote PowerShell session by doing

New-PSSession -ComputerName <target_host> -Credential <credential>

Then we connect to it

Enter-PSSession -ComputerName <target_host> -Credential <username>\<domain>

WinRM: Indicators of compromise

  • wmiprvse.exe spawning processes and suspicious network  connections to svchost
  • Network activity and artifacts on ports 5985 or 5986 TCP.
  • (PSRemoting) Windows Event ID 400 (“Engine state is changed from None to Available.”) and 43 (“Engine state is changed from Available to stopped.”) from Source: PowerShell can be used to identify the beginning and end of a session.

GUI-based: RDP and VNC

RDP and VNC are remote administration tools that are commonly found in enterprise environments. While VNC is less secure and generally not a good practice for managing corporate machines, we often find VNC servers accessible on internal network security assessments.

Both allow users to establish a remote desktop session, which can be used to spawn a command interpreter and execute arbitrary commands on the target host.

These protocols capture and compress video (RDP and some proprietary versions of VNC support audio too) on the remote computer and send it back to the local host that initiated the connection. Conversely, keyboard and mouse events are captured on the client and sent to the remote computer, completing the illusion of a remote desktop.

In some cases however, it may be not ideal or practical to establish a full remote desktop session (e.g. over high latency/low bandwidth connections). For those cases, it’d be possible to send keystrokes only, a la USB Rubber Ducky, deploying and executing arbitrary code (or commands) on the remote computer.

For RDP, SharpRDP can be used to perform authenticated command execution against a remote computer. It supports authentication with plaintext credentials or by current user context if interactive logons are disabled (RDP restricted admin mode enabled).

For VNC, vncdotool and the VNC Keyboard Remote Code Execution metasploit module are available.

GUI-based execution: indicators of compromise

On Windows systems, both of these tools will use the “Run” dialog, which creates a new registry entry on HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU. This may serve as an indicator of compromise.

Additionally, the following can be observed on SharpRDP executions:

  • mstscax.dll loaded into a process other than mstsc.exe
  • Windows Event ID 4624 (“An account was successfully logged on”)
    • Type 10: RemoteInteractive
    • Type 3: Network

For vncdotool, it’s up to the specific VNC server where and how to log connections and events. Further investigation may be required depending on the product in use.