公司动态
QQ 聊天数据库解密深度解析:qq-win-db-key 全平台密钥提取原理与实战指南
QQ 聊天数据库解密深度解析qq-win-db-key 全平台密钥提取原理与实战指南【免费下载链接】qq-win-db-key全平台 QQ 聊天数据库解密项目地址: https://gitcode.com/gh_mirrors/qq/qq-win-db-keyqq-win-db-key 是一个面向全平台 QQ 聊天数据库解密的开源工具集其核心价值在于回答一个难题如何安全地拿到 SQLCipher 加密数据库的解密密钥完成 QQ 聊天记录的本地备份与迁移。本文将从技术原理、分平台实战、进阶优化到避坑排查带您完整掌握这套跨平台密钥提取方案。一、痛点引入当你的聊天记录锁在了数据库里想象一个常见的场景你准备换电脑想把用了五年的 QQ 聊天记录完整迁移到新机器上。你打开 QQ 的「导出消息记录」功能却发现导出的格式在第三方工具里根本读不出完整上下文你尝试直接复制本地数据文件夹拷过去之后却提示数据损坏无法读取。问题出在哪关键就在于 QQ NT 版本把聊天记录存进了SQLCipher 加密的 SQLite 数据库典型文件是nt_msg.db。数据库本身是标准 SQLite 结构但每一页数据都经过 AES 加密没有密钥即便你把文件完整拷贝出来看到的也只是一堆密文。更棘手的是这条加密链路有四个隐形关卡页面大小、KDF 迭代次数、HMAC 算法、KDF 算法任何一个参数对不上解密都会直接失败。手动试错几乎不可能因为密钥本身也是运行时动态生成的不落盘、不进配置文件。这正是 qq-win-db-key 存在的理由它通过逆向工程定位密钥在内存中的存在位置在不修改安装包、不注入持久化代码的前提下把密钥取出来。二、项目核心价值速览一句话概括qq-win-db-key 是一套覆盖五大操作系统的 QQ 数据库密钥提取脚本集它把定位加密函数 → 挂钩参数 → 还原密钥 → 解密数据库这条完整链路做成开箱即用的代码。以下是它的关键指标维度覆盖情况支持平台Android、iOS、Windows、macOS、Linux目标版本覆盖 QQ 8.9.x 系列NTQQ 内核及旧版 PCQQ注入方式Frida 动态注入 / Windows 调试器 / GDB / LLDB核心函数nt_sqlite3_key_v2SQLCipher 密钥接口脚本数量5 个平台目录、14 个脚本/工具文件安全取向优先不注入进程、不修改安装包的静态轻量方案值得注意的是这个项目定位不是纯小白一键工具而是面向具备逆向基础的开发者的参考实现——脚本会随 QQ 版本更新而失效使用者需要具备按版本调整 Hook 点、解析二进制的能力这正是本项目最有价值的地方它把怎么做完整示范出来了。三、技术原理拆解密钥到底藏在哪怎么取出来3.1 一切的起点nt_sqlite3_key_v2QQ 的数据库基于 SQLCipher 加密而 SQLCipher 在打开数据库时最终都会调用同一个关键接口int sqlite3_key_v2(sqlite3 *db, const char *zDb, const void *pKey, int nKey);在 QQ NT 的封装层里这个函数被包装成了nt_sqlite3_key_v2并附带了一条诊断日志字符串nt_sqlite3_key_v2: db%p zDb%s。核心在于这条字符串在编译后仍会保留在二进制文件的只读数据段.rdata/.rodata中而引用它的代码位置就是我们逆向的灯塔。3.2 定位函数的三板斧不同平台定位这个函数的方式略有差异但思路一致可以归纳为三步找字符串在二进制中搜索nt_sqlite3_key_v2: db%p zDb%s或nt_sqlite3_key_v2: no key等诊断字符串拿到它在文件中的偏移RVA。找引用在代码段中搜索对该字符串地址的引用指令——Windows x64 是 RIP 相对寻址的LEA指令ARM64 是ADD Xn, Xm, #imm12指令。回溯函数头从引用点向上回溯找到函数序言x64 的栈帧建立、ARM64 的SUB sp, sp, #imm即得到函数入口。Windows 版 PowerShell 脚本用异常目录反向确认函数边界macOS 的find_key_func.py则用两条诊断字符串同时出现且间距小于 4096 字节来交叉验证Android 和 PCQQ 脚本则直接使用Frida 的Memory.scanSync做特征码扫描把函数开头的机器码序列pattern一次性匹配出来。3.3 取密钥读寄存器就够了找到函数入口之后剩下的工作就交给调用约定。sqlite3_key_v2的四个参数在不同架构下映射如下参数含义Windows x64ARM64 (Android/macOS/iOS)db数据库句柄RCXX0zDb库名如mainRDXX1pKey密钥指针R8X2nKey密钥长度R9X3以 Windows 脚本为例它在目标函数入口写下一个0xCC软件断点当 QQ 登录触发数据库打开时断点命中脚本读取R8 寄存器指向的内存校验其是 16 字节的可见 ASCII 字符串后即为有效密钥。macOS 脚本同理读取 X2/X3Linux GDB 脚本则通过$rsizDb和$rdxnKey先确认调用是否符合预期再提取密钥。3.4 解密参数四个值一个都不能错拿到密钥只是第一步SQLCipher 解密还需要与加密时一致的参数。项目脚本与文档中反复出现的标准参数如下参数值说明cipher_page_size4096页面大小QQ 使用 4KBkdf_iter4000KDF 迭代次数cipher_hmac_algorithmHMAC_SHA1完整性校验算法cipher_default_kdf_algorithmPBKDF2_HMAC_SHA512密钥派生算法这一步至关重要参数不匹配时PRAGMA key之后执行.tables只会得到database file is encrypted或空结果而不会明确提示你哪个参数错了。3.5 整体架构流程图QQ 登录 → 打开 nt_msg.db → 调用 nt_sqlite3_key_v2(db, zDb, pKey, nKey) │ ┌─────────────────────────────┘ ▼ 定位函数字符串→引用→函数头或特征码扫描 ▼ 挂钩/断点拦截Frida / Debugger / GDB / LLDB ▼ 读取寄存器参数 → 还原密钥ASCII 或 HEX ▼ sqlcipher 打开数据库 PRAGMA 设置加密参数 → .tables 验证 → 导出明文库四、快速上手指南从克隆到跑通最小示例4.1 环境准备先克隆仓库git clone https://gitcode.com/gh_mirrors/qq/qq-win-db-key cd qq-win-db-key按平台准备依赖工具平台必备工具AndroidPython 3.8、pip install frida-tools、已 root 设备、frida-serverWindowsPowerShell 5.0或 Core 7.0无需额外依赖LinuxPython 3、GDB、readelf/strings/objdumpbinutilsmacOSXcode Command Line Tools自带 lldb无需禁用 SIPiOSFrida、越狱或开发者签名环境4.2 最小示例一Android 平台提取密钥# 1. 手机开启 frida-serverTermux 里可命名为 friendly sudo friendly # 2. 打开 QQ 并登录进入主界面 # 3. 运行脚本传入 QQ 版本号 python scripts/android/android_get_key.py 8.9.76脚本会自动定位libkernel.so中nt_sqlite3_key_v2的特征码并注入 Hook。运行后请退出登录并重新登录一次因为密钥在登录流程中才会被传入。终端会打印如下关键输出¦- targetDB: 0x... ¦- *zDb: main ¦- *pkey: 32位可见密钥 ¦- *pkey-hex: 0x61, 0x62, ... ¦- nKey: 324.3 最小示例二Windows NTQQ 平台提取密钥# 直接运行脚本会自动检测已安装的 QQ 并定位 wrapper.node powershell -ExecutionPolicy Bypass -File scripts/windows/ntqq/windows_ntqq_get_key.ps1脚本执行静态分析后会自动拉起 QQ 并附加调试器此时只需在 QQ 窗口正常登录断点命中即打印密钥。如果你只想做静态分析不附加调试器加上参数即可.\windows_ntqq_get_key.ps1 -NoDebugForKey4.4 拿到密钥后统一的解密操作无论哪个平台取到的密钥解密流程一致以 macOS 脚本提示的步骤为例先去掉文件头 1024 字节tail -c 1025 nt_msg.db nt_msg.clean.db 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能列出表名说明解密链路全部打通随后可用.output和.dump导出明文数据或另存为新的明文数据库。五、真实场景实战两个典型完整链路5.1 场景一换机前的 Android 聊天记录完整备份痛点手机要恢复出厂设置聊天记录必须落地。操作链路在目标手机上打开 QQ 并登录进入主界面运行scripts/android/android_get_key.py按提示退出登录再重新登录触发密钥捕获记录终端输出的密钥字符串从/data/data/com.tencent.mobileqq/下取出数据库可通过系统备份或 root 文件管理器例如databases/nt_db/nt_msg.db用 4.4 节的 sqlcipher 流程解密得到明文数据库文件将明文库与密钥一起归档保存完成备份。关键提示建议同时保存密钥的 HEX 形式脚本会一并打印因为个别版本密钥可能包含不可见字符HEX 形式可避免复制时丢字节。5.2 场景二macOS 上不动 SIP 的静默提取macOS 的逆向往往受 SIP系统完整性保护限制而scripts/macos/arm-nosip/目录提供了无需关闭 SIP的方案这也是本仓库的一大亮点。操作链路两个终端# 终端 A启动 lldb 并附加 QQ等待注入 lldb -n QQ -w --one-line command script import /path/to/qq_key_extractor.py # 终端 B等终端 A 显示 Waiting for process QQ 后启动 QQ open /Applications/QQ.app回到终端 A依次执行(lldb) process continue ← 放行等 QQ 出现登录界面 Ctrl-C ← 暂停 (lldb) qq-setbp ← 自动计算 slide 并设置断点 (lldb) c ← 继续 [在 QQ 点击登录] ← 密钥自动打印QQ 正常运行脚本会打印数据库路径和解密命令模板照抄即可。find_key_func.py还支持单独对wrapper.node做静态定位输出函数虚拟地址供手动下断点适合想深度研究的朋友。六、进阶技巧与性能调优6.1 批量处理多个账号如果您需要为多台设备或多个 QQ 号提取密钥可以把密钥获取与解密封装成批处理脚本。核心思路是把取密钥和解密解耦密钥统一落盘缓存解密流程复用import json from pathlib import Path KEY_CACHE Path(keys.json) def load_cache(): if KEY_CACHE.exists(): return json.loads(KEY_CACHE.read_text()) return {} def get_key(account, extractor): cache load_cache() if account in cache: # 缓存命中跳过重新提取 return cache[account] key extractor(account) # 调用平台脚本的提取逻辑 cache[account] key KEY_CACHE.write_text(json.dumps(cache, indent2)) return key缓存机制能显著减少重复注入带来的账号风控风险——同一账号反复登录退出容易被安全策略盯上。6.2 Linux 脚本的离线缓存优化scripts/linux/linux_qq_get_key.py本身就是一个优秀的优化范例它把objdump反汇编结果中算出的字符串引用偏移ref_off连同wrapper.node的SHA-256 哈希一起写入本地缓存文件。下次运行时如果文件哈希没变就直接读缓存跳过耗时的反汇编步骤。这个思路值得复用任何静态分析结果都可以用文件哈希 结果缓存的方式做增量加速。6.3 并行解密与内存控制解密大体积数据库动辄数 GB时分块处理用sqlcipher的PRAGMA cache_size调小页缓存或分表.dump避免一次性载入全部数据导致 OOM增量迁移只解密增量时段的数据用WHERE条件按时间字段筛选后再导出并行多账号场景下不同账号的数据库相互独立可以并行解密但同一账号务必串行避免并发登录触发风控。6.4 错误处理与日志建议给所有脚本调用加统一日志与重试机制。密钥提取失败多发生在进程注入时机不对最简单有效的重试策略是失败后杀掉 QQ 进程、彻底重启、重新注入。把每次提取的时间、版本、输出摘要写入日志能大幅降低排查成本。七、避坑指南与常见问题7.1 密钥提取失败脚本无输出可能原因排查与解决QQ 版本与脚本不匹配确认版本号Android 脚本支持 8.9.58 / 8.9.63 / 8.9.68 / 8.9.76传参如python android_get_key.py 8.9.76注入时机不对先打开 QQ 并登录进入主界面再运行脚本然后退出登录重新登录触发密钥调用Frida 服务未运行检查frida-ps -UAndroid 需确认 frida-server 已启动且与主机 frida 版本一致安全机制拦截Android 需关闭 Magisk Hide 与 Shamiko、禁用 SELinux避免使用 x86/x64 模拟器排查命令frida-ps -U # 确认设备连接与进程可见 adb shell su -c pidof com.tencent.mobileqq # 确认 QQ 进程存在7.2 密钥拿到了但.tables仍然解密失败可能原因排查与解决加密参数不匹配逐条核对cipher_page_size、kdf_iter、cipher_hmac_algorithm、cipher_default_kdf_algorithm数据库带文件头部分版本nt_msg.db前 1024 字节是明文头需先tail -c 1025去掉再解密密钥复制出错对比 HEX 形式输出确认没有缺失字节注意 Windows 控制台编码用 UTF-8数据库版本差异老库可能是 SQLCipher 3 参数如 HMAC_SHA1新库可能是 4.x用PRAGMA cipher_version;查看排查命令sqlcipher nt_msg.clean.db PRAGMA integrity_check; # 若输出 ok 但空表再检查上述四个加密参数7.3 跨平台结果不一致同一个账号在不同平台的密钥理论上一致但实际会出现差异原因通常是不同平台的 QQ 版本号不同内部加密实现有差异。解决方案是以目标数据库实际所在平台的脚本为准先在本机验证解密成功再统一归档密钥与参数。7.4 安全红线务必阅读⚠️ 本仓库 README 明确警告部分脚本可能破坏聊天记录或导致封号。请务必做到操作前先用 PCQQ 自带的「导出消息记录mht 格式」做一份保险备份对原始数据做完整备份系统备份或全盘备份优先在不常用设备或虚拟机中试验优先选择不注入进程、不修改安装包的方式例如 macOS 的静态分析路径本项目仅供学习交流禁止用于违反法律法规或《QQ 软件许可及服务协议》的行为。八、总结与展望回到开头的场景五年的聊天记录被锁在加密数据库里靠手工根本无解。而 qq-win-db-key 用一套清晰的思路解决了它——找字符串、找引用、回溯函数头、挂钩取参、按参数解密五大平台各有一套可运行的参考实现从 Frida 注入到 Windows 调试器从 GDB 到 LLDB几乎覆盖了主流动态调试技术的全部形态。它的价值不止于能用更在于示范每一个脚本都是一堂可运行的逆向工程课。如果你想深入建议沿着三条线继续学习掌握二进制格式PE 的节表与异常目录、Mach-O 的 fat header 与__text段、ELF 的 Program Header 与.rodata这是所有定位逻辑的地基理解调用约定x64 的 R8/R9 与 ARM64 的 X2/X3 传递参数是读寄存器取密钥的前提学会特征码更新QQ 每次更新函数签名与字符串偏移都可能变化find_key_func.py这类静态定位脚本正是为自适应新版本而生值得反复研读。技术永远在迭代QQ 的加密实现也会不断加固但只要掌握定位 → 挂钩 → 还原这套方法论任何加密都只是时间问题。最后送给每一位读者一句话数据是数字时代最珍贵的资产而掌握自己数据的钥匙才是真正的安全感。【免费下载链接】qq-win-db-key全平台 QQ 聊天数据库解密项目地址: https://gitcode.com/gh_mirrors/qq/qq-win-db-key创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考