NTQQ聊天记录导出方法

近期尝试把积攒多年的QQ聊天记录进行蒸馏,但发现使用NT架构的新版QQ后无法直接导出聊天记录,在此简单记录一个可行的获取聊天记录方法。以下内容以小米HyperOS下的NTQQ 9.2.65为例

获取聊天记录数据库

导出Android QQ备份文件

使用手机自带的备份功能对手机QQ进行备份,将备份得到的Zip文件传输至Windows PC。

前期准备

将小米备份的Zip文件进行解压,可得到一个.bak后缀的文件,此文件实际是修改后的安卓备份文件(.ab)。

下面需要用到两个软件:HxDAndroid Backup Extractor

解包备份文件

将上面解压得到的.bak文件后缀改为.ab

在命令行中执行

1
java -jar abe.jar unpack XXX.ab XXX.tar

将得到的.tar文件进行解压

获取文件及密钥

获取nt_uid

~\apps\com.tencent.mobileqq\f\uid文件夹中,可以找到文件名为aaa###bbb的文件,其中#后面的字符串就是nt_uid

获取QQ_UID_hash

通过QQ_path_hash = md5(md5(nt_uid) + "nt_kernel")计算得到QQ_UID_hash

获取聊天记录文件

聊天记录文件位于~\apps\com.tencent.mobileqq\db\nt_db\nt_qq_{QQ_path_hash}\nt_msg.db

获取密钥

使用HxD打开nt_msg.db文件,文件头部跟随在QQ_NT DB后的8位字符串即为rand

通过key = md5(QQ_UID_hash + rand)即可获得密钥

另外,文件头部还可能含有cipher_hmac_algorithm的值(如HMAC_SHA1)

解密数据库

移除无关文件头

由于nt_msg.db文件前面有 1024 字节的文件头,导致通常的 SQLite 无法识别。需使用Hxd删除前1024个字符,即00000~003F0行,并保存为nt_msg.clean.db

或者在命令行中执行

1
python -c "open('nt_msg.clean.db','wb').write(open('nt_msg.db','rb').read()[1024:])"

打开数据库

使用SQLiteStudio打开nt_msg.clean.db,数据库类型选择SQLCipher,加密算法配置为:

1
2
3
4
5
6
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;
PRAGMA cipher = 'aes-256-cbc';

nt_msg.db内容解析

group_msg_table群聊数据

列名 类型 说明
40001 int 消息ID,具有唯一性
40002 int 消息随机值,用于对消息去重
40003 int 群聊消息ID,在每个聊天中依次递增
40010 int 聊天类型,私聊为1,群聊为2,频道为4,公众号为103,企业客服为102,临时会话为100
40011 int 消息类型,无消息:0,消息空白:1,text文本消息:2,群文件:3,系统(灰字)消息:5,语音消息:6,视频文件:7,合并转发消息:8,回复类型消息:9,红包:10,应用消息:11
40012 int pb消息类型,非常规text消息:0,普通文本消息:1,群文件其他类型消息:1,图片消息:2,群文件图片消息:2,群公告:3,群文件视频消息:4,撤回消息提醒:4,群文件音频消息:8,原创表情包:8,精华消息:11,拍一拍消息:12,群文件docx消息:16,平台文本消息:32,群文件pptx消息:32,回复类型消息:33,群文件xlsx消息:64,存在链接:161,群文件zip消息:512,群文件exe消息:2048,表情消息:4096
40013 int 发送标志,本机发送的消息为1,其他客户端发送的为2,别人发的消息为0 ,转发消息为5,在已退出或被封禁的消息中为当日整点时间戳
40020 str nt_uid, 对应 nt_uid_mapping_table
40021 str 会话ID
40027 int 会话ID
40041 int 发送状态,2为成功,0为发送被阻止(如不是对方好友),1为尚未发送成功(比如网络问题),3为消息被和谐
40050 int 发送消息时的完整时间戳,UTC+8:00
40090 str 发送者群名片,旧版 QQ 迁移数据中格式为 name(12345) 或 namei@example.com, QQNT 中为群名片
40093 str 发送者昵称,旧版 QQ 此字段为空,QQNT 中未设置群名片时才有此字段
40800 protobuf 聊天消息
40900 protobuf 不同情况下存在不一样的数据(以列40011为区分)值为8时,列40900存贮转发聊天的缓存,值为9时,列40900存贮引用的消息
40005 int 只知道自己发的消息一定概率存在数值
40058 int 当日 0 时整的时间戳格式 时区为 GMT+0800
40060 int 已退出或已解散的群聊标志
40850 int 该消息所回复的消息的序号
40030 int QQNT 保存的群号
40033 int 发送者 QQ 号

c2c_msg_table私聊数据

列名 类型 说明
40030 int 私聊对象QQ 号
40033 int 发送者 QQ 号
40050 int 时间戳(单位为秒)
40058 int 日期,当日 0 时整的时间戳格式
40093 str 消息发送者,QQ 昵称或是备注名
40800 bytes 消息内容
--- 本文结束  The End ---