撬开PC QQ的本地SQLite数据库(适用于Msg3.0.db等)

*注意 本文于2月14日(0950z)发布于52pojie.com;不允许转载。如果发现,追究侵权责任

去年年底我发了一篇撬开MacQQ的本地SQLite数据库(适用于Msg3.0.db+)。有部分读者在下面询问相同的方法能不能在PC(Windows上使用)——答案当然是不行的。今天正好需要解开一个Windows下的QQ数据库文件,所以研究了一下,写了这篇文章。

在文章开始前,先做一下Q&A:
1. 打开本地QQ SQLite数据库的意义是什么?
主要是方便备份聊天记录,以及在极端情况下,如果QQ被封,只要先前备份过数据的key,那聊天记录依然可以提取,减少信息丢失带来的损失。
2. 这个方法会不会被不法分子利用窃取隐私?是不是可以用来盗取别人的聊天记录?
该DB文件密码由线上下发而来(具体原理是读取db的SQLite Header,然后发送sso_cryptsvr.0x12c包,从服务器上获得)。发包要求使用密码进行初步认证(wtlogin),因此没有该QQ号的密码,是不可能打开数据库文件的。(这里不考虑对于QQ程序的攻击引发的数据库密码泄露)

-------ZCZC 正文开始----------
本次分析过程使用的是新版的PC版QQ,聊天记录文件存放于Msg3.0.db。用hex工具打开文件一看,就发现有SQLIte3的头。说明和MacQQ一样,也是SQLite3。加密情况暂时不明,猜想应该是一样的(最终证明的确是一样的。)

既然是sqlite3,那么总体思路不变,找到调用key的函数。首先看的是sqlite.dll,里面有sqlite3_open都没有发现sqlite3_key为名的函数。接下来继续寻找……
发现在KernelUtil.dll里,找到了一些和SQLite3有关的函数,其中的CppSQLite3DB::key似乎就是我们要找的函数。

x32dbg下了一个断点,发现没有命中。于是disassem一下,看看这个函数里面在干嘛。

其中sub_5D2477A0这个函数长得还挺可疑的。其他的函数看起来都人畜无害。跟进去看看:


发现了关键数字“16”,MacQQ上的Msg3.0.db的keysize就是16。所以怀疑这个函数肯定和设置key有关系,暂名为sqlite3_key_。
查看交叉引用,发现了在CppSQLite3DB::open里也被使用了,于是也在这里下个断点。

(顺便还把其他有“key”的地方都打上了断点)

一次性命中,啪得一下,很快啊。x86,参数栈传。可以注意到call这个函数的时候,参数类型sqlite3_key的定义很像。
FYI,定义是 int sqlite3_key(sqlite3 *db, const void *pKey, int nKey);

那么第二个参数就是数据库密码,第三个参数指示长度为16位。key大部分为可见字符。
尝试使用上一篇文章提到的方式,对该数据库进行解密。

发现大成功,说明加密算法和Mac版QQ的加密算法一致。

兴冲冲地用工具打开解密后的db,发现并打不开。
难道解密失败?
继续使用hex工具。可以看到,内容已经全部是明文了。不过前面有400字节的extheader,这就是导致SQLite工具打不开文件的原因。

手动删除400字节的头,Msg3.0.db 打开成功。

数据库可以打开了,但是聊天记录以及聊天记录metadata是编码状态,需要解码后才能使用。

---NNNN--

PS. PC版的QQ是有QQProtect这种流氓功能的,QQProtect以内核态驱动形式载入,还篡改了SSDT。所以直接调试被QQProtect保护的QQ主程序非常困难。这里面有一些小trick,不属于本文讨论的内容。有兴趣的可以自己研究。
PS2. 在打开PC QQ登录的时候,会出现多个进程。大致是启动进程、登录UI进程和服务进程(负责实际工作)。启动进程在唤起UI进程之后会立即被销毁。登录完成后,登录UI进程也会被销毁,断点必须打在服务进程上。

THE END
喜欢就支持以下吧
点赞0
分享
评论 抢沙发
  • 管埋员

    昵称

  • 取消
    昵称