Remote desktop shadowing is Microsoft's free alternative to VNC, TeamViewer, DameWare etc. (well, sort of and only sometimes) - najki78/publicStuff GitHub Wiki

Remote desktop services shadowing (also called shadow session mode)

Remote desktop services shadowing (from now on Shadowing) is one of the lesser known Windows features that enables connecting to the remote computer “console” using RDP.

It allows IT personnel to view (and interact with) the remote desktop while letting the screen visible to the personnel behind the console. Unlike mstsc /console, it does not lock the console view for locally logged on user, letting both local console user and remote user to see the console screen simultaneously.

If you ask Why not to use Quick Assist or any other remote control tool?, you ask the right question.

The key strength of Shadowing though is its Unattended mode. When you need to remotely control unsupervised machines, without waiting for the user approval to accept the remote control connection.

Although Shadowing is possible in Attended mode as well (requiring remote user approval), due to the complexity of the configuration, instead of Shadowing, I would still recommend Microsoft's Quick Assist free remote control solution.

When does it make sense to use Shadowing instead of the commercial software?

  • When you do not want to lose money on the commercial software
  • When you are fine with only core functionality and no additional bells and whistles
  • For scenarios benefiting from the Unattended mode (remotely connecting to unsupervised machines with configured autologon, kiosks, machines on the plant shop floor, shared machines etc)

Operational modes

When enabled, there are two main modes in which Shadowing might operate:

  • Attended - asking remote computer's console logged on user permission to establish Shadowing
  • Unattended - not asking for any approval

Unattended mode is potentially dangerous from the security perspective, but very useful for the machines with no permanent presence of the user.

Each of these modes might be configured for Full Control or View Session only.

Pros:

  • Free. Built in Windows Client OS.
  • Built on Remote Desktop Services (even using mstsc.exe client to connect) - although (surprisingly) doesn’t use RDP 3389/TCP port for incoming traffic.
  • Works fine with Windows 10 clients, both AAD joined and Hybrid joined (assuming AD only clients as well, but not having such client for testing).

Cons:

  • In unattended mode, by default, Shadowing offers no indication that console is being shadowed (remotely watched) and therefore might only be used on non-sensitive machines where this does not cause a security concern (e.g. shared Windows 10 machines on the shop floor etc). If, on the remote machine, you want the console user to be aware if the session is being shadowed, click here for more information.
  • In unattended mode, Shadowing requires that someone is logged on to the console. If the console is logged off, you can still use traditional mstsc /console Remote Desktop, if enabled.
  • The console session cannot be locked. You have to ensure lock screen is disabled (proactive remediation script below handles that).
  • Access is allowed only to members of local Administrators on the remote machine and/or by granting special permissions.
  • No additional functionality comparing to 3rd party products. No chat with console user, file transfer etc.
  • The feature might be unreliable at times, often due to the local firewall issue or providing distorted image when Shadowing.

Implementation

The remaining part of this article focuses on setting up Shadowing using Intune and highly recommend you see excellent Roman Maximov's Remote Desktop Shadowing summary before reading further.

Enabling Shadowing on the remote computer

The scripts below configure Shadowing for the Full control without user approval scenario (unattended mode).

For Attended mode (with user approval), there are few modifications needed to the scripts:

  • changing the Shadow registry value from "2" (Full control without user approval) to either "1" (Full control with user’s permission) or "3" (View session with user’s permission),
  • removing AllowLockScreen registry key that is disabling Lock screen and
  • removing creation of the scheduled task "Disable Lock Screen" (that ensures the screen is never locked).

Enabling required services on the Windows client

If you want to enable Shadowing using Intune, you can use these proactive remediations. Apart from enabling Shadowing, the script disables Lock screen functionality. The scripts run in SYSTEM context (Run this script using the logged-on credentials: No). The device has to be restarted after first run of the script to take the changes into effect.

Enabling local Windows firewall exceptions

Create a new Microsoft Defender Firewall Rule (in Microsoft Endpoint Manager admin center -> Endpoint security -> Manage - Firewall) with these rules enabled:

  1. Name: Remote Desktop - Shadow (TCP-In) - %SystemRoot%\system32\RdpSa.exe

Interface Types: Lan, Wireless

File Path: %SystemRoot%\system32\RdpSa.exe

Network Types: FWPROFILETYPEDOMAIN: This value represents the profile for networks that are connected to domains., FWPROFILETYPESTANDARD: This value represents the standard profile for networks. These networks are classified as private by the administrators in the server host. The classification happens the first time the host connects to the network. Usually these networks are behind Network Address Translation (NAT) devices, routers, and other edge devices, and they are in a private location, such as a home or an office. AND FWPROFILETYPEPRIVATE: This value represents the profile for private networks, which is represented by the same value as that used for FWPROFILETYPESTANDARD.

