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

使用CryptUnprotectData解密Chrome Cookie AES密钥遇参数错误(错误码13)

解决CryptUnprotectData解密Chrome AES密钥时的参数错误(错误码13)

你的代码存在几个关键问题,导致CryptUnprotectData返回参数错误:

问题分析

  • 错误处理顺序错误:必须先判断CryptUnprotectData的返回值,只有当函数返回FALSE时,调用GetLastError才有意义,否则GetLastError可能返回之前操作的残留错误码。
  • 输入数据处理错误:Chrome加密的AES密钥是二进制数据,直接存入std::string会因可能包含的\0字节截断数据;同时DataBytes.cbData不应加1,string::size()已经是实际字节数,加1会把字符串末尾的\0当作有效数据传入,触发参数非法。
  • 输出BLOB初始化错误:不需要提前设置output.cbData,CryptUnprotectData会自动分配内存并填充output的两个字段。
  • 二进制数据输出错误:解密后的AES密钥是二进制数据,直接用cout << output.pbData会因遇到\0停止输出,无法正确显示。

修正后的代码

#include <iostream>
#include <Windows.h>
#include <wincrypt.h>
#include <fstream>
#include <string>
#include <vector>
using namespace std;

std::string GetLastErrorAsString()
{
    DWORD errorMessageID = ::GetLastError();
    if(errorMessageID == 0) {
        return std::string();
    }

    LPSTR messageBuffer = nullptr;

    size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                                NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
                                (LPSTR)&messageBuffer, 0, NULL);

    std::string message(messageBuffer, size);

    LocalFree(messageBuffer);

    return message;
}

// 辅助函数:二进制数据转十六进制字符串,方便查看密钥
std::string BytesToHexString(const BYTE* bytes, DWORD length)
{
    std::string hexStr;
    const char* hexChars = "0123456789ABCDEF";
    for (DWORD i = 0; i < length; ++i)
    {
        hexStr += hexChars[(bytes[i] >> 4) & 0x0F];
        hexStr += hexChars[bytes[i] & 0x0F];
        hexStr += ' ';
    }
    return hexStr;
}

int main()
{
    // 注意:Chrome的加密密钥通常是Base64编码后存于Local State文件,需先解码为二进制
    // 此处替换为实际的二进制加密密钥数据
    std::vector<BYTE> encryptedKey = {/* 填充实际二进制加密密钥 */};

    DATA_BLOB DataBytes;
    DataBytes.pbData = encryptedKey.data();
    DataBytes.cbData = encryptedKey.size();

    DATA_BLOB output = { nullptr, 0 };

    // 先判断函数返回值
    if (!CryptUnprotectData(&DataBytes, NULL, NULL, NULL, NULL, 0, &output))
    {
        cout << "解密失败:" << GetLastErrorAsString() << endl;
        return 1;
    }

    // 用十六进制输出解密后的密钥(二进制数据不能直接cout)
    cout << "解密后的AES密钥(十六进制):" << endl;
    cout << BytesToHexString(output.pbData, output.cbData) << endl;

    // 释放内存
    if (output.pbData)
    {
        LocalFree(output.pbData);
    }

    return 0;
}

额外说明

  • Chrome的加密密钥存储在Local State文件中,是Base64编码字符串,你需要先将其解码为二进制数据,再传入CryptUnprotectData,不能直接把Base64字符串当作输入。
  • 确保程序以当前用户权限运行,CryptUnprotectData需要匹配的用户上下文才能解密Chrome的密钥。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 12:30:44