解密安卓NTQQ的数据库

虽然电脑上还是旧版的QQ,但手机上早已更新到了新版(NT)。这次来研究一下如何解密NTQQ的数据库。虽然电脑版的NTQQ数据库格式跟安卓的相同,但获取key这一部分只适用于安卓版本。

首先,手机需要有root权限,这样才能访问/data/data目录。进入/data/data/com.tencent.mobileqq,将databases和files/uid这两个文件夹拷到电脑上,接下来的操作会在电脑上(Windows)进行。

获取数据库文件

在uid目录下,可以看到文件名格式为“QQ号###uid”的文件,例如123456789###u_xxxxxxxx。得到这个uid之后,对它进行md5,得到一串hash,此处记为uid hash。

将uid hash末尾加上“nt_kernel”后,再次进行md5,得到另一串hash,将这串hash前面加上“nt_qq_”,在databases/nt_db目录下可以找到对应的路径,这就是QQ号对应的数据库路径了。

hash代码如下:

def get_qq_uid_hash(nt_uid):
    return md5(nt_uid.encode('utf-8')).hexdigest()

def get_qq_path_hash(qq_uid_hash):
    return md5((qq_uid_hash+'nt_kernel').encode('utf-8')).hexdigest()

获取key

数据库目录下有多个数据库文件,我尝试了其中几个文件,解密方式应该都是一样的。
用winhex打开数据库文件,可以看到如下内容:

其中,第一个红框内的字符串记为rand。将前面得到的uid hash后面加上这个rand,再进行md5,就得到key了:

def get_key(qq_uid_hash, rand):
    return md5((qq_uid_hash+rand).encode('utf-8')).hexdigest()

解密

先去除掉文件的前1024个字节,这样才能被正确读取:

import shutil

with open('nt_msg.db', 'rb') as f_in:
    f_in.seek(1024)
    with open('nt_msg_2.db', 'wb') as f_out:
        shutil.copyfileobj(f_in, f_out)

解密需要使用sqlcipher,windows下可以从这里下载已编译好的版本:https://github.com/QQBackup/sqlcipher-github-actions/releases
运行sqlcipher命令行:

.\sqlcipher-x64.exe .\nt_msg_2.db

进入sqlcipher环境后,依次输入如下命令:

PRAGMA key = 'key';
PRAGMA cipher_page_size = 4096;
PRAGMA kdf_iter = 4000;
PRAGMA cipher_hmac_algorithm = HMAC_SHA1;
PRAGMA cipher_default_kdf_algorithm = PBKDF2_HMAC_SHA512;
PRAGMA cipher = 'aes-256-cbc';

首先,第一行的key,就是前面获取到的key。
第四行的算法,根据图1中的第2个红框进行填写,此处就是HMAC_SHA1。
此时,应该可以正常读取数据库的内容了。

导出

尽管现在可以正常读取数据库了,但为了之后更方便地读取,我需要将它导出为未加密状态的正常数据库文件。在这一步,我遇到了不少麻烦。

一开始,我直接在sqlcipher中导出为新的数据库:

ATTACH DATABASE 'nt_msg_dec.db' AS plaintext KEY '';
SELECT sqlcipher_export('plaintext');
DETACH DATABASE plaintext;

出现报错:
Runtime error: database disk image is malformed

于是,根据这个issue,我先在sqlcipher中导出sql文件:

.output nt_msg.sql
.dump

安装MSYS2,进入UCRT64终端,安装sqlite3:

pacman -S mingw-w64-ucrt-x86_64-sqlite3

对之前的sql进行一些处理,再导入sqlite3:

cat nt_msg.sql | sed -e 's|^ROLLBACK;\( -- due to errors\)*$|COMMIT;|g' > nt_msg_2.sql
sqlite3 nt_msg_dec.db < nt_msg_2.sql

又出现报错:
Parse error near line xxx: unrecognized token: xxx

我猜测,应该是因为里面某些字段包含特殊字符(例如一些非主流的昵称)。目前没发现有什么办法能够在保留这些字符的情况下进行导入,因此只好去除掉这些字符:

sed -i 's/[[:cntrl:]]//g' nt_msg_2.sql

再次导入sqlite3,这次正常了,能够创建出新的数据库文件了。就是不知道会不会有什么缺失。

下一步,我将基于数据库中的聊天记录,删除掉部分群聊的图片。

参考

1. https://docs.aaqwq.top/decrypt/NTQQ%20(Android).html
2. https://github.com/Mythologyli/qq-nt-db

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注