2024年1月7日发(作者:)

QQ聊天记录解析

一、 问题概述

需要确定QQ安装文件路径,确定后根据分析的QQ号,获得QQ聊天记录文件。通过解析和解密该文件,得到QQ聊天记录的全部内容。

二、 文件存放路径

以路径:C:Program 为例:

路径层次

1

路径名称

QQ安装目录

详细说明

C:Program FilesTencentQQ

为安装QQ时的默认路径,如果QQ程序装在别的目录,也可以进行注册表搜索,得到安装目录。(代码1)

2 QQ号码目录 593389426

表示需要解析QQ聊天记录的QQ号码。

3

表示聊天记录消息信息存储文件。

using (ryKey reg =

bKey

(@"SoftwareTencentQQ"))

{ QQPath = ue("Install") as string; }

代码1:(得到的QQPath为QQ安装目录)

三、 问题解决方案

步骤名称

1:定义六种QQ

消息基础类型

详细说明

六种消息类型分别为:

1:BIMMsg:广播信息

2:C2CMsg:客户对客户信息

3:GroupMsg:QQ群信息

4:MobileMsg:移动QQ用户信息

5:SysMsg:系统信息

6:TempSessionMsg:临时信息

这六种类型是根据解析文件所可能获得的结构类型建立的基础常量。

2:解析首先用分析文件

文件,可以得到以下的结构化形式:

可以看出,解析出的结构,如果类型中存在聊天记录的,会显示,不存在聊天记录的类型,不会被提取出来。

在结构化图中,还有一种比较特殊的类型Matrix,他是保存加密密钥相关的信息。

下面再按照上图的结构化层次,一行一行进行解析。

就拿C2CMsg为例:

首先解析到行C2CMsg,发现他是文件夹行(类型FileType=1)并且路径FilePath(表示父文件夹)不是六种类型之一,则不处理。

再解析到行593389426,发现是文件夹行,路径FilePath

=“C2CMsg” ,为六种类型之一,则记录该行,准备分析。

再解析到行,是文件行(类型FileType=2),也不处理。

在第一次遍历的时候,只考虑文件夹的情况。通过第一次遍历解析,就可以将全部的父文件为六种类型的文件

夹提取出来,(可以发现这些文件夹为QQ号,群号,系统号10000)。

其他的几种类型文件夹解析方式同上。

得到全部相关文件夹后,遍历文件夹,解析其中的文件。从结构化层次中可以看到每个文件夹都有两个数据文件,分别是:

1: (聊天记录信息密文存储文件)

通过解析此文件,得到需要的聊天记录信息。但得到的信息为加密信息,还需要通过TEA算法,结合3中的公共密钥,对信息进行解密,得到最终的聊天记录信息。

2: (聊天记录索引文件)

通过解析此索引,得到每种类型文件夹内,一共存在的聊天记录数,方便对文件处理。

还有一个我们需要的特殊文件,是存放在特殊文件夹Matrix中的,这个文件是解密密钥的相关文件。通过QQ号和此文件信息,结合MD5算法和TEA算法,可以解析处聊天记录的公共密钥。为后面解密文件提取信息做准备。

3:获得TEA算法 1:取得QQ号的MD5散列值。

解密密钥

2:用二进制流提取出的文件信息,和1中的散列值进行MD5算法解密,得到一个解密字串。

3:将2中的解密字串作为输入值,1中的MD5散列作为解密密钥,调用TEA算法,获得的解密结果就为聊天记录信息的公共密钥。

4:根据1中的六种建立的文件夹作为解析的聊天记录的存储路径。

类型,分别在算法程序所在文件夹内建立六个子文件夹

5:在4中文件夹内遍历2中提取出的QQId文件夹,根据其父路径根据需要,建立(FilePath),在建立六种类型文件夹下,再建立以QQID命QQID子文件夹

名的文件夹,这些文件夹就是最后解析出的聊天记录文件存储地。

6:解析数据文件 遍历2中提取出的QQId文件夹,开始解析数据文件。

1:以二进制流读取文件进行解析,此文件是

文件的索引文件。即记录文件的记录数和记录长度。文件是以每4个字节为单位记录文件的长度数。

例如:读取文件,得到的byte数组为

0 0 0 0 96 0 0 0 216 0 0 0 96 1 0 0

则表示文件记录数为4。

第一个记录段长度为96-0=96;

第二个记录段长度为216-96=120;

第三个记录段长度为256+96-216=136;

第四个记录段长度为文件总长度-(256+96);

将这些信息全部记录下来,为下面解析提供数据。

2:以二进制流读取文件进行解析,此文件为记录信息。通过上面得到的每个记录段的长度,分别对文件二进制流读取相应的长度,就可以得到记录段的密文信息。通过TEA算法解密,得到记录段的真实二进制流信息。

3:分析得到的二进制流信息。

⑴读取前四个字节,表示消息的时间,这里的时间是以据“1970年1月1日8点”的偏移量(ticks)表示。

这里的时间是格林威治标准时间(1970-1-1)+中国时区(偏差8小时)。

通过方法

DateTime time =

new DateTime(1970, 1, 1,8,0,0) +

new TimeSpan(0, 0, ticks);

得到准确的消息时间。

⑵过滤内部偏移量:根据消息所属的类型,确定偏移量。其中

BIMMsg,C2CMsg,MobileMsg偏移量为1;

GroupMsg偏移量为8;

SysMsg偏移量为4;

TempSessionMsg偏移量为9;

如果消息所属类型为TempSessionMsg,执行第三步,否则跳过,直接执行第四步

⑶先用ReadInt32读取二进制流的4个字节,读取内容为一个长度值,通过该长度值,再读取相应长度的字节数ReadBytes(长度)。读出的信息表示临时信息所属的组信息。

⑷用ReadInt32读取二进制流的4个字节,读取内容为一个长度值,通过该长度值,再读取相应长度的字节数ReadBytes(长度)。读出的信息表示该条消息的发送人的信息。

⑸用ReadInt32读取二进制流的4个字节,读取内容为一个长度值,通过该长度值,再读取相应长度的字节数ReadBytes(长度)。读出的信息表示该条消息的具体内容。

还存在问题:

1:如图有的QQ的文件,会出现IMInfo文件夹和文件,用途未知。

2:解析文件时,按步骤读取了二进制流的字节数后,还会有剩余的字节,而且剩余的字节数不一致,不知道用途是什么。