Search code examples
c++rdpdpapi

Using CryptDataProtect to output encrypted password for use in RDP file generates the incorrect hash


I am trying to generate an RDP file in C++ to automatically log on to a remote machine. I am using the CryptProtectData function to generate an encrypted string which can then be written to the password 51:b parameter of the file. However, when I then try and connect with this file, it says the password is invalid.

I have tried the following code:

#include <dpapi.h>
#include <sstream>

DATABLOB in ;
DATABLOB out ;
BYTE *pw_text = (BYTE *)L"to_encrypt"; // RDP uses unicode from my understanding...
DWORD pw_length = wcslen(L"to_encrypt");

in.pbData = pw_text ;
in.cbData = pw_length ;

CryptProtectData(&pw_in, L"PSW", NULL, NULL, NULL, NULL, &pw_out);

std::stringstream ss ;
ss << std::hex ;

for (int i = 0; i< pw_out.cbData; i++)
{
    ss << std::setw(2) << std::setfill('0') << (int)pw_out.pbData[i] ;
}

However, when I take the string contained in ss, paste it into my RDP file and attempt to connect it says the password is incorrect.

If I use the Powershell command to encrypt the password and use that it works, but it would be better if I can do this in C++ along with the rest of the application.


Solution

  • The cbData field in the DATA_BLOB structure is the length in bytes.

    On the other hand, the wcslen function returns the number of characters.

    One wide character is represented using 2 bytes, so there will be some difference.

    Try multiplying the size of one character to the number of characters.

    DWORD pw_length = sizeof(*L"a") * wcslen(L"to_encrypt");