Decrypting Remote Desktop Connection Manager Passwords with PowerShell

Today I needed to find a password for a certain account I had used before (but had forgotten), and I remembered that I had stored the credentials in the Remote Desktop Connection Manager, Microsoft’s free RD tool. Of course, it crossed my mind whether these credentials could be decrypted, and it turns out they can, quite easily, with a little PowerShell.

The credentials are stored in encrypted form in the RDG file you create for your RDP connections. It’s just an XML file, so can be easily parsed with PowerShell. Using a handy trick blogged by , I decrypted all the credentials found in the RDG file.

The passwords can only be decrypted with the user profile that added them to the RDG file, however, so they are still reasonably secure. If the credentials were added by another account or on another system, you will get a “Failed to decrypt” error as seen below, which is the same error you get if you try to copy the RDG file and open it on another computer or with another user profile.

Needless to say, I found the password I needed!

capture


# Path to RDCMan.exe
$RDCMan = "C:\Program Files (x86)\Microsoft\Remote Desktop Connection Manager\RDCMan.exe"
# Path to RDG file
$RDGFile = "$env:USERPROFILE\Documents\RDPConnections.rdg"
$TempLocation = "C:\temp"

Copy-Item $RDCMan "$TempLocation\RDCMan.dll"
Import-Module "$TempLocation\RDCMan.dll"
$EncryptionSettings = New-Object -TypeName RdcMan.EncryptionSettings

$XML = New-Object -TypeName XML
$XML.Load($RDGFile)
$logonCredentials = Select-XML -Xml $XML -XPath '//logonCredentials'

$Credentials = New-Object System.Collections.Arraylist
$logonCredentials | foreach {
    [void]$Credentials.Add([pscustomobject]@{
    Username = $_.Node.userName
    Password = $(Try{[RdcMan.Encryption]::DecryptString($_.Node.password, $EncryptionSettings)}Catch{$_.Exception.InnerException.Message})
    Domain = $_.Node.domain
    })
    } | Sort Username

$Credentials | Sort Username

10 thoughts on “Decrypting Remote Desktop Connection Manager Passwords with PowerShell

  1. Thanks Trevor, I had never considered this.

    I had to make a modification to the XPath parameter get this to work in my situation. Just posting back in case anyone’s experience is the same.

    # Path to RDCMan.exe
    $RDCMan = “C:\Program Files (x86)\Microsoft\Remote Desktop Connection Manager\RDCMan.exe”
    If (-not(Test-Path $RDCMan)){break}

    $RDGFiles = (GCI “$env:USERPROFILE\*” -Recurse -Include *.rdg).FullName

    Copy-Item $RDCMan “$env:TEMP\RDCMan.dll”
    Import-Module “$TempLocation\RDCMan.dll”
    $EncryptionSettings = New-Object -TypeName RdcMan.EncryptionSettings

    Foreach ($rdg in $RDGFiles){
    Write-Host -ForegroundColor Cyan “Examining $rdg”
    $XML = New-Object -TypeName XML
    $XML.Load($rdg)
    $logonCredentials = Select-XML -Xml $XML -XPath ‘//credentialsProfile’

    $Credentials = New-Object System.Collections.Arraylist
    $logonCredentials | foreach {
    [void]$Credentials.Add([pscustomobject]@{
    Username = $_.node.username
    Password = $(Try{[RdcMan.Encryption]::DecryptString($_.Node.password, $EncryptionSettings)}Catch{$_.Exception.InnerException.Message})
    Domain = $_.node.domain
    })
    }
    }

    $Credentials

  2. Hi Jacques,

    I had the same problem as you (my passwords are encrypted using a certificate). Find the certificate thumprint–I did this by looking it up in MMC but there are a bunch of ways to enumerate the certificate store and retrieve a thumbprint.

    After that, it’s a quick change to the script:

    1. Set the CredentialData and EncryptionMethod properties to use the cert thumbprint:
    $EncryptionSettings = New-Object -TypeName RdcMan.EncryptionSettings
    # add:
    $EncryptionSettings.CredentialData.Value = “546170e5cf1b08c49377c73b19da1b3eed63fca6” $EncryptionSettings.EncryptionMethod.Value = [RdcMan.EncryptionMethod]::Certificate

    2. In my case, the logons I saved were all in connection group “profiles”, which were in a different section of the XML file. But otherwise the same approach would work, so I modified the XPath:

    $profiles = Select-XML -Xml $XML -XPath ‘//credentialsProfile’
    ForEach ($profile in $profiles) {
    $userName = $profile.Node.userName
    $password = $profile.Node.password
    $domain = $profile.Node.domain
    $passwordDecrypted = [RdcMan.Encryption]::DecryptString($password, $EncryptionSettings)
    Write-Output “$userName@${domain}: $passwordDecrypted”
    }

    Hope that helps!

  3. Hi,

    From a security perspective, if someone gets access to the RDG file, is it possible to crack the pw by replicating the username on a test domain on an environment. For example 2 VMs one representing a domain controller having an identical domain name as the real scenario and an identical username in the AD to the one that created the rdg file. The other VM would be domain joined representing a workstation where the user will execute the script above. Good to see if it works in this way, as it would be a nasty compromise.

  4. Thanks a bunch, Trevor!

    I was in the process of migrating to a new laptop. I’ve been using RDCM for years, from well before pw were encrypted. I was troubled to find the new laptop could not decipher the credentials now. But, I found your page, and your script worked nicely.
    Just a couple of bump on the road. I was getting an error importing RDCMan.dll. Resolved with update to PowerShell version 4. (original version was 2!???? I and run/install MS updates regularly)
    In case someone has the same issue, I referenced the following URL: https://support.royalapplications.com/support/solutions/articles/17000027868-import-module-could-not-load-file-or-assembly-file-c-program-files-x86-code4ward-net-royal-t

    It is a different dll, but same error/issue.

    Then, the output I got was not complete… it missed all the group passwords settings (not all, but a lot of the passwords are inherited from the group entry). I was able to modify the script to get to just the group credentials settings. Unfortunately, I had to get the entire output using 2 scripts since I didn’t know how to process/reference the XML entries for everything in one step.
    Oh, and additionally, I modified the script to also display the server address and display name with the credentials. I had too many credential entries to know which ID belonged to which server.

    All this to say: I would not have been able to do this much without your insightful script.

    Kind Regards.

    1. FuzzySCSI – you mentioned you were successful in exporting out all the group passwords and server address and display names – any chance you’re able to share your modified version of the script?

  5. @FUZZYSCSI
    I am trying to get the password I stored on my RDCM
    I will appreciate if you can help me, I have no idea how to do this and I do not have the path “C:\Program Files (x86)\Microsoft\Remote Desktop Connection Manager\

  6. Great post ! Thank You.
    A little improvement i found 🙂

    $logonCredentials = Select-XML -Xml $XML -XPath ‘//credentialsProfile|//logonCredentials’$logonCredentials = Select-XML -Xml $XML -XPath ‘//credentialsProfile|//logonCredentials’

  7. A roll-up of everybody’s changes to this code, bringing it up to date for idiots like me would be really good.
    Especially since some of them don’t really show much context :-/

  8. I don’t know if this works with the new RDCMan (v2.90, released January 27, 2022), but if your organization uses Crowdstrike (or similar security software), be careful running this. I tried it on my development machine with a file I use in that new RDCMan version and it didn’t work, but Crowdstrike immediately network-quarantined my machine and a few minutes later our security team messaged me.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.