Skip to content

NTQQ (Windows)

IDA分析

QQ NT Windows 数据库解密+图片/文件清理:本仓库使用 IDA debugger 完成了逆向分析到解密的全过程,并实现了图片与文件清理。

IDA下载(吾爱破解提供)

转载说明

原文发表于Myth's Blog,作者为Myth,根据 CC BY-SA 4.0 授权协议发布,内容经issues #50补充

部分图片来自GroupChatAnnualReport

QQ NT Windows 数据库解密+图片/文件清理

笔者测试时使用的 QQ 版本:9.9.3-17412

经验证的 QQ 版本:9.9.3-17749 9.9.12-26339

找到数据库 passphrase

  1. 解压IDA压缩包,双击打开 ida64.exe ,选择 new , 在弹出的资源管理器界面中定位到 QQNT 安装目录下的 ./versions/{version}/resources/app文件夹,其中 {version} 为 QQNT 的版本号。在右下角过滤器中选择全部文件,单击 wrapper.node 文件,并点击右下角的 "Open" 按钮。

wrapper.node文件路径说明

早期 Windows QQ_NT 版本 wrapper.node 文件位于 ./resources/app/versions/{version} 文件夹中

保持默认导入选项,点击 "OK" 按钮。如果有弹出让选择PDB文件相关提示框点击 "No"。等待文件加载完成。

分析时间较长,请耐心等待

分析完成后打开 Strings 视图(如果没有同时按 shift + F12 或按图片示例打开),CTRL+F搜索 nt_sqlite3_key_v2: db=%p zDb=%s 字符串, 双击 nt_sqlite3_key_v2: db=%p zDb=%s 一行,跳转到 IDA View-A 标签的对应行。

  1. 在 IDA View-A 标签中,单击 nt_sqlite3_key_v2 的名称 aNtSqlite3KeyV2,按快捷键 X 打开交叉引用窗口。双击第一条结果,转到引用位置。 或者右键此处点击Jump to xref to operand..
    JumpOpXref 后发现在

  2. 按下 F5 反编译此函数, 如果有弹出窗口点击 "Yes"。等待反编译完成。单击引用语句的左侧蓝色圆点添加断点。

  3. 退出 QQ 并重新打开,但不要登录。在上端工具栏右侧选择Local Windows debugger 在 IDA 中点击顶部导航栏 "Debugger" 中的 "Attach to process..." 菜单项, 从列表最后开始找到第一个 QQ.exe 进程,双击打开。

如果等待附加进程时QQ已经无响应了(卡在登录界面无法点击),等待加载完成后按快捷键 F9 继续运行。

点击登录 QQ,此时成功在断点处停下,打开一个 Locals 视图(Debugger->Debugger windows->Locals)查看参数的值

  1. 在 a3 对应的位置右键jump to,直到看到如下图所示的 16 位字符串。#8xxxxxxxxxxx@uJ 即为我们需要的 passphrase (不一定是这个格式,但总字符数是一样的)

打开数据库

请参考 NTQQ 解密数据库

使用 frida hook

1. 定位 nt_sqlite3_key_v2:

此处采用 IDA 演示,您可以替换成您喜欢的任何反编译器

在 Strings 窗口中搜索 nt_sqlite3_key_v2,得到多个结果

定位到字符串 nt_sqlite3_key_v2: db=%p zDb=%s

在 IDA View 中定位到此字符串

在此字符串上按x,或右键选此字符串并选择Jump to xref查看引用,进入引用的函数

通过字符串找到目标函数

记录函数地址,切换到 Hex View,复制从函数地址开始的一段字节序列,作为特征 Hex

QQ 9.9.1.15043 为

plain
48 89 5C 24 08 48 89 6C  24 10 48 89 74 24 18 57
48 83 EC 20 41 8B F9 49  8B F0 4C 8B CA 4C 8B C1
48 8B EA 48 8B D9 48 8D  15 33 05 A0 00 B9 08 00

2. Hook 并找到 Key

根据 https://www.zetetic.net/sqlcipher/sqlcipher-api/#sqlite3_key 指出

sqlite3_key_v2 的签名为

c
int sqlite3_key_v2(
  sqlite3 *db,                   /* Database to be keyed */
  const char *zDbName,           /* Name of the database */
  const void *pKey, int nKey     /* The key */
);

其中对我们有用的是 pKeynKey

作者本人采用 frida hook

根据 repo 提供的脚本略加修改,很容易得到我们需要的 pKeynKey

(如果你对如何修改有疑问,可以使用 msojocs/nt-hook 中给出的完整脚本。注意,编译此脚本需要你的系统安装有 Node.js 环境,但编译得到的.js文件可以直接运行。注意,本仓库最新版本可能不能在 Windows 平台下直接使用,请自行根据 commit 信息找到可用版本(比如超链接给出的版本),或自行更改相关代码。)

PS:有概率你会得到的一个长度为 20 的 key,但那不是我们想要的,可以挂上一个动态调试器来观察 key 对应的具体数据库

3. 打开数据库

请参考 NTQQ 解密数据库