全平台QQ聊天数据库解密实战:从一堆乱码到可读的聊天记录
【免费下载链接】qq-win-db-key全平台 QQ 聊天数据库解密项目地址: https://gitcode.com/gh_mirrors/qq/qq-win-db-key
你有没有遇到过这样的场景:换了新手机、想清理空间,或者纯粹想把某段重要的聊天记录永久留档,于是兴冲冲地把 QQ 的数据库文件拷了出来——结果打开一看,全是密密麻麻的乱码,别说聊天内容,连个完整的汉字都找不到。
这不是文件损坏,而是 QQ 用 SQLCipher 加密了你的聊天数据库。本文要介绍的 qq-win-db-key 项目,就是一套横跨 Android、iOS、Windows、macOS、Linux 五大平台的密钥提取方案,它的目标只有一个:帮你拿到那把"钥匙",把乱码重新变回能读的聊天记录。
接下来,我会带你从原理一路走到实战,用一套完整的故事线,把这件事讲透。
一、先搞懂谜题:加密数据库到底是个什么"锁"
先别急着敲命令,我们花三分钟理解一下你面对的是什么。
你可以把 QQ 的聊天数据库想象成一个保险箱。保险箱本身(.db文件)里的东西——你的好友、群聊、每一条消息——都是明文存放的,但被锁在了箱子里。SQLCipher 干的事就是"写入前先加锁、读取前先开锁":每次往数据库写数据,它先用密钥加密再落盘;每次读数据,先解密再返回给 QQ 程序。
那么问题来了:钥匙(密钥)藏在哪里?
答案很反直觉——钥匙就藏在 QQ 自己手里。QQ 程序运行时,必然要在某个时刻把密钥交给 SQLCipher 的解锁函数,否则它自己也读不了自己的数据库。而这个"解锁函数",就是 SQLCipher 的公开接口sqlite3_key_v2(QQ NT 版本里对应nt_sqlite3_key_v2)。
所以整个项目的核心思路只有一句话:不碰保险箱,改盯拿钥匙的那只手。
你不需要破解密码学算法,AES、SHA512 这些加密算法本身是牢不可破的;你只需要在 QQ 程序"掏钥匙开门"的那一瞬间,把钥匙的样子拍下来。这就是动态调试(Hook / 断点)的价值所在。
另外,拿到钥匙还不够,你还得知道保险箱的"开门参数":SQLCipher 加密时用了多大的页面(page size)、密钥派生迭代多少次(KDF iterations)、用哪个哈希算法。这些参数错了,钥匙对了也开不了门。QQ 常见配置是:
| 参数 | 取值 |
|---|---|
| 页面大小 Page size | 4096 字节 |
| 密钥迭代 KDF iterations | 4000(部分新版本为 64000) |
| KDF 算法 | PBKDF2-HMAC-SHA512 |
| HMAC 算法 | HMAC-SHA512 |
记住这张表,解密阶段会用到。现在,谜题解开了,我们进入正题。
二、准备工作:把"工具箱"备齐再动手
在开始之前,你需要按自己所在的平台准备环境。项目代码获取方式很简单:
git clone https://gitcode.com/gh_mirrors/qq/qq-win-db-key cd qq-win-db-key项目采用scripts/目录按平台分模块组织,你一眼就能找到自己需要的脚本:
scripts/android/:Android 平台,基于 Frida 的注入与密钥提取scripts/ios/:iOS 平台,Frida 脚本scripts/linux/:Linux NTQQ,基于 GDB 的密钥提取scripts/macos/arm-nosip/:macOS ARM 芯片方案,无需关闭 SIPscripts/windows/ntqq/:Windows NTQQ 新版本scripts/windows/pcqq/:Windows 旧版 PCQQ 工具链
通用的依赖主要有三样:Python 3.8+、Frida(动态调试)、SQLCipher 命令行工具(最后解密用)。各平台的额外依赖,我们放到对应实战环节里说。
这里给你一个很重要的提醒:动手前先做备份。后面每一步操作都建立在"数据可恢复"的前提上,这是整个流程的安全底线。
三、手把手实战:按你的平台走完"取钥匙"全程
密钥提取的核心逻辑各平台一致,但操作细节差别不小。我们按三个最常见的平台逐个走一遍,你在哪个平台就用哪段。
1️⃣ Android 平台:用 Frida 拍下"掏钥匙"瞬间
Android 是目前资料最全、成功率最高的平台。你需要一台已 root 的手机(或已 root 的安卓设备),并在设备上运行与手机架构匹配的frida-server。
先在电脑上装好 Frida 工具:
pip install frida-tools adb devices # 确认设备已连接并被识别然后做三件"减负"操作:关闭 Magisk Hide 与 Shamiko(否则会隐藏进程,Frida 挂不上去)、临时禁用 SELinux、不要用 x86 架构的安卓模拟器(脚本只保证 ARM 环境)。
接着打开 QQ,正常登录并进入主界面,保持运行。然后在本机运行提取脚本:
python scripts/android/android_get_key.py 8.9.58脚本会自动找到 QQ 进程并注入 Frida 脚本,用一串特征字节(pattern)在libkernel.so里定位nt_sqlite3_key_v2函数并挂钩。挂上之后,脚本会提示你"退出登录并重新登录"——因为只有在登录那一刻,QQ 才会去"掏钥匙开保险箱",我们的钩子才能截获它。
预期输出大致长这样:
Attach key_v2_function addr: 0x... ¦- targetDB: ... ¦- *zDb: nt_msg.db ¦- *pkey: abcd1234.,.,ABCD1234567812345678 ¦- nKey: 32*pkey后面那一串,就是你要的密钥,先抄下来或存到本地文件。
这一步如果没成功,通常是这三种情况:一是 QQ 版本不在脚本支持的列表里(android_get_key.py内置了 8.9.58 / 8.9.63 / 8.9.68 / 8.9.76 等版本的特征码,版本不符就需要改 pattern);二是frida-server版本与电脑端 Frida 不匹配;三是 Magisk Hide 没关干净,注入被拦了。
如果你的需求是 Android 备份文件(.ab格式)里的数据库,项目还提供了android_get_backup_key.py,走的是另一条提取路径,用法类似,只是只支持特定版本,运行时把版本号作为参数传入即可。
2️⃣ Linux 平台:用 GDB 在断点处"截胡"
Linux 上的 NTQQ 把核心逻辑打包在/opt/QQ/resources/app/wrapper.node这个原生模块里。linux_qq_get_key.py的思路非常优雅:不注入、不 Hook,纯静态分析加 GDB 断点。
脚本会自动完成三件事:
- 用
readelf解析wrapper.node的程序头,定位.rodata段,再在.rodata里搜索nt_sqlite3_key_v2: db=%p zDb=%s这个日志字符串,得到它的文件偏移; - 用
objdump反汇编.text段,找出所有引用这个字符串的指令地址(ref_off),这些地址指向的代码块就是"掏钥匙"的调用点; - 把候选地址转成断点,用 GDB 附加到 QQ 进程,等
nt_sqlite3_key_v2被调用时停在断点上,从寄存器里读出密钥。
运行方式:
sudo python scripts/linux/linux_qq_get_key.py脚本需要 root 权限(GDB 附加进程需要),过程中会打印出定位到的rodata_info、字符串偏移、引用地址,最后在断点处读出zDb(数据库名)和密钥。
这一步如果没成功,通常是:wrapper.node路径不对(新版 QQ 安装路径可能有变化,需要改脚本开头的WRAPPER_NODE_PATH常量),或者 QQ 版本更新后nt_sqlite3_key_v2字符串格式变了导致 pattern 匹配失败。另外注意,脚本会把定位结果缓存到ref_off_cache文件,如果换了 QQ 版本记得删掉缓存让它重新计算。
3️⃣ Windows 平台:让 PowerShell 自己当一次"调试器"
Windows NTQQ 同样在wrapper.node里藏着密钥逻辑,但windows_ntqq_get_key.ps1的做法更"重量级":它直接内嵌了一个完整的调试器实现,用 Win32 API(CreateProcessW+WaitForDebugEvent)启动 QQ、等待wrapper.node加载、下软件断点、在断点命中时读取寄存器里的密钥。
这个脚本最贴心的地方是自动检测:它会从注册表里找到 QQ 的安装目录和版本号,不需要你手动填路径。直接跑:
.\scripts\windows\ntqq\windows_ntqq_get_key.ps1脚本启动后会自动拉起 QQ,你在弹出的 QQ 窗口里正常登录。当登录触发数据库解密时,断点命中,脚本会从R8寄存器(x64 调用约定里第 4 个参数)读出密钥并打印:
找到密钥: xxxxxxxxxxxxxxxx这一步如果没成功,通常是:QQ 是多版本共存导致脚本识别错了wrapper.node路径(可以用-WrapperNodePath参数手动指定);或者 QQ 更新后函数 RVA 变化。另外,如果你只想做静态分析不想真的拉起 QQ 调试,可以加-NoDebugForKey参数,脚本只解析不调试。
4️⃣ 拿到钥匙之后:解锁数据库(所有平台通用)
密钥到手,最后一步就是开锁。用 SQLCipher 命令行工具打开加密的数据库:
sqlcipher encrypted.db在 SQLCipher 交互界面里,依次输入(注意 SQLCipher 4.x 的语法):
PRAGMA key = '你提取到的密钥'; PRAGMA cipher_page_size = 4096; PRAGMA kdf_iter = 4000; PRAGMA cipher_hmac_algorithm = HMAC_SHA512; PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA512; -- 先验证一把:能查到表就说明参数对了 .tables -- 确认无误后导出为明文库 .save decrypted.db如果你的 SQLCipher 是 3.x,cipher_hmac_algorithm和cipher_kdf_algorithm这两行要换成PRAGMA cipher_use_hmac = OFF;,并注意kdf_iter的差异(新版 QQ 有些库用的是 64000 而不是 4000,都试一下即可,试错成本很低)。
这一步如果没成功,通常是:密钥里带了特殊字符导致 PRAGMA 解析失败(用单引号包住、必要时转义);或者是kdf_iter参数不匹配——这是最隐蔽的坑,报错信息还不明显,建议两个值都试一次。
到这一步,你已经完成了"取钥匙 → 开锁 → 导出明文"的完整链路。你的聊天记录终于不再是一堆乱码了。
四、高手进阶:把单次操作变成可复用流程
如果你只是偶尔备份一次,上面就够了。但如果你要管理多个账号、或者经常备份,下面这些进阶玩法能省你不少事。
方案一:多账号批量处理。每个 QQ 账号的密钥不同,但提取流程完全一样。你可以写个简单脚本把"提取密钥 → 拼接解密参数 → 导出明文库"串成一条流水线,循环处理账号列表,失败的重试、成功的记日志。注意每个账号的密钥要分开存储,别混在一起。
方案二:按场景选平台。不同平台的成功率和折腾成本差别很大,我给你一个客观的参考:
| 平台 | 脚本 | 依赖 | 难度 |
|---|---|---|---|
| Android | android_get_key.py | root + frida-server | 中 |
| Linux | linux_qq_get_key.py | GDB + root | 中低 |
| Windows NTQQ | windows_ntqq_get_key.ps1 | PowerShell 5.0+ | 低 |
| Windows 旧版 PCQQ | pcqq_get_key.py | Frida + 旧版 QQ | 中 |
| macOS ARM | qq_key_extractor.py | 无 SIP 限制要求 | 中 |
| iOS | ios_get_key.js | 越狱环境 + Frida | 高 |
方案三:旧版 PCQQ 的特殊玩法(高风险,谨慎)。scripts/windows/pcqq/里除了常规的pcqq_get_key.py(HookKernelUtil.dll的sqlite3_key函数,密钥以 hex 形式输出),还有两个名字里就写着DANGER的工具:pcqq_DANGER_rekey.py和pcqq_rekey_to_none.cpp,作用是直接把数据库的密钥改写成"空",让数据库变成无加密状态。听起来很方便,但"重加密"本质上是改写数据库文件头部的密钥派生信息,一旦中途断电、版本不匹配或参数算错,整个库就废了。非必要不碰,碰之前务必全盘备份。
五、风险与边界:动手前,请先读完这一段
这个项目在 README 里把丑话说在了前头,我觉得这是它最值得尊敬的地方。这里替它把话说透:
数据风险。提取密钥本身是只读操作,风险很低;但解密后的写入、重加密(尤其是 PCQQ 的 rekey 工具)都是写操作,任何一步出错都可能导致聊天记录永久丢失。铁律只有一条:操作前用官方"导出消息记录"功能或系统备份工具先留一份底。
账号风险。注入进程、挂调试器这类操作,理论上可能被 QQ 的风控机制识别,极端情况下可能导致账号异常。建议优先在虚拟机、不常用设备或小号上验证流程,确认无误再碰主力账号。
合规风险。这类工具只应服务于"备份自己的聊天记录"这一目的。请务必遵守《QQ 软件许可及服务协议》以及你所在地的法律法规,不要用于获取他人数据、商业用途或任何法律取证场景。项目作者也明确声明:仅供学习交流,不承担任何因使用本工具产生的直接或间接责任。
兼容性边界。这不是一个"一次写好、永远能用"的项目。脚本依赖特定的 QQ 版本号、特征码、函数偏移,QQ 每次更新都可能让现有脚本失效,需要你按新版本重新定位特征。README 也明说了:本项目假设使用者具备一定的逆向、动态调试和脚本修改能力,它不是给纯小白的傻瓜式工具。
六、写在最后:技术是工具,数据属于你自己
回顾整条链路:从"文件全是乱码"的困惑,到理解 SQLCipher"写入前加锁、读取前开锁"的机制,再到用 Frida、GDB、调试器在 QQ"掏钥匙"的瞬间截获密钥,最后用匹配的加密参数解锁数据库——整个过程没有破解任何密码学算法,只是巧妙地利用了程序自身的行为。这种"不正面硬刚、而是从侧面观察"的思路,本身就是逆向工程最迷人的地方。
qq-win-db-key 的价值在于:它把这条思路沉淀成了 Android、iOS、Windows、macOS、Linux 五个平台都能落地的代码,让你不用从零开始读汇编、找偏移,而是站在前人的肩膀上完成自己的数据备份。
最后再叮嘱一句:工具无罪,用法有界。请把它用在"备份你自己的聊天记录"这件正当的事上,动手前备份、操作时谨慎、完成后清理临时文件。数据是你的,安全也是你的。
【免费下载链接】qq-win-db-key全平台 QQ 聊天数据库解密项目地址: https://gitcode.com/gh_mirrors/qq/qq-win-db-key
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考