Direction: The rule applies to inbound traffic.

"Service Name" has been set to not configured

"Local Port Ranges" has been set to not configured

Action: Allow

Description: Inbound rule for the Remote Desktop service to allow shadowing of an existing Remote Desktop session. (TCP-In)

Protocol: 6

  1. Name: File and Printer Sharing (SMB-In) - 445/tcp

Interface Types: Wireless, Lan

"File Path" has been set to not configured

Network Types: FWPROFILETYPEDOMAIN: This value represents the profile for networks that are connected to domains., FWPROFILETYPESTANDARD: This value represents the standard profile for networks. These networks are classified as private by the administrators in the server host. The classification happens the first time the host connects to the network. Usually these networks are behind Network Address Translation (NAT) devices, routers, and other edge devices, and they are in a private location, such as a home or an office. AND FWPROFILETYPEPRIVATE: This value represents the profile for private networks, which is represented by the same value as that used for FWPROFILETYPESTANDARD.

Direction: The rule applies to inbound traffic.

"Service Name" has been set to not configured

"Local Port Ranges" has been set to not configured ---> changed to 445/tcp [2022-08-17 Lubos]

Action: Allow

Description: Inbound rule for File and Printer Sharing to allow Server Message Block transmission and reception via Named Pipes. [TCP 445]

Protocol: 6

How to verify Shadowing is enabled on the remote computer

  1. Check if the following registry entries are present:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\SessionData]

"AllowLockScreen"=dword:00000000

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server]

"AllowRemoteRPC"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services]

"Shadow"=dword:00000002

The allowed values for "Shadow" are:

0 – disable remote control;

1 — full control with user’s permission;

2 — full control without user’s permission;

3 — view session with user’s permission;

4 — view session without user’s permission.

  1. Verify in the Task Scheduler the existence of the scheduled task “Disable Lock Screen”. It runs on user logon and after the session is unlocked and re-sets "AllowLockScreen"=dword:00000000 (otherwise the value is changed to “1“ by the system).

  2. Start Windows Defender Firewall with Advanced Security console - wf.msc (Run As Administrator) and in Monitoring -> Firewall, check the firewall rules "Remote Desktop - Shadow (TCP-In) - %SystemRoot%\system32\RdpSa.exe" and "File and Printer Sharing (SMB-In) - 445/tcp" are enabled.

  3. Ensure that Windows service Remote Desktop Services (TermService) on the remote machine is running.

Granting special permissions to use Shadowing

In its default settings, only members of Administrators group on the remote machine are able to connect using Shadowing. In case you need to grant permissions to connect using Shadowing to other account, not a member of Administrators group, grant it special permissions:

Important: The example below does not work for granting permissions to Azure AD group, only Azure AD user. This is the current limitation of Windows and to bypass it, use the workaround below.

  • Retrieve the configuration of special permissions:

CMD:

wmic /NameSpace:\\root\cimv2\TerminalServices PATH WIN32_TSPermissionsSetting.TerminalName="console" get StringSecurityDescriptor

PowerShell:

$WIN32_TSPermissionsSetting = get-ciminstance -namespace root\cimv2\terminalservices -class WIN32_TSPermissionsSetting | Where-Object TerminalName -EQ "console" $WIN32_TSPermissionsSetting

  • Set special permissions to connect using Shadowing (an example for Azure AD account):

CMD:

wmic /NameSpace:\\root\cimv2\TerminalServices PATH WIN32_TSPermissionsSetting.TerminalName="console" call AddAccount "AzureAD\[email protected]",2

PowerShell:

$WIN32_TSPermissionsSetting = get-ciminstance -namespace root\cimv2\terminalservices -class WIN32_TSPermissionsSetting | Where-Object TerminalName -EQ "console" $WIN32_TSPermissionsSetting | Invoke-CimMethod -MethodName AddAccount -Arguments @{AccountName="AzureAD\[email protected]";PermissionPreSet=2}

CMD:

wmic /namespace:\\root\CIMV2\TerminalServices PATH Win32_TSPermissionsSetting WHERE (TerminalName like 'console') CALL RestoreDefaults

PowerShell:

$WIN32_TSPermissionsSetting = get-ciminstance -namespace root\cimv2\terminalservices -class WIN32_TSPermissionsSetting | Where-Object TerminalName -EQ "console"

$WIN32_TSPermissionsSetting | Invoke-CimMethod -MethodName RestoreDefaults

Always logoff the current session on the remote machine for the changes to take effect.

Workaround - Granting special permissions to use Shadowing to Azure AD users

Until Microsoft makes it possible to grant these special permissions to Azure AD group, use the workaround using a local group on the remote machine.

  1. On the remote machine, create a local group, for instance:

CMD:

