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

Advertisements

3 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!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s