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.
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.
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.
$ psexec.py corp.local/administrator:'Password123!'@10.10.10.10
corp.local/administrator:password@targetis 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:
- Authenticate to the target via SMB (port 445)
- Upload a service binary to
\\target\ADMIN$\(or C$) - Create a Windows service (via the Service Control Manager over RPC)
- Start the service → it runs as
NT AUTHORITY\SYSTEM - Communicate through named pipes over SMB for I/O
- On exit, stops the service, deletes the binary (cleanup)
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
| Tool | Protocol | Privilege level | Stealth | Requirements |
|---|---|---|---|---|
| psexec.py | SMB (445) | SYSTEM | Low (service creation logged) | Local admin + ADMIN$ writable |
| wmiexec.py | WMI (135) + SMB | User-level | Medium (no service creation) | Local admin + DCOM access |
| evil-winrm | WinRM (5985) | User-level | Medium (legitimate protocol) | Port 5985 open + valid creds |
| xfreerdp | RDP (3389) | User-level (GUI) | High (looks like normal login) | Port 3389 open + valid creds |
- 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
# 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
# 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
# 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
# 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
| Error | Cause | Fix |
|---|---|---|
STATUS_ACCESS_DENIED | Not local admin, or ADMIN$ not writable | Try wmiexec.py or evil-winrm. Verify admin privileges |
STATUS_SHARING_VIOLATION | Another psexec session or AV locking the file | Wait and retry, or use wmiexec.py |
ERROR_SERVICE_REQUEST_TIMEOUT | Service takes too long to start (AV blocking) | AV is killing the service. Try wmiexec.py instead |
Connection refused | Port 445 not open or firewall blocking | Check with Nmap. Try port 5985 (evil-winrm) or 3389 (RDP) |
| Shell hangs / no output | Named pipe communication issue | Kill and reconnect. If persistent, switch to wmiexec.py |
KDC_ERR_S_PRINCIPAL_UNKNOWN | Using IP with Kerberos auth | Use hostname: dc01.corp.local not 10.10.10.10 |
OPSEC considerations
- 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
- Using IP with Kerberos: Kerberos needs hostnames. Always use
dc01.corp.localwith-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?
What makes psexec.py noisier than wmiexec.py or evil-winrm?
You have an NT hash and no plaintext password. Can you still use psexec.py?
-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?
KRB5CCNAME to the ccache file, and use -k -no-pass with a hostname rather than an IP, since Kerberos needs a resolvable name.