吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 16027|回复: 29
收起左侧

[原创] PCXX逆向:两种姿势教你解密数据库文件

  [复制链接]
鬼手56 发表于 2019-7-20 17:00
本帖最后由 鬼手56 于 2020-5-22 10:30 编辑

定位数据库文件密码

微信的数据库使用的是sqlite3,数据库文件在C:\Users\XXX\Documents\WeChat Files\微信账号\Msg这个路径下,

1561259537651.png

所有的数据库文件都是经过AES加密的,AES的密钥是32位,而且所有数据库文件共用一个密钥,我们需要找到那个AES密钥才能进行解密,然后才能对数据库文件进行操作。

定位数据库密钥的思路

微信在登录时肯定要从数据库文件中获取历史聊天记录加载到程序中,然后我们才能看到之前的聊天记录。那么在微信读取数据库文件之前肯定要先打开数据库文件,所以CreateFile这个API就是我们的切入点。

在API断下之后怎么去找数据库的密码呢?可以根据AES的密钥长度为32位这个线索,32也就是十六进制的20,时刻注意20这个数字!

另外,在解密数据库的call中至少需要两个参数,一个是AES的密钥,另外一个是需要解密的数据库文件的路径。

还有一种方法是在内存中搜索数据库文件的名字,然后下访问断点。这种方案也是可行的。

获取数据库密钥的实战分析

CreateFileW断点

1561259356190.png

打开微信,手机不要点击登录,用OD附加微信,在CreateFileW函数下断点,下好断点之后在手机上确认登录

1561260926840.png

在CreateFileW的参数中找一个FileName为xxx.db的,我们要在微信访问这个数据库文件的时候断下,然后从这里开始往下跟。一直跟到有数据库的密码的地方

常见错误

1561269141671.png

如果出现了这个错误,需要修改一下设置

1561269184024.png

1561269200277.png

将StrongOD和OD本身取消忽略所有异常,这个错误是因为多线程访问冲突引起的。

排查堆栈

在CreateFileW的返回地址下断,直接F9运行,CreateFileW这个API我们是不需要看的

1561261789432.png

CreateFileW断点断下来,那么现在应该怎么跟呢?肯定不能一直往下单步,虽然单步也能达到目标。

分析一下现在的状况,这个时候微信的数据库处于一个还未初始化,但是即将初始化的状态,我们可以在堆栈或者堆栈附近的地址找到关于数据库初始化相关的函数。然后在微信初始化完数据库之后单步往下跟。这样能省去很多麻烦

排查堆栈地址

1561271262327.png

直接找到第四个返回地址

1561271357729.png

这个函数传入了三个参数,虽然三个参数都没有什么价值。但是这个call稍微往下拉,你会发现一个字符串

1561271414290.png

这个函数的作用应该就是用来提示错误的,一般比较大的工程都会将错误提示信息写成一个函数,报错的时候会提示哪一个模块的哪一个cpp的哪一行出错了,以便最快定位到错误点。

再往上看会发现一个je,用来跳过这个错误

1561271577621.png

根据这个错误提示的内容,我们现在可以百分百的确定打开数据库的操作已经完成!

单步跟踪

1561271822790.png

因为微信的数据库文件不止一个,所以我们不需要重启微信。直接在这个函数下断点,然后取消剩下的所有断点,按F9运行,程序断下。然后F8单步,

1561271995292.png

这里是我们遇见的第一个函数,看参数就知道不是我们想要的了,跳过 继续往下

1561272075437.png

第二个函数将数据库名和一个保存零的指针入栈,也跳过

1561272141219.png

第三个函数就很可疑了,这个call将三个参数压入堆栈,其中eax是一个结构体,里面保存一个地址和0x20这个数字,AES的密钥正好是32位的,也就是十六进制的0x20。

数据窗口跟随,前两行0x20个字节就是数据库的密钥了

1561263143154.png

各个参数含义如下:
1561265377100.png

用代码实现解密数据库

编译选项

1563544784793.png

工程需要包含OpenSSL的相关文件

解密代码

这份代码原作者是谁我已经不记得了 反正被拷来拷去拷了很多次了

编辑了好几次 都显示不正常,不放了!

实际效果

运行程序

1563545305320.png

最后生成的dec_ChatMsg.db就是解密出来的文件,对比一下解密前后的文件
1563545375014.png

解密前

1563545422871.png

解密后 看到这个MAGIC头,不用验证我就知道已经解密成功了。接下来还是验证一下结果

1563545484931.png

用Navicat新建一个SQLite连接,

1563545530465.png

选择解密后的数据库

1563545554940.png

可以看到所有的表数据已经出现了。解密完成

动态获取数据库密钥

找到了密钥之后就结束了吗?这个密钥目前是写死的,如果变化的话,我们又要重新找,然后再次输入。所以我们需要动态获取到数据库密钥。想要动态获取数据库密钥,就必须定位到数据库密钥的基址。步骤如下:

