Have you ever wondered what the "/public" command-line option in MSTSC actually does? It enables "public mode" in the RDP client, a feature somewhat similar to "incognito mode" in web browsers. This is a feature meant to be used on a "public" or "shared" computer, where users might want to prevent credentials, session details, and cached images from being stored locally.
For forensic analysts, the traces left behind by a malicious attacker using MSTSC on a compromised system can be a gold mine of information. Here are a list of all the features affected by the RDP public mode:
Connection settings
Did you know that mstsc saves connection settings to the hidden Default.rdp file? With the public mode enabled, mstsc won't let you save modifications to connection settings to that file:
The simplest way to edit it manually is to launch Notepad from the command-line: notepad "~\Documents\Default.rdp"
.
Credential caching
The Windows credential manager is used by mstsc to save credentials locally to be reused for new connections to the same server. The public mode disables using cached credentials, such that you will be prompted for credentials even if they are available locally:
Saved credentials use the "TERMSRV/" prefix and can be listed using this command:
cmdkey /list | ? { $_ -Match "TERMSRV/" } | % { $_ -Replace ".*: " }
The public mode also prevents the user from saving credentials in the login prompt:
Persistent Bitmap caching
The most notable artifact left by mstsc is the persistent bitmap cache. In RDP, the server breaks the desktop image into bitmap fragments, caching them on the client. When a fragment repeats, the server instructs the client to reuse the cached version instead of resending it. However, caching only improves performance after the client has stored enough fragments. To speed up new connections, the persistent bitmap cache allows bitmaps to be retained across sessions.
While the public mode disables this feature, it can also be disabled separately using BitmapCachePersistEnable:i:0
in the .RDP file. The persistent bitmap cache stores files (bcache24.bmc, Cache0000.bin, Cache0001.bin, etc) under %LOCALAPPDATA%\Microsoft\Terminal Server Client\Cache
. While the cache format is not documented, you can use BMC-Tools to extract its bitmap contents:
git clone <https://github.com/ANSSI-FR/bmc-tools> && cd bmc-tools
python .\bmc-tools.py -s "$Env:LocalAppData\Microsoft\Terminal Server Client\Cache" -d .
You can then browse through thousands of bitmap fragments from previous remote desktop sessions:
Keep in mind that the bitmap cache isn't a reliable recording method - it's like trying to reconstruct shredded documents by digging through the recycling bin. This being said, it can still be a treasure trove of information.
Most recently used servers
The Microsoft RDP client remembers up to 10 most-recently used (MRU) servers, making it easy to select a server from the dropdown without typing it all again:
The public mode disables updating that server list which is stored in the registry:
[HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Default]
"MRU0"="10.10.0.25"
"MRU1"="IT-HELP-TEST.ad.it-help.ninja"
"MRU2"="IT-HELP-DVLS.ad.it-help.ninja"
"MRU3"="IT-HELP-WAC.ad.it-help.ninja"
"MRU4"="IT-HELP-GW.ad.it-help.ninja"
In other words, you will still see the dropdown list with the public mode, but mstsc will not update it with new servers you connected to.
Server username hints
To speed things up at the login prompt, mstsc remembers the last username used to connect to a given server and pre-selects it for you:
This information is stored in the registry under HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Servers\Server\UsernameHint,
like this:
[HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Servers\10.10.0.25]
"UsernameHint"="Administrator@ad.it-help.ninja"
Aside from revealing the username, this registry key also reveals servers that you have connected to. Again, the public mode prevents this information from being used and stored.
Server certificate exceptions
There is not a single IT administrator in the universe who isn't familiar with the yellow certificate warning dialog from MSTSC. Yes, it is possible to deploy proper certificates for RDP, but let's be honest: we've all used that "Don't ask me again for connections to this computer checkbox" at least once:
As you may have guessed, the RDP public mode disables server certificate exceptions, because they are saved in the registry under HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Servers\Server\CertHash,
like this:
[HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Servers\10.10.0.25]
"CertHash"=hex:13,fe,21,42,92,fc,6a,9d,ac,ea,a0,3d,b5,9b,59,c8,90,6f,37,b9,cc,\
31,08,9d,63,f7,4b,e7,c4,3b,77,f2
The certificate hash itself is not very useful, but because it is stored by server name, it leaves a trace of the servers you have connected to.
Server authentication exceptions
The server authentication level in RDP is a bit trickier to understand: the server can be authenticated through its certificate, Kerberos, or both. To see how the public mode affects server authentication, make sure that server authentication is set to warn you if server authentication fails. Alternatively, modify your .RDP file with authentication level:i:2
:
When connecting to an untrusted server (when neither certificate validation or Kerberos validation can be used to authenticate the server), you should see this security warning dialog:
Notice how the public mode disables the "Don't ask me again for connections to this computer" checkbox, but also disables the saved credentials usage. If you add a security exception for a server, it will be stored under HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\LocalDevices
, like this:
[HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\LocalDevices]
"10.10.0.25"=dword:0000004d
The destination server name is stored, so again, it can be used to find servers you have connected to. As for the associated DWORD value, it changes depending on the local resources or devices you have authorized for the connection (drives, clipboard, printer, etc).
Cleaning up
The RDP public mode is great, but what if you didn't use it previously and want to reset mstsc in a clean state? Here's a PowerShell code snippet to wipe all of the local artifacts left behind (saved credentials, persistent bitmap cache, and registry keys):
cmdkey /list | ? { $_ -Match "TERMSRV/" } | % { $_ -Replace ".*: " } | % { cmdkey /delete:$_ }
Remove-Item -Path "$Env:LocalAppData\Microsoft\Terminal Server Client\Cache" -Recurse -ErrorAction SilentlyContinue
Remove-Item -Path "$Env:LocalAppData\Microsoft\Terminal Server Client\Cache" -Recurse -ErrorAction SilentlyContinue
Remove-Item -Path "HKCU:\Software\Microsoft\Terminal Server Client\Default" -Force -ErrorAction SilentlyContinue
Remove-Item -Path "HKCU:\Software\Microsoft\Terminal Server Client\Servers" -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item -Path "HKCU:\Software\Microsoft\Terminal Server Client\LocalDevices" -Recurse -Force -ErrorAction SilentlyContinue
Using the RDP public mode can be useful to work around weird issues, often caused by leftover saved credentials and username hints. While rare, a corrupted persistent bitmap cache can cause visual glitches in RDP. I recommend trying the public mode when you have no idea what the problem might be, but it could be related to one of the features listed above.