Windows: Get and decrypt password from rdp files

Hi,

rdp files can store the password for a connection. The password is protected with the users key who saved the file.

The password can be decrypted by the .NET System.Security.Cryptography.ProtectedData class.

This script opens a rdp file and retrieve the user and the password.

<#
	.SYNOPSIS
		A PowerShell script to decrypt passwords from rdp files
	.DESCRIPTION
		A PowerShell script to decrypt passwords from rdp files
	.PARAMETER rdpfile
		rdp file
#>
[CmdletBinding()]
Param(
  [Parameter(Mandatory=$true,Position=1)][alias("f")][string]$rdpfile=""
)  

if(-not (Test-Path $rdpfile))
{
	write-warning ("File {0} not found!" -f $rdpfile)
	exit 2
}

[string]$sUserName=$null
[string]$sDomain=$null
[string]$sEncryptedPass=$null
[string]$sPass=$null

# Read RDP File
$sFileContent=Get-Content $rdpfile
foreach($sLine in $sFileContent)
{
	if($sLine.StartsWith("username:s:"))
	{
		$sUserName=$sLine.Replace("username:s:","")
	}
	elseif($sLine.StartsWith("domain:s:"))
	{
		$sDomain=$sLine.Replace("domain:s:","")
	}
	elseif($sLine.StartsWith("password 51:b:"))
	{
		$sEncryptedPass=$sLine.Replace("password 51:b:","")
	}
}
# Check Input
if(!$sUserName)
{
	write-warning "No username found!"
	exit 2
}
if(!$sEncryptedPass)
{
	write-warning "No encrypted password found!"
	exit 2
}
if($sUserName.IndexOf("\") -lt 0 -and  $sDomain)
{
	$sUserName="{0}\{1}" -f $sDomain,$sUserName
}


[System.reflection.assembly]::LoadWithPartialName("System.Security") | out-null

$iBytes=$sEncryptedPass.Length/2
[byte[]]$aEncryptedPasswordBytes = New-Object -TypeName byte[] $iBytes
for ($i = 0; $i -lt $iBytes; $i++) {
    $aEncryptedPasswordBytes[$i] = [System.Convert]::ToByte($sEncryptedPass.Substring($i*2,2), 16)
}
[byte[]]$passwordAsBytes = [System.Security.Cryptography.ProtectedData]::Unprotect($aEncryptedPasswordBytes, $null, [System.Security.Cryptography.DataProtectionScope]::CurrentUser)
$sPass=[System.Text.Encoding]::Unicode.GetString($passwordAsBytes)

write-host ("{0,-16} : {1}" -f "UserName",$sUserName)
write-host ("{0,-16} : {1}" -f "Password",$sPass)

The Convert[To|From]-SecureString string uses the same methods. So you can encrypt and decrypt the password these command-lets:

Encrypt

PS D:\> $PasswordEncrypted=("MySecretPassword!" | ConvertTo-SecureString -Force -AsPlainText ) | ConvertFrom-SecureString

Decrypt

PS D:\> $ssecPasswordEncrypted = ConvertTo-SecureString $PasswordEncrypted
PS D:\> $pSecString = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($ssecPasswordEncrypted)
PS D:\> $MyPlainPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto($pSecString)
PS D:\> write-host $MyPlainPassword

To add a password to the RDP file add the following line:

password 51:b:01000000d08c9d....

All after “b:” must be replace with the content of $PasswordEncrypted

Note: Such a file does only work on the PC where the encrypted password is generated because it is bound to the users key of that machine by using the DPAPI.

Michael

Further links

Extracting DPAPI Passwords

Leave a Reply Cancel reply