You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用CryptProtectData生成RDP文件加密密码无效问题排查

解决C++生成RDP加密密码无效的问题

你的代码存在几处关键错误,导致加密后的密码无法被RDP客户端识别,以下是问题分析和修正方案:

问题点梳理

  • 变量名不匹配:定义了DATA_BLOB in_blob,但调用CryptProtectData时错误传递了未定义的pw_in,导致加密数据无效。
  • 字节长度计算错误:RDP密码要求是Unicode(UTF-16LE)格式,你仅传入了字符数而非实际字节数,且未包含字符串终止符\0,导致加密的数据不完整。
  • 加密标志缺失:未指定必要的加密标志,且加密范围与PowerShell默认逻辑不一致,导致加密后的密码无法被RDP解析。
  • 附加熵参数错误:传递了L"PSW"作为描述字段,但RDP密码加密不需要附加熵,这会导致加密逻辑与标准不符。

修正后的代码

#include <dpapi.h>
#include <sstream>
#include <iomanip>
#include <wchar.h>
#include <cstdio>

#pragma comment(lib, "crypt32.lib")

int main() {
    const wchar_t* password = L"to_encrypt";
    DWORD password_char_len = wcslen(password);

    // 准备输入数据:完整Unicode字符串(含终止符)的字节数
    DATA_BLOB in_blob;
    in_blob.pbData = reinterpret_cast<BYTE*>(const_cast<wchar_t*>(password));
    // 字节数 = (字符数 + 1) * 每个宽字符的字节数(UTF-16LE每个字符占2字节)
    in_blob.cbData = (password_char_len + 1) * sizeof(wchar_t);

    DATA_BLOB out_blob = { 0 };

    // 加密标志:禁止弹出UI,使用本地机器加密范围(与PowerShell的LocalScope一致)
    DWORD flags = CRYPTPROTECT_UI_FORBIDDEN | CRYPTPROTECT_LOCAL_MACHINE;

    // 执行加密:无附加熵、无描述字段
    BOOL encrypt_result = CryptProtectData(
        &in_blob,
        NULL,
        NULL,
        NULL,
        NULL,
        flags,
        &out_blob
    );

    if (!encrypt_result) {
        // 可通过GetLastError()获取具体错误码排查问题
        return 1;
    }

    // 将加密后的二进制数据转换为大写十六进制字符串
    std::stringstream ss;
    ss << std::hex << std::uppercase;
    for (DWORD i = 0; i < out_blob.cbData; ++i) {
        ss << std::setw(2) << std::setfill('0') << static_cast<int>(out_blob.pbData[i]);
    }

    // 输出结果,可直接写入RDP文件的`password 51:b`字段
    printf("加密后的密码(十六进制):%s\n", ss.str().c_str());

    // 释放DPAPI分配的内存,避免泄漏
    LocalFree(out_blob.pbData);

    return 0;
}

关键说明

  1. 字节长度计算:必须传入完整Unicode字符串的总字节数(包含终止符\0),确保加密的是RDP客户端期望的完整密码格式。
  2. 加密范围选择:
    • 使用CRYPTPROTECT_LOCAL_MACHINE时,加密后的密码可被本地所有用户使用;
    • 如果仅需当前用户使用,替换为CRYPTPROTECT_CURRENT_USER即可。
  3. 内存管理:加密完成后必须调用LocalFree释放out_blob.pbData,避免内存泄漏。
  4. 十六进制格式:使用std::uppercase统一输出大写十六进制字符,与RDP文件的标准格式保持一致(大小写实际不影响兼容性,但统一格式更稳妥)。

内容的提问来源于stack exchange,提问作者PenguinKenny

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 19:20:46