Evil-WinRM

Evil-WinRM is the go-to interactive shell for Windows over WinRM (Windows Remote Management, port 5985/5986). Once you have valid credentials, it gives you a clean PowerShell-style prompt on the target, with built-in helpers to upload/download files and run local scripts in memory. It solves the “I have creds for a Windows box, now what?” problem without RDP or a heavy C2.

You will reach for it constantly on Windows and Active Directory boxes: the moment an enumeration step or a crack yields a username and password (or NTLM hash) for a user in the Remote Management Users group, Evil-WinRM is how you log in and work.

What you will learn#

  • How to install, update, and verify Evil-WinRM
  • Logging in with a password, an NTLM hash, or a certificate
  • Uploading and downloading files, and loading scripts in memory
  • When WinRM is the right access path and when it is not
  • How defenders see WinRM logons
  • Common mistakes and a commented cheat sheet

Only connect to hosts you own or are explicitly authorized to test. WinRM logons are real authentication events and are logged. Confirm the engagement covers the account and the host, and keep the credential source and timestamps in your notes.


Prerequisites#

  • A Linux host with Evil-WinRM (Kali ships it).
  • Valid credentials for a Windows account that is a member of Remote Management Users (or local admin). WinRM membership is what makes the login work.
  • Network reach to TCP 5985 (HTTP) or 5986 (HTTPS).
  • TARGET_IP below is an authorized host; USERNAME / PASSWORD / HASH are placeholders.

Lab setup#

mkdir -p ~/labs/box/{loot,scripts,notes} && cd ~/labs/box
# Confirm WinRM is open first (from your Nmap results):
#   5985/tcp open  wsman      (HTTP)   5986/tcp open  wsmans  (HTTPS)

Installation#

# Debian / Ubuntu / Kali
sudo apt update && sudo apt install -y evil-winrm

# Or as a Ruby gem (newest version)
gem install evil-winrm

Use apt for convenience; the gem tracks the latest release. Build from source only if you need an unreleased feature.


Update process#

sudo apt update && sudo apt install --only-upgrade -y evil-winrm   # package
gem update evil-winrm                                              # gem

Check if installed and available#

command -v evil-winrm
evil-winrm --version
evil-winrm --help | less

First safe test#

Against a lab host where you own a WinRM account:

evil-winrm -i TARGET_IP -u USERNAME -p 'PASSWORD'

Success looks like an *Evil-WinRM* PS C:\Users\USERNAME\Documents> prompt. Failure looks like Connection refused (WinRM closed), an auth error (wrong creds or the user is not in Remote Management Users), or a TLS error on 5986.


Core concepts#

  • WinRM is the SOAP-over-HTTP(S) management service; Evil-WinRM speaks it.
  • Auth methods: password (-p), pass-the-hash (-H <NThash>), or certificate (-c/-k) for 5986.
  • Remote Management Users: the group whose members may connect; admin works too.
  • In-memory helpers: upload/download move files; Bypass-4MSI and the -s/Invoke-Binary/menu features load PowerShell or .NET tooling without always touching disk.
  • 5985 vs 5986: plain HTTP vs TLS; use -S for HTTPS.

When this tool is useful#

  • You have Windows creds (password or NTLM hash) and WinRM is open.
  • AD lateral movement: a cracked or sprayed account that can WinRM into a host.
  • Post-exploitation: stable interactive shell to enumerate and stage privesc.

When not to use this tool#

  • WinRM is closed, or the account is not in Remote Management Users (use another vector: SMB, RDP, a service exploit).
  • You only have a low-priv web shell with no creds yet.
  • You need long-haul C2 with evasion; that is a different toolset and scope.

Command anatomy#

evil-winrm -i [target] -u [user] (-p [pass] | -H [hash]) [-S] [-s scripts/] [-e bins/]
#             TARGET_IP   USERNAME  PASSWORD   NThash      HTTPS  local script dir
  • -i / -u: target and username.
  • -p / -H: password OR NTLM hash (pass-the-hash).
  • -S: use HTTPS (5986). -s / -e: local dirs for scripts / executables.

Common flags and options#

OptionMeaningWhen to use itExample
-iTarget IP/hostAlways-i TARGET_IP
-uUsernameAlways-u svc_user
-pPasswordPassword auth-p 'PASSWORD'
-HNTLM hashPass-the-hash-H 32196b56ff...
-SUse HTTPS (5986)TLS-only WinRM-S
-c / -kCert / key (PEM)Certificate auth-c cert.pem -k key.pem
-sLocal scripts dirLoad .ps1 in memory-s scripts/
-eLocal executables dirInvoke-Binary .NET-e bins/

Practical examples#

# Password login
evil-winrm -i TARGET_IP -u USERNAME -p 'PASSWORD'
# Pass-the-hash (NTLM hash instead of password)
evil-winrm -i TARGET_IP -u USERNAME -H 2b576acbe6bcfda7294d6bd18041b8fe
# Use the NT half of an NTLM hash you are authorized to use.
# HTTPS WinRM (port 5986), ignore a self-signed lab cert
evil-winrm -i TARGET_IP -u USERNAME -p 'PASSWORD' -S
# Stage local scripts/binaries for in-memory loading
evil-winrm -i TARGET_IP -u USERNAME -p 'PASSWORD' -s ~/labs/box/scripts -e ~/labs/box/bins
# Inside the shell: type a script name to load it, or  Invoke-Binary tool.exe args

