1.原理
SQLite 是一个轻量级的、开源的关系型数据库,是目前移动平台(如 iOS、Android)数据库的最佳选择。然而免费版的 SQLite 是不支持加密的(官网下的默认就是免费版的) ,这就导致了存储在 SQLite 中的数据很容易被人查看到,不法分子可能会利用数据库表结构及内容字段分析我们的应用,进而发起攻击。出于安全的考虑,我们当然要对数据库文件进行加密。
微信数据库的类型是sqlite,不管是ios还是mac还是win或者安卓,区别在于每个数据库都加密了但是加密的密钥不同,这里win和mac主要采用从远程服务器获取一些信息加上本地的某些信息通过一系列算法生成的密钥通过AES加密的,AES的密钥是32位,而且所有数据库文件共用一个密钥,我们需要找到那个AES密钥才能进行解密,然后才能对数据库文件进行操作。但是安卓和ios不同,通过翻阅一些文章发现,手机端的数据库生成的密钥是通过本地已有数据进行生成的密钥,仅有7位,我们可以通过暴力破解的方式获取密钥。
解密PC数据库 一般都是通过od附加微信进行动态调试 https://bbs.pediy.com/thread-251303.htm还有一种办法就是通过寻找微信模块的地址然后加上偏移量就能获取密钥以及一些用户信息,但是这也有个问题就是当每次微信版本更新时偏移量也会随之改变,我看到解决方法是作者需要每个版本获取偏移量,然后更新工具这样也很麻烦。
于是根据别人的文章分析了一下,如果说每次偏移量都会变但是相关信息的数据结构的相对便宜量不会变,这种方式可以全版本通用,通俗一点来讲就是,每次私钥和wxid的字符串地址虽然会变但是相对位置不变,我可以通过wxid的字符串加减多少一定能找到私钥的地址。
2.分析
这里我首先通过往常一样的动调发现,在密钥出现的上下地址中存在另一种公钥和私钥的字符串-----BEGIN PUBLIC KEY-----\n...这不就是一个很好的特征吗于是我们首先通过python中的pymem模块来操作内存,至于为什么要用这个模块的,因为他对初学者比较友好里面封装了很多函数,很方便调用适合我这种对win系统不了解的人,按照这个思路我们先找到-----BEGIN PUBLIC KEY-----字符串的地址,再去反向搜索这个地址的地址,根据测试这个地址一般是大于WeChatWin.dll 但也不是绝对有些情况会导致搜不到这个字符串地址。
但是这里出现了一个问题,我在学习pymem的过程中通过翻阅文档发现有一个全局搜索函数pattern_scan_all,但是通过实际下载pymem模块时候却没有了这个函数,于是我这里只好自己把这个函数再重新写一遍。```def pattern_scan_all(handle, pattern, *, return_multiple=False):
brew install sqlcipher
这里我们写好了相关解密脚本结果mac数据库和win数据库采用的加密方式不同,于是我又去了解了一下。
传入密钥
通过Rand_bytes算法生成16个字节的salt,并存储在数据库第一页的头部(SQLite3的db文件,头部前16个字节固定为SQLite 3 format,所以可以利用文件头来存储一些数据)。
通过PKCS5_PBKDF2_HMAC_SHA1算法将密钥和salt一起加密并多次迭代,生成AES加密所用的key;此处是对key的加密,即使原始的密码泄露,也无法解密数据。
通过AES对称加密算法对每一页的文件内容(有效的内容,不包含文件头和reserved字段)进行加密。
加密时,文件执行过AES加密后,对文件内容,通过Hmac算法,获取文件校验码,填充在page尾部(SQLite3提供了reserved字段,自动在page尾部预留一段空间)。
解密时,先调用Hmac算法获取文件标识码,与page尾部的数据进行对比,如果数据一致,则证明文件没有被篡改过,不然证明文件已经被篡改,则抛出异常。
PS:以上为默认的算法,sqlCipher没有固定算法,用户可以自己设置。
经测试windows系统的wx数据库就是用上述加密方式,首先会通过读取文件头生成16个字节的salt,再使用PBKDF2_HMAC_SHA1算法设置迭代次数为64000次生成的密钥这样的话解密就很简单了
这里也遇到了坑 key可以有两种表现方式,一种是单纯字符串口令,另一种就是原始密钥,我们从内存中获取的是原始密钥所以要输入的是PRAGMA key = "x'密钥'"我们回到mac密钥的获取,因为mac的权限管理做的很死,我们首先需要关闭SIP(系统完整性保护)
系统完整性保护(SIP)是 OS X El Capitan 及更高版本所采用的一项安全技术,旨在帮助防止潜在恶意软件修改 Mac 上受保护的文件和文件夹,但这也造成了安装某些特殊版本软件的或者做特殊修改的时候权限不足。在这里就体现在使用 LLDB 调试时候,所有的调试语句都会被系统拒绝,因此在正式进行调试之前,一个重要的准备工作就是检查系统完整性保护(SIP)的开启状态,如果开启的话,要把它关闭。
检查 SIP 的开启状态
在终端里输入 csrutil status 回车,如果看到:
这说明的 SIP 已经开启,如果要继续调试的话,需要关闭。如果是 System Integrity Protection status: disabled. 则说明 SIP 已经处于关闭状态,可以直接进行调试。
- 重启,并在开机的时候长按 Command 和 R
- 进入系统恢复状态
- 点击屏幕顶部工具栏上的 实用工具,选择终端
- 在终端中输入 csrutil disable 回车,会出现下述字符串,再次重启生效
然后我们就可以开始调试微信了
1. 打开电脑端微信(不要登陆)
2. 在Terminal输入命令lldb -p $(pgrep WeChat)
3. 输入br set -n sqlite3_key,回车
4. 输入c,回车
5. 手机扫码登陆电脑端微信
6. 这时候电脑端微信是会卡在登陆界面的,不需要担心,回到Terminal
7. 输入memory read --size 1 --format x --count 32 $rsi,回车就可以获取到了密钥
这里我们可以直接PRAGMA cipher_compatibility = 3就可以设置好解密参数了 ,这是一个标准
解密效果如下
3.一些其它功能
微信在2022.06月之后更改了传输文件存储位置,和每个人聊天所传输的文件会被放在不同的文件夹下,大大提升了我们寻找历史文件的难度,于是我写了个整合文件名输出的功能
还有就是压缩功能可以分别压缩数据库,图片,历史传输文件
4.碎碎念
原先想继续完善安卓和ios的解密脚本来着,但是作者马上要开始准备秋招了没时间写,等过段时间再更新下,写这篇文章的目的是想让大家接触下电子取证这个方向的知识,不仅仅是微信还有一些社交软件都可以尝试去分析下,例如soul,陌陌,qq等。不限于app甚至是阿里云镜像取证,这个方向也有很多知识值得学习。