chrome本地cookie经dpapi加密,需用cryptunprotectdata解密encrypted_value(跳过前3字节版本头),转utf-16字符串;history明文可直查但须复制文件防锁。

Chrome本地Cookie文件被加密,直接读取会乱码
Chrome把Cookie存在SQLite数据库里(路径通常是%LOCALAPPDATA%GoogleChromeUser DataDefaultCookies),但里面encrypted_value字段是AES加密的,用SELECT * FROM cookies查出来全是二进制垃圾——不是没读到,是解不开。
关键点在于:Windows上Chrome用的是DPAPI加密,密钥绑定当前用户登录会话;macOS用Keychain;Linux基本明文(但新版也逐步加了加密)。所以跨平台硬读行不通,Windows下必须调用系统API解密。
- 别试图用
System.Security.Cryptography自己实现AES解密——密钥不固定,也不在文件里 - 别用第三方SQLite工具直接打开
Cookies文件后导出——encrypted_value列没法人工还原 - 如果Chrome正在运行,直接访问
Cookies文件会失败(数据库被锁),得先复制一份再操作
C#调用Windows DPAPI解密encrypted_value
Windows平台唯一靠谱路径:用CryptUnprotectData API解密encrypted_value字段。注意它只接受byte[]输入,且必须和Chrome写入时用的同个用户上下文(即不能用服务账户或不同Windows用户运行你的程序)。
示例核心逻辑:
里面有2个文件夹。其中这个文件名是:finishing,是我项目还没有请求后台的数据的模拟写法。请求后台数据之后,瀑布流的js有一点点变化,放在文件名是:finished。变化在于需要穿参数到后台,和填充的内容都用后台的数据填充。看自己项目需求来。由于chrome模拟器是不允许读取本地文件json的,所以如果你要进行测试,在hbuilder打开项目就可以看到效果啦,或者是火狐浏览器。
var blob = Marshal.AllocHGlobal(data.Length);
Marshal.Copy(data, 0, blob, data.Length);
try
{
if (CryptUnprotectData(blob, data.Length, out var decrypted))
return decrypted;
}
finally
{
Marshal.FreeHGlobal(blob);
}-
CryptUnprotectData返回true才代表解密成功;失败通常因为用户不匹配、Chrome正在运行导致密钥未加载、或数据已损坏 -
encrypted_value前3字节是0x01 0x00 0x00(版本头),解密前要跳过,否则解出来开头多三个乱码字节 - 解密后得到的是UTF-16小端字节数组,需用
Encoding.Unicode.GetString()转成字符串,不是UTF8
读取历史记录比Cookie简单,但要注意数据库锁
History文件(路径:%LOCALAPPDATA%GoogleChromeUser DataDefaultHistory)里的urls表基本是明文,没有加密字段。只要Chrome没在写入,就能直接查。
常用查询:
SELECT url, title, last_visit_time FROM urls ORDER BY last_visit_time DESC LIMIT 10
-
last_visit_time是Windows FILETIME格式(微秒级时间戳,从1601年1月1日起),需转换:DateTime.FromFileTimeUtc(value) - Chrome运行时访问
History文件大概率抛SQLiteException: database is locked,务必先复制文件再打开连接 - 别忽略
sqlite3.dll依赖——.NET 6+可用Microsoft.Data.Sqlite,但得确保运行时能找到原生库(尤其发布为单文件时)
权限、路径、运行时机三者缺一不可
即使代码全对,也会跪在这三处:
- 你的C#程序必须以目标用户身份运行(比如不能用管理员权限起进程去读另一个普通用户的
User Data目录) - 路径拼接别硬编码:
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)+"\Google\Chrome\User Data\Default",否则Win11/旧版路径可能不同 - Chrome关闭后仍可能有残留进程(
chrome.exe --type=crashpad之类),用tasklist /fi "imagename eq chrome.exe"确认清空再读,不然还是锁
真正麻烦的从来不是“怎么写代码”,而是让代码在正确的时间、正确的权限、正确的环境下,拿到那个没被锁住的、属于当前用户的文件。









