使用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
相关产品推荐
相关产品推荐