In the shell, the built-ins you will use most:

upload local\winPEAS.exe C:\Users\Public\wp.exe   # push a file to the target
download C:\Users\USERNAME\Desktop\flag.txt        # pull a file back
services                                           # list services
Bypass-4MSI                                        # AMSI bypass before loading scripts (lab)

Example workflow#

# 1. Confirm WinRM + that your creds belong to a WinRM-capable user
nmap -p5985,5986 TARGET_IP
# 2. Log in
evil-winrm -i TARGET_IP -u USERNAME -p 'PASSWORD'
# 3. Orient + grab the user flag
#    whoami /all ; type ..\Desktop\user.txt
# 4. Stage a privesc enumerator, then review output locally
#    upload local\winPEAS.exe C:\Users\Public\wp.exe ; C:\Users\Public\wp.exe

Reading and interpreting output#

  • A prompt means you are in; whoami /all shows your groups and privileges (look for SeImpersonatePrivilege, admin membership, useful tokens).
  • Bypass-4MSI failing usually means AMSI/EDR is active; expect script loads to be flagged.
  • Upload/download failures are normally permission or path issues, not WinRM.

Common mistakes#

  • Trying WinRM when the account is not in Remote Management Users (login fails).
  • Forgetting -S on a 5986-only (HTTPS) target.
  • Passing a full LM:NT hash where only the NT half is needed for -H.
  • Single vs double quoting passwords with special characters in the shell.
  • Assuming WinRM is stealthy; it is well logged (see below).

Troubleshooting#

ProblemLikely causeFix
Connection refusedWinRM closedConfirm 5985/5986 open; try -S
Auth fails with valid credsNot in Remote Management UsersUse a different account/vector
TLS errorSelf-signed on 5986Use -S (Evil-WinRM ignores the cert)
-H rejectedWhole NTLM hash passedUse just the NT hash
Script will not loadAMSI/EDRBypass-4MSI first (lab), or load differently

Tools that pair well#

  • nmap to confirm WinRM (5985/5986) is open.
  • netexec to validate creds and check (Pwn3d!)/WinRM access at scale.
  • impacket (secretsdump) to recover the hashes you then pass with -H.
  • hashcat / john to crack a hash into a password first.

Automation and note taking#

# Log the whole session for evidence
evil-winrm -i TARGET_IP -u USERNAME -p 'PASSWORD' 2>&1 | tee notes/winrm-$(date +%Y%m%d-%H%M).log

Record the account used, how you obtained it, and any files moved.


Blue-team visibility#

WinRM logons are loud and logged: Windows Security 4624 (logon type 3) and WinRM Operational events, plus PowerShell script-block logging (4104) when you load scripts. EDR commonly flags AMSI-bypass attempts and in-memory .NET loads. Defenders should monitor WinRM connections, restrict the Remote Management Users group, and alert on Bypass-4MSI-style patterns.

Safer or lower-noise usage#

  • Use only the account in scope; do not spray.
  • Prefer reading over writing; pull files instead of dropping tools when you can.
  • Avoid AMSI bypass / in-memory loads unless the engagement calls for it.
  • Keep one session; reconnect noise adds logon events.

Alternatives#

  • RDP (xfreerdp) for a GUI when 3389 is open.
  • impacket psexec/wmiexec for command execution over SMB/DCOM (noisier, drops a service).
  • WinRM via Metasploit (winrm_* modules) when you are already in Metasploit.

Evil-WinRM wins for a clean interactive shell when WinRM + valid creds line up.


Deprecated and legacy notes#

  • Some old guides show the winrm/winrm_shell Ruby scripts; evil-winrm superseded them.

Quick reference cheat sheet#

# Password
evil-winrm -i TARGET_IP -u USERNAME -p 'PASSWORD'
# Pass-the-hash (NT hash)
evil-winrm -i TARGET_IP -u USERNAME -H NTHASH
# HTTPS (5986)
evil-winrm -i TARGET_IP -u USERNAME -p 'PASSWORD' -S
# With local scripts + binaries for in-memory loading
evil-winrm -i TARGET_IP -u USERNAME -p 'PASSWORD' -s scripts/ -e bins/
# In-shell:
#   upload local remote   |   download remote   |   services   |   Bypass-4MSI

Mini decision tree#

  • WinRM open + password: -u USER -p PASS.
  • Only a hash: -H NTHASH (pass-the-hash).
  • Port 5986 only: add -S.
  • Need to crack first: hashcat / john, then come back.
  • Login fails despite valid creds: the user is probably not WinRM-capable; find another path.

Final checklist#

  • Account + host are in scope
  • WinRM port confirmed (5985/5986)
  • Correct auth method (-p / -H / cert, -S for HTTPS)
  • Session logged; files moved are noted
  • No real third-party targets

Final summary#

Evil-WinRM is the cleanest interactive Windows shell when WinRM is open and you hold valid credentials. The fastest start is evil-winrm -i TARGET_IP -u USER -p PASS. The most common mistake is expecting it to work for an account that is not in Remote Management Users. Learn netexec next to validate which creds actually grant WinRM access before you log in.

Find us elsewhere

Merch, stickers, and moreSupport the work at the Solvere Labs shop