$theTitle=wp_title(" - ", false); if($theTitle != "") { ?>
About Virtualization, VDI, SBC, Application Compatibility and anything else I feel like
Several months ago I wrote about encrypting and decrypting RDP passwords. I left one thing open: encrypting the password up to the full 1329 bytes as mstsc does.
Many people were curious about it so I hope the answer is not a disappointment because it’s actually really simple (but I took me a while to figure that out nonetheless). In what I figure is an attempt to hide the password length mstsc always fills up the password with zeroes until it has 512 bytes length.
Then the password is encrypted like I described earlier which gives us a 1328 bytes password hash. So we have one mystery left, how to reach the 1329 bytes size which still is a strange value since the password is in Unicode which takes 2 bytes per char (so the size should be even).
As it turns out, mstsc just adds a zero!
Remote Desktop Password Encryption & Decryption Tool (52961 downloads)
17 Responses for "How rdp passwords are encrypted 2"
Hi,
I tried using the .NET wrapper provided by MS and using the help. But your tool is not able to decrypt the same. Could you please post the code for the encryption?
Is it possible to generate a hash for another user / Sid ? – I have a requirement using HP thin clients to generate the appropriate hash to insert in default.rdp file – it works for Adminstrator user on the thin client – but obviously not for the User account.
Hi,
I would like distribute the same file.rdp on my 2 different XP WS (with the same pwd).
Please, could you said me how to generate the ‘passord 51:b:’ with VBscript?
Thank for your reply.
Regards.
Dominik
@Dominique: This is not possible with VBS since there is no COM object that supports CryptProtect Data api.
You would either have to create a commandline encryption tool or a com enabled one to encrypt passwords with vbs.
Hi,
In that case, is your rdp2.exe usable from a command line with parameters?
Best regards.
Dominik
Remko, thanks for your Web site, thanks also to Justin Shepard for the translation into VB.
I have change something’s within his code and adapted the sub main to create an executable object with VB express 2005 (please transfer this news to Jeremy…)
Concerning my main code, I use 2 parameters (arguments): input file name & output file name. At the end of the encryption, the 1329 bytes are completed with the end of the encryption of 256 spaces.
####################################
Imports System
Imports System.IO
Imports System.Text
Imports System.Runtime.InteropServices
Imports System.ComponentModel
Imports Microsoft.VisualBasic
Public Module RdpEncrypt
Public Class DPAPI
_
Private Shared Function CryptProtectData( _
ByRef pPlainText As DATA_BLOB, _
ByVal szDescription As String, _
ByRef pEntropy As DATA_BLOB, _
ByVal pReserved As IntPtr, _
ByRef pPrompt As CRYPTPROTECT_PROMPTSTRUCT, _
ByVal dwFlags As Integer, _
ByRef pCipherText As DATA_BLOB _
) As Boolean
End Function
_
Private Shared Function CryptUnprotectData( _
ByRef pCipherText As DATA_BLOB, _
ByRef pszDescription As String, _
ByRef pEntropy As DATA_BLOB, _
ByVal pReserved As IntPtr, _
ByRef pPrompt As CRYPTPROTECT_PROMPTSTRUCT, _
ByVal dwFlags As Integer, _
ByRef pPlainText As DATA_BLOB _
) As Boolean
End Function
_
Friend Structure DATA_BLOB
Public cbData As Integer
Public pbData As IntPtr
End Structure
_
Friend Structure CRYPTPROTECT_PROMPTSTRUCT
Public cbSize As Integer
Public dwPromptFlags As Integer
Public hwndApp As IntPtr
Public szPrompt As String
End Structure
Private Const CRYPTPROTECT_UI_FORBIDDEN As Integer = 1
Private Const CRYPTPROTECT_LOCAL_MACHINE As Integer = 4
Private Shared Sub InitPrompt _
( _
ByRef ps As CRYPTPROTECT_PROMPTSTRUCT _
)
ps.cbSize = Marshal.SizeOf(GetType(CRYPTPROTECT_PROMPTSTRUCT))
ps.dwPromptFlags = 0
ps.hwndApp = IntPtr.Zero
ps.szPrompt = Nothing
End Sub
Private Shared Sub InitBLOB _
( _
ByVal data As Byte(), _
ByRef blob As DATA_BLOB _
)
‘ Use empty array for null parameter.
If data Is Nothing Then
data = New Byte(0) {}
End If
‘ Allocate memory for the BLOB data.
blob.pbData = Marshal.AllocHGlobal(data.Length)
‘ Make sure that memory allocation was successful.
If blob.pbData.Equals(IntPtr.Zero) Then
Throw New Exception( _
“Unable to allocate data buffer for BLOB structure.”)
End If
‘ Specify number of bytes in the BLOB.
blob.cbData = data.Length
Marshal.Copy(data, 0, blob.pbData, data.Length)
End Sub
Public Enum KeyType
UserKey = 1
MachineKey
End Enum
Private Shared defaultKeyType As KeyType = KeyType.UserKey
Public Shared Function Encrypt _
( _
ByVal keyType As KeyType, _
ByVal plainText As String, _
ByVal entropy As String, _
ByVal description As String _
) As String
If plainText Is Nothing Then
plainText = String.Empty
End If
If entropy Is Nothing Then
entropy = String.Empty
End If
Dim result As Byte()
Dim encrypted As String = “”
Dim i As Integer
result = Encrypt(keyType, _
Encoding.Unicode.GetBytes(plainText), _
Encoding.Unicode.GetBytes(entropy), _
description)
For i = 0 To result.Length – 1
encrypted = encrypted & Convert.ToString(result(i), 16).PadLeft(2, “0”).ToUpper()
Next
Return encrypted.ToString()
End Function
Public Shared Function Encrypt _
( _
ByVal keyType As KeyType, _
ByVal plainTextBytes As Byte(), _
ByVal entropyBytes As Byte(), _
ByVal description As String _
) As Byte()
If plainTextBytes Is Nothing Then
plainTextBytes = New Byte(0) {}
End If
If entropyBytes Is Nothing Then
entropyBytes = New Byte(0) {}
End If
If description Is Nothing Then
description = String.Empty
End If
Dim plainTextBlob As DATA_BLOB = New DATA_BLOB
Dim cipherTextBlob As DATA_BLOB = New DATA_BLOB
Dim entropyBlob As DATA_BLOB = New DATA_BLOB
Dim prompt As _
CRYPTPROTECT_PROMPTSTRUCT = New CRYPTPROTECT_PROMPTSTRUCT
InitPrompt(prompt)
Try
Try
InitBLOB(plainTextBytes, plainTextBlob)
Catch ex As Exception
Throw New Exception(“Cannot initialize plaintext BLOB.”, ex)
End Try
Try
InitBLOB(entropyBytes, entropyBlob)
Catch ex As Exception
Throw New Exception(“Cannot initialize entropy BLOB.”, ex)
End Try
Dim flags As Integer = CRYPTPROTECT_UI_FORBIDDEN
If keyType = keyType.MachineKey Then
flags = flags Or (CRYPTPROTECT_LOCAL_MACHINE)
End If
Dim success As Boolean = CryptProtectData( _
plainTextBlob, _
description, _
entropyBlob, _
IntPtr.Zero, _
prompt, _
flags, _
cipherTextBlob)
If Not success Then
Dim errCode As Integer = Marshal.GetLastWin32Error()
Throw New Exception(“CryptProtectData failed.”, _
New Win32Exception(errCode))
End If
Dim cipherTextBytes(cipherTextBlob.cbData) As Byte
Marshal.Copy(cipherTextBlob.pbData, cipherTextBytes, 0, _
cipherTextBlob.cbData)
Return cipherTextBytes
Catch ex As Exception
Throw New Exception(“DPAPI was unable to encrypt data.”, ex)
Finally
If Not (plainTextBlob.pbData.Equals(IntPtr.Zero)) Then
Marshal.FreeHGlobal(plainTextBlob.pbData)
End If
If Not (cipherTextBlob.pbData.Equals(IntPtr.Zero)) Then
Marshal.FreeHGlobal(cipherTextBlob.pbData)
End If
If Not (entropyBlob.pbData.Equals(IntPtr.Zero)) Then
Marshal.FreeHGlobal(entropyBlob.pbData)
End If
End Try
End Function
End Class
Sub Main(ByVal args() As String)
Try
Dim INfilename As String = args(0) ‘Input file with string without CrLf
Dim OUTfilename As String = args(1) ‘Output file
Dim EncryptedText As String
Dim TextToEncrypt As String
Dim EncryptedBlank As String
Dim BlankToEncrypt As String = Space(256)
TextToEncrypt = File.ReadAllText(INfilename)
EncryptedText = DPAPI.Encrypt(DPAPI.KeyType.MachineKey, TextToEncrypt, Nothing, “psw”)
EncryptedBlank = DPAPI.Encrypt(DPAPI.KeyType.MachineKey, BlankToEncrypt, Nothing, “psw”)
File.WriteAllText(OUTfilename, EncryptedText & _
Right(EncryptedBlank, 1329 – Len(EncryptedText))) ‘Encrypted blank to complete to 1329
Catch ex As Exception
While Not (ex Is Nothing)
Console.WriteLine(ex.Message)
ex = ex.InnerException
End While
End Try
End Sub
End Module
####################################
Regards.
Dominik
Hi Remko,
In your original post in the comments you wrote:
“I will write a new demo app to accompany the article that encrypts the full length password and can encrypt password that are valid for machine instead of user.
This makes it possible (eg) to publish an rdp connection.”
I’m just wondering if this is the app you were talking about. I tried to encrypt a password using the tool but didn’t see any option for machine vs. user; I tried it anyway but it doesn’t seem to work for any other user that signs on to the machine besides the one the password was encrypted under.
Any tips? Basically what I’m trying to do is make an RDP file that I can save under All Users\Desktop and any user who signs in can use it to connect to another machine using a single username/password. I tried your LaunchRDP utility however the missing ‘toolbar’ is an issue for me (users need to be able to minimize the remote desktop window)
Thanks!
Hello Remko,
Can you please give me code in C++ which does password encryption same as RDP does?
I am working on very urgent requirement.
It will be greate if you help me.
Thanks
Jignesh
Hi Remko !!
Can you please provide the source code in VC++ 6.0/mfc for the encryption/decryption tool that you have used in your ‘Remote Desktop Password Encryption & Decryption Tool (395)’.
Thanks in advance 🙂
Is there any VC++ code available?
Dominique Descat, if you will not be against, I would use your code for one of sourceforge projects: RDPman and it’s derivate?
Thanks.
(In e-mail it’s not .ur – shold be .ru, thanks for understanding)
Hey thanks for this info. Learned a lot from you.
I have done the same thing in C# but using DataProtection found in http://msdn.microsoft.com/en-us/library/aa302402.aspx#secnetht07_topic4
You can download the Encrypt/Decrypt sample here.
http://multirdpc.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=25591#ReleaseFiles
I used this tool to encrypt my password and put it in an RDP file.
It seems that Windows (XP Pro SP3) ignores the username and password entries that I put in the RDP file and will only use the credentials stored in the registry. It doesn’t matter whether I launch the RDP by double-clicking it or launching it using mstsc from a command prompt.
Does anyone know how to get Windows use the credentials I have stored in the RDP file? Is it because of the version of mstsc (and supporting files) that I am using? A policy? Thanks a lot
I want automated the file creation with .rdp extension for remote desktop and your program is very good but in my vb6 program the call at your program is not the good way.
is not possible for you create an rdp.dll with the encrypt function only ????
Best regards
[…] I found the article about decrypting saved RDP passwords at http://www.jaysonragasa.net/post/EncryptDecrypt-RDP-Password.aspx and https://www.remkoweijnen.nl/blog/2008/03/02/how-rdp-passwords-are-encrypted-2/. […]
Thank you for another informative site. Where else may just I am getting that type of info written in such a perfect approach? I have a mission that I’m just now working on, and I’ve been at the look out for such info.
Hi Remko,
I have following question:
If I created the MSTSC encrypted password for “secrettext” password on Desktop Machine-1, somehow I cannot use this encrypted password on Desktop Machine-2. Can we generate the MSTSC encrypted password for “secrettext” password, which will be work on different windows machines? Is there any API or any combination in “CryptProtectData” API to do this?
It’s very urgent, if you guide me in these case then it will be great help for me.
Thanks in advance.
Thanks & regards,
Santosh Patil
Leave a reply