Home About

Exploring Remote Desktop Manager


I've been meaning to take a look at this product for a while, since I ported Ben Turner and Rich Hicks implementation of Remote Desktop Connection Manager to .NET. There PowerShell Version can of that can be found here.

With that said, Remote Desktop Manager was the next one to look at (no, its not the same thing :D).



The Application

It has some cool Credential Entry options:


It also has a load of different Sessions, for example:


Even AD, Citrix and iDRACs:


As well as PowerShell Remoting:


I want to focus on extracting Windows Credentials, although there are a lot of options for other Third-Party Credentials.

Spectating the Application

I want to see where its storing the data I give it, easiest way is Process Monitor:


And in Remote Desktop Manager:


When that is done, it goes to the Local Data Source:


Some ProcMon later, a few interesting DLLs are found:

C:\Program Files (x86)\Devolutions\Remote Desktop Manager Free\Devolutions.Wayk.Native.Windows.dll
C:\Program Files (x86)\Devolutions\Remote Desktop Manager Free\Devolutions.Wayk.Net.Windows.dll
C:\Program Files (x86)\Devolutions\Remote Desktop Manager Free\Devolutions.WaykDen.Client.dll
C:\Program Files (x86)\Devolutions\Remote Desktop Manager Free\Devolutions.Zxcvbn.dll
C:\Program Files (x86)\Devolutions\Remote Desktop Manager Free\Itenso.dll
C:\Program Files (x86)\Devolutions\Remote Desktop Manager Free\System.ValueTuple.dll
C:\Program Files (x86)\Devolutions\Remote Desktop Manager Free\x64\DevolutionsWayk.dll

As well as a bunch of operations in:




However, there is a file called RemoteDesktopManagerFree.cfg, which contains:


If I create another entry, does it give me two of these?

Nope, its still one:


But, the Connections.db does update:


Back to this database! To be honest, the Dashboard does mention this:



As everything is pointing me to this database, I'll load it up in SqliteStudio. Clicking through all the available tables, ConnectionHistory contains the credentials names:


TESTTESTTEST and TESTTESTTESTAGAIN contain different credentials, and the DATA field contains two different strings:





The first 213 characters are the same:


As cool as this is, their Security Overview details:

All passwords stored in the data sources are encrypted using a strong encryption algorithm, to the extent that if a user attempts to access the data directly in the database, it will be considered unreadable.

It then goes on to say:

If you choose to store passwords locally, Remote Desktop Manager will use the same mechanism used by mstsc.exe (Remote Desktop Manager client), which stores the passwords in the Windows Credential Manager. It must be noted that the password will not be able to be viewed due to being encrypted by Windows. For obvious reasons, this choice also means that credentials stored in this fashion are not shared. Please refer to Windows Credential Manager for more information.

And finally:

The encryption key is built-in the application and is therefore the same for all copies of the software in circulation. It is imperative that you follow our recommended steps and apply a Security Provider to encrypt not only the passwords, but also all connection data stored in the data source. This will provide protection over your data at rest, using a key under your exclusive control.

So, if I establish a connection to a host, it should use the same mechanism as mstsc.exe and store credentials in the Credentials Manager. If that's the case, then RDPThief can be used to steal credentials from mstsc.exe. As for Windows Credential Manager, it is trivial to extract credentials from.

Before looking at the Windows Credential Manager, may as well see if the AES Key can be pulled from the Application; or if that is avoidable and a decryption function is accessible (similarly to Remote Desktop Connection Manager).

Crypto Hunting

Opening this in Process Hacker confirms it is a .NET application:


Naturally, the next thing is DotPeek. Some poking around later, it seems the important segments are obfuscated:


Reversing this can be a last resort. As I already mentioned, there are easier ways than reversing crypto to get credentials for RDP. I'll double check that they work, I can't really be bothered to debug the application to get the Key and IV when I don't need to.

Creating a Session

Lets create a session and see what it does:


The above screenshot is the application loaded and pointed towards the credentials created earlier.

Its worth noting that this application has a lot of functionality. In this case, the Display:


External presumably creates an mstsc.exe process. But, we'll see.

Now there is a new entry in Local Data Source:



Opening a session within the application loads it like so:


Looking at the process, it doesn't create an mstsc.exe process when opened as an embedded session, but it has a bunch of mstsc threads:


This appears to be the MsTscAx Class, which makes sense.

When its opened external, thats when the mstsc.exe process is spawned as a child:


So, how does Windows Credential Manager work here. Embedded first:



And now external (I'm expecting mstsc.exe to add the credentials to this manager):


As expected. TERMSRV/ is now an entry.

This is trivial to extract with CredEnumerateA, and the only way to get mstsc.exe involved from RDPThief is to use the external feature. So far nothing specific is used to attack this application. However there is one last thing I want to check, and that is APIMonitor. I want to see how MsTscAx is being used.

API Monitor

Starting API Monitor and monitoring Remote Desktop Manager, mstscax.dll is seen an awful lot. Poking through the results, this sticks out:


CredIsMarshaledCredentialW is the target within RDPThief. Looking through the code, Rio used Detours to hook this function and it can be seen on line 77.

RDPThief works by monitoring for mstsc.exe processes and injects the DLL into that process, this can be seen in the Agressor Script. A quote from the README:

An aggressor script accompanies it, which is responsible for managing the state, monitoring for new processes and injecting the shellcode in mstsc.exe. The DLL has been converted to shellcode using the sRDI project (https://github.com/monoxgas/sRDI). When enabled, RdpThief will get the process list every 5 seconds, search for mstsc.exe, and inject to it.

If the user is using the external functionality of Remote Desktop Manager, then RDPThief is fine. If the user is using the embedded functionality, then this DLL will need to be injected into that process.

The CNA for RDPThief uses bshinject as seen on line 28:

bshinject($1, $pid , "x64" ,script_resource("RdpThief_x64.tmp"));

And then uses bshell to type the file:

alias rdpthief_dump {
    bshell($1,"type %temp%\\data.bin")

So, in theory I can replicate this but point it at a different process:


That works. Note 6644 is RemoteDesktopManagerFree.exe.

Finally, CredEnumerateA with SeatBelt:



I'm actually not to sure why its all hashes, if you know please let me know on Twitter. Presumably, it is some kind of credential guard but I wanted to explore some fancy form of credential extraction. It is worth noting, however, that you could probably load a DLL into this process, but I prefer the shellcode injection that RDPThief uses; bit more lowkey. Final thing to mention here is that the code to hook the required function isn't complex so I didn't feel the need to rewrite it, its probably easier just to expand the RDPThief CNA script to handle Remote Desktop Manager.

Remote Desktop Manager is like any other session manager. It has its limitations at a Windows Level, but as an application it seems to be protecting its data enough for me to not be bothered to reverse it. That said, its just obfuscation and a hard-coded AES Key/IV. Using popular-repurposed tools like RDPThief and Seatbelt, it falls victim to credential extraction. It would be cool to see how it handles the PowerShell, Azure etc credentials too. But, that can be left for another time.