直接在CE中搜索之前找到的密钥

1561268466712.png

1561268827715.png

接着依次搜索这两个地址,找到了一个绿色的基址

1561268892759.png

这个基址以指针的形式保存了微信数据库的密钥,这个地址就是我们要的微信密钥的基址了。

动态获取数据库密钥的代码如下:

char databasekey[0x20] = { 0 };
//获取WeChatWin的基址
DWORD dwKeyAddr = (DWORD)GetModuleHandle(L"WeChatWin.dll")+ WxDatabaseKey;

LPVOID* pAddr =(LPVOID*)(*(DWORD*)dwKeyAddr);

DWORD dwOldAttr = 0;
VirtualProtect(pAddr, 0x20, PAGE_EXECUTE_READWRITE, &dwOldAttr);

memcpy(databasekey, pAddr, 0x20);

VirtualProtect(pAddr, 0x20, dwOldAttr, &dwOldAttr);

定位数据库文件句柄

在拿到数据库密码之后,我们还需要对数据库文件进行解密,解密完成之后才能查询数据库。那么有没有更好的方法可以不需要获取密码也不需要解密数据库文件就能直接进行数据库的查询操作呢?当然是有的,就是通过微信的数据库句柄!

关于微信数据库句柄

微信的数据库句柄在一些地方会经常用到,比如查询好友的详细信息的时候,需要传入一个数据库的句柄。然后通过句柄去查询信息,最后返回好友详细信息。

如果我们直接拿到密码,然后对数据库进行解密,再查询好友信息,这种方法当然也是可以的。但是拿到的数据并不是实时的。

如果我们拿到这个数据库的句柄,就能实时的去查询好友的详细信息了,而且也不需要进行解密和获取数据库密码的操作了。

获取微信数据库句柄的思路

找微信数据库句柄的思路和找数据库密码的思路是一样的,微信在点击登录的时候,肯定是要打开本地的数据库,然后获得一个句柄,所以我们可以通过在CreateFileW下断点,接着单步跟踪,就能找到数据库的句柄

定位微信的数据库句柄

1561438041362.png

在CreateFileW下断,当微信读取数据库文件时让程序断下。

1561438495400.png

接着来到CreateFileW的返回地址处,点击K查看调用堆栈

1561438566220.png

经过排查,这个地址的call最像我们需要的找的call,在这个call的地址下断,点击F9运行

1561438683397.png

程序断下,此时ecx指向数据库文件的路径

1561438908116.png

edx指向一个空的缓冲区,那么这个就非常像我们要找的call

1561439263776.png

单步步过这个call,发现缓冲区里写入了一个地址,那么就可以确定这个就是我们要找的call,只要我们HOOK这个地址,那么就能拿到所有的数据库文件的句柄了。而数据库的名称就在堆栈里,可以自己去找到偏移然后获取数据。

免费评分

参与人数 13威望 +2 吾爱币 +17 热心值 +13 收起 理由
15291037368 + 1 + 1 谢谢@Thanks!
Hmily + 2 + 7 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
1241174954 + 1 谢谢@Thanks!
蓦留 + 1 + 1 我很赞同!
我为52pojie狂 + 1 + 1 今天为你献身1分,好贴。
LIMINLI + 1 谢谢@Thanks!
onedai18 + 1 谢谢@Thanks!
mlj0381 + 1 + 1 谢谢@Thanks!
smile1110 + 2 + 1 谢谢@Thanks!
笙若 + 1 + 1 谢谢@Thanks!
cndmad + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
gqdsc + 1 + 1 大神厉害
bmwgtr + 1 + 1 支持原创,感谢大佬分享~

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

头像被屏蔽
liucq 发表于 2019-7-20 18:07
提示: 作者被禁止或删除 内容自动屏蔽
头像被屏蔽
liucq 发表于 2019-7-21 01:48
不要方和圆 发表于 2019-7-20 17:11
bmwgtr 发表于 2019-7-20 17:32
写的很详细,收藏下慢慢学习~~~感谢分享
VajraPrajna 发表于 2019-7-20 20:06
收藏下慢慢学习~~~感谢分享
 楼主| 鬼手56 发表于 2019-7-20 20:34
本帖最后由 鬼手56 于 2020-5-22 10:29 编辑
liucq 发表于 2019-7-20 18:07
//pc端密码是经过OllyDbg得到的64位pass,是64位,不是网上传的32位,这里是个坑

这句话说明你没理解32位 ...

1111111111111
晓我琴宝贝 发表于 2019-7-20 21:50
还是得去看看SQLite3源码了解下数据库加密流程更好,加密函数随意可以自定义,找加密函数和密钥的关键就是了解SQLite3那个源码
xxxx6666 发表于 2019-7-20 23:52



不明觉厉
studyggm 发表于 2019-7-21 09:07
慢慢消化,做个标记
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-22 14:57

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表