Python查看Android QQ本地消息记录数据库

Python查看Android QQ本地消息记录数据库

需求

  • 随着电子产品的更新换代,隔几年我们就会换手机,早期版本的QQ不支持备份聊天记录,系统版本的不同也给QQ数据迁移带来了一定的麻烦,导致新手机上看不到以往的QQ聊天记录。如果有重要信息在里面,或者比较念旧,希望保存之前的记录,能不能将其提取出来?

调研

  • Android QQ的聊天记录存储于/data/data/com.tencent.mobileqq/databases目录下,其中QQ号.db文件即为该QQ号的聊天记录数据库,获得该文件即有机会调取出相应的聊天记录。

  • 本文仅用于技术研究和学习之用,切勿用于非法用途。

前期准备

  • 首先需要获得上面提到的 QQ号.db 文件。

    由于该文件位于/data分区下,Android 默认不可读写,如果手机已root可直接复制到电脑上。现在的手机系统大多提供了数据备份与恢复这一功能,在手机没有root并且不想root的情况下,我们可以使用这一工具备份整个QQ的数据,然后将压缩包导出至电脑上,提取出其中的QQ号.db文件。

    直接打开这个 .db 文件是不是就可以看到消息记录了呢?使用 SQLite Expert 打开这个数据库会看到,这个 database 包含很多张 table ,并且其中有许多被命名为mr_friend_***mr_troop_***,查看这些 table ,会发现里面的敏感内容如 msgData、senderuin、selfuin 等等全是乱码。大家都学过英语,这几个字段是什么意思就不用解释了,毫无疑问,这就是我们想要查询的东西,它应当是被加密了。表名mr_friend_***应当代表与某好友的聊天记录,mr_troop_***应当代表某QQ群的聊天记录,其中***为QQ号/群号的32位大写MD5值。

  • 获取加密内容的密钥

    互联网是很发达的,在博主之前早已有人破解出了密钥,在此就不用多费时间去亲自推敲了:密钥为存储聊天记录的这台手机的IMEI号,将数据库中的加密数据与该IMEI号进行异或即可解密。如果手机背面的进网许可标签没有撕掉,直接把手机翻过来就能看到IMEI号;也可以直接在手机里查询,打开拨号盘,输入*#06#,会显示14位长度的MEID和15位长度的IMEI,如果手机有两个卡槽则还有第2个15位的IMEI。

代码实现

import sqlite3
import time
import hashlib

IMEID = '****************' # 可以是15位IMEI也可以是14位MEID

conn = sqlite3.connect('*********.db') # QQ号
c = conn.cursor()

cu = conn.cursor()

# 获取表名,保存在tab_name列表
cu.execute("select name from sqlite_master where type='table'")
tab_name = cu.fetchall()
tab_name = [line[0] for line in tab_name]

num = input("请输入QQ号:")
hl = hashlib.md5()
hl.update(num.encode(encoding='utf-8'))

for line in tab_name:
  if "mr_friend_"+hl.hexdigest().upper() in line: # 查找对应QQ号的聊天记录,如果是群聊记录则需将mr_friend改成mr_troop
    cursor = c.execute('SELECT senderuin,time,msgData FROM '+line+' WHERE msgtype=-1000;') # msgtype=-1000代表文本类型

    def decrypt_msg(encrypted_msg): # 解密单条数据
      if type(encrypted_msg) is bytes:
        "" # bytes类型无需转码
      elif type(encrypted_msg) is int:
        if 1000000000<encrypted_msg<10000000000:
          timeArray = time.localtime(encrypted_msg)
          encrypted_msg = time.strftime("%Y-%m-%d %H:%M:%S", timeArray) # 时间戳需要转换为标准时间
        return encrypted_msg
      else:
        encrypted_msg = bytes(encrypted_msg, encoding = "utf8")  
      msg = []
      for i in range(len(encrypted_msg)):
        msg.append(encrypted_msg[i] ^ IMEID[i%15].encode()[0]) # 如果前面用的14位MEID此处也对应换成i%14
      return bytes(msg).decode()

    for row in cursor:
      decrypted_msgs = []
      for item in row:
        decrypted_msgs.append(decrypt_msg(item))
      print(decrypted_msgs)

注意事项

  • 若单独通过mr_troop_***查询群聊记录,无法查出群成员昵称,需结合表 TroopMemberCardInfo/TroopMemberInfo 进行显示。

  • 若仅查询QQ聊天记录中的图片、视频、语音等文件,直接检索内部存储 /sdcard/tencent/MobileQQ 文件夹即可。

  • 若查询出来的聊天记录最早时间晚于这台手机使用QQ的时间,则需结合 slowtable_QQ号.db 进行查询,QQ默认将超出一定数量限制的聊天记录转存至该文件中。

  • 在撰写完本文后偶然发现一位大佬编写的源码与GUI,还比较全面,一并分享于此,供大家研究参考:怎样导出手机中的QQ聊天记录?

  • 本文仅用于技术研究和学习之用,切勿用于非法用途。

参考资料

posted @ 2021-02-18 13:35  Lolipop  阅读(42)  评论(0编辑  收藏