草庐IT

关于微信数据库的解密以及取证

区块软件开发 2023-03-28 原文

前言

之前研究过一段时间的wx聊天记录解密,以及小程序解密,但是在晚上陆续搜了几篇文章后发现解密教程要么下载Visual Studio,不然就是对web安全人员不友好的od调试,而且根据系统的不同,解密方法也不同,于是作者用为数不多的编程知识写出了这篇教程- -在这里记录一下解密的原理以及一些方法分享给大家。

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):

from pymem.pattern import scan_pattern_page
next_region = 0

found = []
user_space_limit = 0x7FFFFFFF0000 if sys.maxsize > 2 ** 32 else 0x7fff0000
while next_region < user_space_limit:
next_region, page_found = scan_pattern_page(
handle,
next_region,
pattern,
return_multiple=return_multiple
)

if not return_multiple and page_found:
return page_found

if page_found:
found += page_found

if not return_multiple:
return None

return found
再根据分析整体数据结构的偏移量就可获得很多信息了
![img_v2_65fcc1df-bf24-40a9-8eeb-081da6b8608g.jpg](https://storage.tttang.com/media/attachment/2022/07/15/c9c26324-e393-4893-aa6e-663be81a9139.jpg)

# 0x03 解密
上面已经获取了很多信息,接下来我准备开始解密,但是有一个问题,如果我们通过下载Visual Studio的c++库编写解密脚本而且还要自行编译,本身我也不会c++,而且Visual Studio太过臃肿,我这里在网上搜了好半天,看看有没有什么python解密sqlite的库结果发现[pysqlcipher3](https://pypi.org/project/pysqlcipher3/)可以用来解密,但是在安装的过程中,发现安装失败,结果去网上论坛搜索还是需要静态编译链接,我尝试了几次发现还是要下载Visual Studio,于是这个库我只好放弃,但是在解密mac的过程中可以使用上述的这个模块我们只需要在mac系统中安装相应工具就可以使用该模块了
brew install sqlcipher

回到windows,我实在找不到结局方案,只好使用比较low的方法,通过subprocess去调用工具,工具还是蛮小的方法可行。
if not db_file:
raise ValueError("db_File is not defined!")

if not secret_key:
raise ValueError("secret_key is not defined!")
salt = open(db_file, 'rb').read(16)
dk = hashlib.pbkdf2_hmac('sha1', secret_key, salt, 64000, dklen=32)
exe_cmd = "%s %s" % (get_exe_file(), db_file)
p2 = Popen(exe_cmd, stdout=PIPE, stdin=PIPE, stderr=PIPE, shell=True)
cmd_sql = '''PRAGMA key = "x'%s'";PRAGMA cipher_page_size=4096; ATTACH DATABASE 'decrypt_%s' AS plaintext KEY ''; SELECT sqlcipher_export('plaintext'); DETACH DATABASE plaintext;''' % (binascii.hexlify(dk).decode(),os.path.basename(db_file))

code, message = p2.communicate(bytes(cmd_sql, encoding='utf-8'))
这里我们写好了相关解密脚本结果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次生成的密钥这样的话解密就很简单了

salt = open(db_file, 'rb').read(16)
dk = hashlib.pbkdf2_hmac('sha1', secret_key, salt, 64000, dklen=32)
exe_cmd = "%s %s" % (get_exe_file(), db_file)
p2 = Popen(exe_cmd, stdout=PIPE, stdin=PIPE, stderr=PIPE, shell=True)
cmd_sql = '''PRAGMA key = "x'%s'";PRAGMA cipher_page_size=4096; ATTACH DATABASE 'decrypt_%s' AS plaintext KEY ''; SELECT sqlcipher_export('plaintext'); DETACH DATABASE plaintext;''' % (binascii.hexlify(dk).decode(),os.path.basename(db_file))
这里也遇到了坑 key可以有两种表现方式,一种是单纯字符串口令,另一种就是原始密钥,我们从内存中获取的是原始密钥所以要输入的是PRAGMA key = "x'密钥'"我们回到mac密钥的获取,因为mac的权限管理做的很死,我们首先需要关闭SIP(系统完整性保护)

系统完整性保护(SIP)是 OS X El Capitan 及更高版本所采用的一项安全技术,旨在帮助防止潜在恶意软件修改 Mac 上受保护的文件和文件夹,但这也造成了安装某些特殊版本软件的或者做特殊修改的时候权限不足。在这里就体现在使用 LLDB 调试时候,所有的调试语句都会被系统拒绝,因此在正式进行调试之前,一个重要的准备工作就是检查系统完整性保护(SIP)的开启状态,如果开启的话,要把它关闭。

检查 SIP 的开启状态

在终端里输入 csrutil status 回车,如果看到:

System Integrity Protection status: enabled.
这说明的 SIP 已经开启,如果要继续调试的话,需要关闭。如果是 System Integrity Protection status: disabled. 则说明 SIP 已经处于关闭状态,可以直接进行调试。

  1. 重启,并在开机的时候长按 Command 和 R
  2. 进入系统恢复状态
  3. 点击屏幕顶部工具栏上的 实用工具,选择终端
  4. 在终端中输入 csrutil disable 回车,会出现下述字符串,再次重启生效
1. Successfully disabled System Integrity Protection. Please restart the machine for the changes to take effect.
然后我们就可以开始调试微信了
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,回车就可以获取到了密钥

0x6000003624e0: 0x54 0x60 0x97 0x05 0xb5 0x09 0x43 0x9f
0x6000003624e8: 0x94 0xe8 0x38 0x09 0xdc 0x5e 0x79 0x53
0x6000003624f0: 0x4f 0xdc 0xa1 0x66 0x8e 0x96 0x4a 0x98
0x6000003624f8: 0x9a 0x72 0xa6 0x17 0xe0 0x17 0x7c 0x56
这里我们可以直接PRAGMA cipher_compatibility = 3就可以设置好解密参数了 ,这是一个标准

解密效果如下

3.一些其它功能

微信在2022.06月之后更改了传输文件存储位置,和每个人聊天所传输的文件会被放在不同的文件夹下,大大提升了我们寻找历史文件的难度,于是我写了个整合文件名输出的功能

还有就是压缩功能可以分别压缩数据库,图片,历史传输文件

4.碎碎念

原先想继续完善安卓和ios的解密脚本来着,但是作者马上要开始准备秋招了没时间写,等过段时间再更新下,写这篇文章的目的是想让大家接触下电子取证这个方向的知识,不仅仅是微信还有一些社交软件都可以尝试去分析下,例如soul,陌陌,qq等。不限于app甚至是阿里云镜像取证,这个方向也有很多知识值得学习。

有关关于微信数据库的解密以及取证的更多相关文章

  1. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  4. ruby - 我如何添加二进制数据来遏制 POST - 2

    我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

  5. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  6. 区块链之加解密算法&数字证书 - 2

    目录一.加解密算法数字签名对称加密DES(DataEncryptionStandard)3DES(TripleDES)AES(AdvancedEncryptionStandard)RSA加密法DSA(DigitalSignatureAlgorithm)ECC(EllipticCurvesCryptography)非对称加密签名与加密过程非对称加密的应用对称加密与非对称加密的结合二.数字证书图解一.加解密算法加密简单而言就是通过一种算法将明文信息转换成密文信息,信息的的接收方能够通过密钥对密文信息进行解密获得明文信息的过程。根据加解密的密钥是否相同,算法可以分为对称加密、非对称加密、对称加密和非

  7. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  8. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  9. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  10. ruby-on-rails - 创建 ruby​​ 数据库时惰性符号绑定(bind)失败 - 2

    我正在尝试在Rails上安装ruby​​,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf

随机推荐