net localgroup "Remote Console Users" /add /comment:"Group of users allowed to connect to the console using Remote Desktop Services Shadowing."

PowerShell:

if (-not (Get-LocalGroup -Name "Remote Console Users" -ErrorAction SilentlyContinue)) { New-LocalGroup -Name "Remote Console Users" -Description "Users allowed to connect using RDS Shadowing." -ErrorAction SilentlyContinue }

  1. Grant special permissions to a local group (logoff the console session and re-login for the change to take effect):

CMD:

wmic /NameSpace:\\root\cimv2\TerminalServices PATH WIN32_TSPermissionsSetting.TerminalName="console" call AddAccount "\Remote Console Users",2

PowerShell:

$WIN32_TSPermissionsSetting = get-ciminstance -namespace root\cimv2\terminalservices -class WIN32_TSPermissionsSetting | Where-Object TerminalName -EQ "console"

$WIN32_TSPermissionsSetting | Invoke-CimMethod -MethodName AddAccount -Arguments @{AccountName="\Remote Console Users";PermissionPreSet=2}

  1. Add the Azure AD account(s) into a local group:

CMD:

net localgroup "Remote Console Users" /add AzureAD\[email protected]

PowerShell:

Add-LocalGroupMember -Group "Remote Console Users" -Member "AzureAD\[email protected]" -ErrorAction SilentlyContinue

Note: Although, technically, instead of directly adding Azure AD user account(s) into a local group, we might add Azure AD group into a local group. However, when an Azure Active Directory group is added to the Remote Console Users group on a Windows device, it isn't honoured when the user that belongs to the Azure AD group logs in through Shadowing. I had a Support Case opened with Microsoft to find a workaround, but unfortunately there is none: We might only add AAD user accounts, not AAD groups, into the local group and make it work with Shadowing.

Launching Shadowing session (command line)

If you can do without a fancy GUI application and are fine with text mode interface, after enabling Shadowing on the remote machine(s), follow these steps to initiate Shadowing connection from your computer:

  1. Download GitHub - Launching Shadowing session via Powershell script.

  2. Convert the script into an executable file:

Install-Module ps2exe

Invoke-ps2exe "LaunchShadowSession.ps1"

  1. Once you have your LaunchShadowSession.exe ready, start it with the credentials that are member of the local Administrators group on the remote machine. If your locally logged on user is a member of the remote machine Administrators group (or has granted special permissions), go ahead and start LaunchShadowSession.exe.

If not and you need to start LaunchShadowSession.exe under different credentials:

  • Hold Shift key and right click on the launchShadowSession.exe file. From the right-click context menu, select Run as different user.
  • Enter the credentials of the account that is a member of local Administrators group on the remote machine (or has granted special permissions). If such account is in AzureAD, use the form AzureAD\userPrincipalName (e.g. AzureAD\[email protected]).
  • Enter the name / IP address of the remote machine. The shadowing session will be initiated. The console user will NOT be notified you have started to shadow him/her.

Tip: To disconnect from a user session and exit the Shadow mode, press ALT+* on your machine or Ctrl+* on the remote machine (if no alternative combinations are set).

Important: If nobody is logged on the console or the device is locked, the shadowing session cannot be established.

Launching Shadowing session (GUI)

If you prefer GUI, I created a simple application to initiate Shadowing connection from your computer:

image

  1. Download GitHub - Launching Shadowing session via Powershell script.

  2. Convert the script into an executable file:

Install-Module ps2exe

Invoke-ps2exe "RDS-Shadowing-GUI [public].ps1" -requireAdmin -DPIAware -credentialGUI -title "Remote Desktop Services Shadowing GUI"

Note: The parameter -requireAdmin does require starting the app with local Admin privileges, if not required for your purposes, remove it when compiling EXE file.

The rest is similar to the command line version. GUI version allows to store description with the device names (in the registry) and to initiate basic diagnostics for a device (to check if the required ports are opened etc). Double-click on the device name initiates Shadowing session.

Monitoring Shadowing session on the remote machine

If, on the remote machine, you want the console user to be aware if the session is being shadowed (or when it has been shadowed for the last time), run the ShadowingSystrayIndicator script on the remote machine. It will start a systray indicator, making it easy to notice if the console is being shadowed or not.

Interesting article on monitoring Shadowing sessions and (if needed) notifying console user about being shadowed (used in the script above): http://woshub.com/rdp-session-shadow-to-windows-10-user/

All links mentioned in the article:

https://social.technet.microsoft.com/wiki/contents/articles/19804.remote-desktop-services-session-shadowing.aspx

http://microsoftplatform.blogspot.com/2013/07/detailed-walkthrough-on-remote-control.html

https://swarm.ptsecurity.com/remote-desktop-services-shadowing/

Link to the second part: Remote desktop shadowing troubleshooting