NTQQ聊天记录导出方法
近期尝试把积攒多年的QQ聊天记录进行蒸馏,但发现使用NT架构的新版QQ后无法直接导出聊天记录,在此简单记录一个可行的获取聊天记录方法。以下内容以小米HyperOS下的NTQQ 9.2.65为例
获取聊天记录数据库
导出Android QQ备份文件
使用手机自带的备份功能对手机QQ进行备份,将备份得到的Zip文件传输至Windows PC。
前期准备
将小米备份的Zip文件进行解压,可得到一个.bak后缀的文件,此文件实际是修改后的安卓备份文件(.ab)。
下面需要用到两个软件:HxD、Android 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 | PRAGMA key = '密钥'; |
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 | 消息内容 |