QQ数据库解密与SQLCipher密钥提取全平台指南:5步跑通并解密聊天数据库
【免费下载链接】qq-win-db-key 全平台 QQ 聊天数据库解密 项目地址: https://gitcode.com/gh_mirrors/qq/qq-win-db-key
这个仓库 qq-win-db-key 专门解决QQ数据库解密中最核心的一步——SQLCipher密钥提取:在 Windows(旧版PCQQ、新版NTQQ)、Linux、macOS、iOS、Android 五个平台上,从 QQ 进程内存里直接截获数据库密钥,之后用 SQLCipher 打开聊天数据库。适合想在自己设备上找回、迁移或分析聊天库的开发者。仓库里的脚本都是参考实现,不同 QQ 版本可能跑不通,动手前请通读一遍代码并备份数据。
最快跑通:Windows 上 5 步拿到密钥
主线选旧版 PCQQ + Frida:依赖只有 Python、frida、psutil,不用学调试器,反馈最直接。
第 0 步,拿代码:
git clone https://gitcode.com/gh_mirrors/qq/qq-win-db-key
第 1 步,确认要 hook 的是哪个进程。 任务管理器里可能有多个 QQ.exe,脚本 hook 的是命令行参数带 /hosthwnd= 的那个子进程,用 psutil 这样筛:
for pid in psutil.pids():
p = psutil.Process(pid)
if p.name() == "QQ.exe" and len(p.cmdline()) > 1:
QQ_PID = pid
break
第 2 步,定位目标函数。 hook 对象是 KernelUtil.dll 里给数据库上锁的 sqlite3_key 类函数。QQ 没把它导出为符号,所以脚本用特征码在内存里扫:
const kernel_util = Module.load('KernelUtil.dll');
const key_function = single_function(
"55 8b ec 56 6b 75 10 11 83 7d 10 10 74 0d 68 17 02 00 00 e8");
⚠️ 注意:特征码和 QQ 版本强绑定。QQ 升级后这段字节大概率变掉,脚本会直接报 pattern NOT FOUND,需要对新二进制重新提取。
第 3 步,挂 hook 等命中。 函数签名是 sqlite3_key(db, zDbName, pKey, nKey),命中时读出第 3、4 个参数就是密钥:
Interceptor.attach(key_function, {
onEnter: function (args) {
var dbName = funcName(args[0], NULL).readUtf8String();
if (dbName.toLowerCase().endsWith("msg3.0.db")) {
console.log("nKey: " + args[2].toInt32());
console.log("*pkey: " + buf2hex(args[1].readByteArray(args[2].toInt32())));
}
}
});
一个账号会开一堆 .db,全都走这个函数,所以必须按库名过滤。聊天记录主库是 Msg3.0.db,脚本只放行它。
第 4 步,读结果。 密钥以十六进制字节序列打印,是 16 字节的 ASCII 串,形如 abcd1234.. 加几个特殊符号。
第 5 步,验证。 带着密钥打开数据库能列出表,密钥就是对的(下一节)。
完整脚本在 scripts/windows/pcqq/pcqq_get_key.py,直接 python pcqq_get_key.py 即可,注入成功后保持终端窗口不关,回 QQ 里随便切个会话触发一次数据库读写。
其余平台和主线的差异
五个平台走的是同一条路:找模块 → 静态算出函数偏移 → 下断点或挂 hook → 命中时从参数里读密钥。差别只在工具链和环境门槛:
| 平台 | 目标模块 | 函数定位方式 | 读密钥方式 | 环境门槛 | 脚本位置 |
|---|---|---|---|---|---|
| Windows PCQQ | KernelUtil.dll | Frida 特征码扫描 | Frida hook 读参数 | Python + frida | scripts/windows/pcqq/ |
| Windows NTQQ | wrapper.node | 纯 PowerShell 解析 PE:先找 .rdata 里 nt_sqlite3_key_v2: db=%p zDb=%s 字符串,再找引用它的 LEA 指令,经异常目录反推函数入口 | 脚本自带 Debug API 启动 QQ,写 0xCC 软断点,命中后从 R8(x64 第三参数)读 16 字符密钥 | 无额外依赖,PS 5.0+ | scripts/windows/ntqq/ |
| Linux | /opt/QQ/resources/app/wrapper.node | readelf -lW 算 .rodata 段映射 + strings -t d 找串 + objdump 找引用 | GDB 脚本内嵌:断 dlopen 等模块加载,命中循环等 nKey==16 再读寄存器 | root + gdb | scripts/linux/ |
| macOS(Apple Silicon) | wrapper.node 的 arm64 切片 | 纯 Python 解析 fat binary,靠诊断串定位并回溯函数入口,无需关 SIP | lldb 断点回调读 x2/x3(AAPCS64 的第三、四参数) | Xcode Command Line Tools | scripts/macos/arm-nosip/ |
| iOS | QQ 主二进制 | 硬编码偏移(0xDA1BFB4 对应 v9.0.1.620),另靠 sqlite3 结构体偏移链反查库名 | frida hook,按数据库文件名过滤 | 越狱或 TrollStore + frida-server | scripts/ios/ |
| Android | libkernel.so | Frida 扫 ARM64 特征码(码里带 ?? 通配字节) | frida hook,args[2]/args[3] 即 pKey/nKey | root、禁 SELinux、关 Magisk Hide/Shamiko | scripts/android/ |
几点实操判断:
- Windows NTQQ 是最省事的路,不装 Frida 也能跑:
powershell -ExecutionPolicy Bypass -File scripts/windows/ntqq/windows_ntqq_get_key.ps1,脚本自己从注册表找 QQ 安装目录、以调试器方式拉起 QQ,你只管正常登录。拿到密钥后脚本会直接结束 QQ 进程,属正常行为;加-NoDebugForKey则只做静态分析不下断点。 - macOS 数据库在
~/Library/Application Support/QQ/nt_qq_<hash>/nt_db/nt_msg.db,Linux 在~/.config/QQ下,脚本输出里会直接给路径。 - Android 有第二条路:不注入,改用系统备份功能备份 com.tencent.mobileqq,再用
scripts/android/android_get_backup_key.py从备份里提密钥,风险更低。更保险的是 PCQQ 自带的"导出消息记录(mht)",能用官方导出就别上注入。
密钥到手之后
1024 字节文件头怎么去掉
NTQQ 的 nt_msg.db 头部多了一段 1024 字节的自定义头,SQLCipher 认不出,直接开会报错,先切掉:
tail -c +1025 nt_msg.db > nt_msg.clean.db
旧版 PCQQ 的 Msg3.0.db 没有这段头,不用切。拿不准就查前 1024 字节是否为合法 SQLCipher 页面,或两种都试一遍。
SQLCipher PRAGMA 参数怎么配
QQ 用的参数全是非默认值,按 SQLCipher 默认值解密必挂。逐项对照:
| 参数 | 值 | 说明 |
|---|---|---|
| cipher_page_size | 4096 | 页大小 |
| kdf_iter | 4000 | 远低于默认 256000,写错直接解不开 |
| cipher_hmac_algorithm | HMAC_SHA1 | 部分版本见过 SHA512,先按 SHA1 |
| cipher_default_kdf_algorithm | PBKDF2_HMAC_SHA512 | KDF 算法 |
sqlcipher nt_msg.clean.db << 'EOF'
PRAGMA key = '你的密钥';
PRAGMA cipher_page_size = 4096;
PRAGMA kdf_iter = 4000;
PRAGMA cipher_hmac_algorithm = HMAC_SHA1;
PRAGMA cipher_default_kdf_algorithm = PBKDF2_HMAC_SHA512;
.tables
EOF
能列出表即密钥正确。报 file is not a database 时,按顺序查:key 是否写在所有 PRAGMA 之前、文件头切没切、kdf_iter 是不是 4000。
单库与批量解密
单个库要留一份明文副本,做法是打开加密库后 ATTACH 一个空 key 的新库,逐表拷贝:
ATTACH DATABASE 'nt_msg_plain.db' AS plain;
CREATE TABLE plain.msg AS SELECT * FROM main.msg; -- 每张表一行
批量处理就套一层循环,对目录下每个 .db 重复上面动作即可;更省事的是直接用仓库里的现成脚本:scripts/windows/pcqq/pcqq_dump.py 在注入进程内调用 QQ 自己的 sqlite3 接口,新开一个明文库、设 PRAGMA synchronous=ON 后逐表落盘,避免把大文件拖进内存。
校验结果别只信 .tables:对主消息表 SELECT COUNT(*) 看行数是否合理,再抽查几条消息内容。行数正常但内容乱码,说明 KDF 参数还是不对;能读但表缺失,多半是只解了部分库。
常见坑:现象、原因与处理
| 现象 | 原因 | 处理 |
|---|---|---|
pattern NOT FOUND | QQ 版本更新,特征码/偏移已变 | 对新二进制重新提取特征码或偏移 |
pattern FOUND MULTI | 特征码太短,命中多处 | 加长特征码,或结合上下文约束 |
脚本报 QQ not launched. exit. | 没找到 cmdline 带参数的 QQ.exe 子进程 | 先登录 QQ 再跑,用任务管理器确认进程 |
| hook 有输出但拿不到想要的密钥 | 同会话开了多个库,命中了别的库 | 核对 dbName 输出,调整库名过滤条件 |
file is not a database | NTQQ 的 1024 字节头没切 | tail -c +1025 处理后重试 |
| 解开了但数据损坏 | KDF/HMAC 参数不匹配 | 逐项核对 4000 / HMAC_SHA1 组合 |
| Android 注入失败 | SELinux 或 Magisk Hide、Shamiko 拦截 | 先禁 SELinux、关隐藏规则再注入 |
| iOS 断点打偏 | 偏移 0xDA1BFB4 只对应 v9.0.1.620 | 反汇编自己的版本重新取偏移 |
合规提醒与延伸学习
以上技术仅限恢复、迁移自己设备、自己账号上的聊天数据等合法场景,不得用于获取他人数据。⚠️ 仓库明确警告:注入类脚本可能破坏数据库或触发风控,优先用官方导出功能,在虚拟机或备用账号上实验。想深入的话,从 SQLCipher 官方文档理解 KDF 与 HMAC 参数,从 Frida 文档吃透 Interceptor 和模式扫描,再对照本仓库各平台脚本的源码和实际调试输出读一遍,比任何教程都直接。
【免费下载链接】qq-win-db-key 全平台 QQ 聊天数据库解密 项目地址: https://gitcode.com/gh_mirrors/qq/qq-win-db-key
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



