首页 > 其他分享 >逆向WeChat(七)

逆向WeChat(七)

时间:2024-10-07 21:43:49浏览次数:1  
标签:逆向 微信 数据库 RSA ----- KEY WeChat

上篇介绍了如何通过嗅探MojoIPC抓包小程序的HTTPS数据。

本篇逆向微信客户端本地数据库相关事宜。

本篇在博客园地址https://www.cnblogs.com/bbqzsl/p/18423518

微信PC客户端有两种主要的数据存储类型,一种是基于sqlcipher,另一种是基于protobuf。除了这两种外还有别的,不在本篇内容。

它们是对应两个主要的类,StorageBaseConfigInfoStorage。StorageBase使用sqlcipher作为存储手段,ConfigInfoStorage则使用protobuf存储KeyValue。

StorageBase是一个单表操作的封装类,它包含了数据库名跟表名等信息。它封装了打开,查询等底层操作。它的StorageBase::init方法完成了打开数据库以及必要的设置,包括CipherAndKey的设置。逆向分析到现在,我才发现微信是有用混肴的代码段来做代码保护,这个段位于WeChatWin.dll的末尾。StorageBase::init调用DBFactory::openDBbyName方法完成全部打开工作。这个DBFactory::openDBbyName方法,它的日志信息全部字符串都经过混肴处理,显然是不想让人知道。并且DBFactory::openDBbyName的主执行体逻辑被编辑在混肴代码段。混肴代码的目的,不单是让人变白痴,更加重要是让逆向的工具变白痴,包括调用器。微信使用的混肴,有个特点,就是满天的call指令。只要你清楚call指令只是jmp&push的等价物,就明白它的恶心了。调用器的调用栈帧功能,只能用于分析ebp, eip这种中规中举的调用,混肴的call根本不在于call&ret,如果你认为它会在call的下一指令,ret回来执行,你可能等不到它执行。包括逆向工具的代码分析功能也同样被打成白痴。call等同jmp并push eip。这时的eip不是为了ret,而为了开辟esp,并将eip作为后面这个栈位置的内容的解码因子。或者这个栈位置的内容后面是被直接替换而丢弃的。不单代码混肴,连栈结构都被混肴。

所以碰到混肴保护的代码,Mother Mary comes to me Speaking words of wisdom let it be。虽然我假设,微信可能在这里将数据库的KEY,还在KEY的计算方法保护了起来。我承认我还停留在8年那个安卓版的魔法MD5(imei+uin)。想必PC的计算方法是Foo(myPCInfo, uin),存在于客户端代码某处。既然它们都用混肴代码保护起来了,就 so i listened to Mother Mary,let it be。正当我是这么在想的时候,一处AccountService::setDBKey却赫然在目。唉?不对吧。于是我赶紧windbg跟踪。咦?这参数里面不就有我的数据库的KEY吗?前面我还在说,微信煞有介事地用混肴代码将sqlcipher打开数据库的一连串操作,包括KEY设定,通通都保护起来。现在却明目张胆地露出来。这是在打我脸,还是在打它自个的脸。这戏到底在唱的是哪一出,我完全看不懂。它拼命地将那里遮起来不让别人知道,但用来遮住那里的东西却有一张照片是裸露那里的。这是在玩彩蛋。直到看了它们的技术post才明白,”安全性。基于不怕被破解,但也不能任何人都能破解的原则“,https://cloud.tencent.com/developer/article/1005575。这词令有点耳熟,好像在哪里听过类似的格式的短句。微信开发团队为大家指明了方向,欢迎来破解,就怕你不会。(原来它们的数据库还有一个正名WCDB, https://cloud.tencent.com/developer/article/2406614。我却一直将它当sqlcipher在处理。WCDB是用在移动终端的,PC端的应该不是。)虽然市面上关于这个的破解已经写到烂大街,只要在github上搜wecaht Db crack关键词,就有一大堆的repos。我就简单介绍我的分析,还有方法,为观众多一种角度。AccountService有三个成员变量,DBKey,RSA公钥,RSA私钥。它们都是std::string类型。并且有已知固定的长度。最lucky的是,它们之间的相对位置经历了这么多年还有版本都没有变化过。搜查的步骤,先通过RSA私钥字符串的地址,再将地址值结合字符串的长度值找到RSA私钥成员变量的位置,然后相对偏移后得到DBKey成员变量的位置。就如我们熟悉的几何定理三点定面一样,锁定位置。只要三条指令,就可以用windbg实现目标。

x86

s-a 0 L10000000 "-----BEGIN RSA PRIVATE KEY-----"
        * theRes
s-d wechatwin L2000000 theRes 0 0 0 377 37f
        * theRes2
da poi(theRes2 - 18)
        * check if "-----BEGIN PUBLIC KEY-----"
db poi(theRes2 - a8) Lpoi(theRes2 - a4)

x64

s-a 0 L10000000 "-----BEGIN RSA PRIVATE KEY-----"
		* theRes
s-q wechatwin L2000000 theRes 0 377 37f
		* theRes2
da poi(theRes2 - 20)
		* check if "-----BEGIN PUBLIC KEY-----"
db poi(theRes2 - f8) Lpoi(theRes2 - f0) 

补充一下,windbg没有像gdb那样,可以赋值变量,但可以用alias代替。将theRes跟theRes2别名成结果地址, 或者手动替换指令中的theRes跟theRes2。另外一次最多只能搜索地址空间0x10000000,因些在第一个地址段找不到,请用下面命令扫描地址空间的全部用户空间。

s-a 0 L10000000 "-----BEGIN RSA PRIVATE KEY-----"
s-a 10000000 L10000000 "-----BEGIN RSA PRIVATE KEY-----"
s-a 20000000 L10000000 "-----BEGIN RSA PRIVATE KEY-----"
s-a 30000000 L10000000 "-----BEGIN RSA PRIVATE KEY-----"
s-a 40000000 L10000000 "-----BEGIN RSA PRIVATE KEY-----"
s-a 50000000 L10000000 "-----BEGIN RSA PRIVATE KEY-----"
s-a 60000000 L10000000 "-----BEGIN RSA PRIVATE KEY-----"
s-a 70000000 L10000000 "-----BEGIN RSA PRIVATE KEY-----"

 

我也跟跟风,写一个https://github.com/bbqz007/CrackMicroMsgDBKey关于如何用windbg看密钥。

  

找到DBKey后,当然就想知道计算Key的代码。开始我以为会在混肴代码段,但在发现AccountService::setDBKey后,再去跟踪才真相大白。DBKey由服务器返回,计算不在客户端,而在服务器。

有需要的请自行探究,与Auth相关的类。

加密解密两因素,一是Key,二是Cipher。多年没碰微信数据库,我也忘了cipher的设定。随便找个最新的sqlcipher来用,key对了还是死活打不开数据库。因为每个sqlcipher版本默认的cipher不同,或者分发软件的发行者编译的选项不同,默认的cipher不同。cipher的设置必须也要匹配。我们可以直接通过微信直接查询它打开的数据库。一共有kdf_iter,cipher_page_size, cipher_use_hmac, cipher_plaintext_header_size, cipher_hmac_algorithm,cipher_kdf_algorithm六项。

微信将sqlcipher的访问封装成一个单表操作的类。StorageBase。它包含了数据库名,表名,还有最重要的数据库句柄。毕竟还是sqlite3。我们只要找到api表就可以使用所有c接口了。上图的示例就是通过api表的c接口访问StorageBase打开的数据库句柄。即使StorageBase虽然将打开数据库的流程通通用混肴代码保护起来。

得到capi表后,sqlite3_exec可以操作数据库,如上图演示,sqlite3_prapare可以跟踪sql,如下图演示。

 我已经在我的KTL工具ver0.9.1gitee仓库)添加了patch,方便有需要的人,只要在AlgoDataTool.cpp设置你的破解出来的DBKey,就可以浏览你的微信数据库。

数据库文件目录在”我的文档“下,”WeChat Files\wxid_????????\Msg"。如果想知道当前登陆的wxid,可以查看”WeChat Files\config\AccInfo.dat",字符串类型数组中编号4的数值,而编号10则是昵称。如何查看,就是接下来要介绍的另一种数据库类型,我同样也在KTL添加了patch,提供对应查看工具。在本篇,数据库是一个广泛的,包括各种格式的数据文件。比如,类mongodb同样可以用plaintext的方式作为底层存储。一种格式的文件也可以通过mysql存储引擎接口做成自定义存储引擎被mysql使用。

 

另一种数据库基于protobuf,类型名称为ConfigInfoStorage。它的主要数据成员是micromsg::KeyValueSetting,这是由proto文件生成的类。虽然没有KeyValueSetting的proto文件,但是由逆向内容可以分析根结构。

根级结构主要有5个成员,它们都是数组,每个数组元素皆为一个key-value对。key是整形。知道总的框架结构,在没有proto文件情况下,也可以对protobuf进行大概的分析。虽然没有proto定义文件,但仍然可以用protoc工具解码,只是不知道成员的名称,所有名称都是整形的位置号。但是有了上面的根级结构就可以开展分析。根1号位是32位整形的value数组,每个value都有一个名称对应的编号。数组每个元素是一个intkey-value的proto,所以元素的1号位是intkey,2号位是value。后面的数组以同样的方式。根2号位是buffer类型的数组,这里的buffer有些是经序列化的protobuf。可以认为是对象类型的数组。根3号位是字符串数组,所有字符串的value都在这个数组。根4号位是64位的整形数组。根5号位是浮点形数组。

protoc工具不能在没有proto文件的情况下,解码成JSON格式,只能用TextFormat。但是这个TextFormat是真的独特,似DICT或JSON,但又不同。不能方便使用python或json浏览器进行分析。所以我用我的KTL添加了一个功能,可以将protoc工具解码出来的TextFormat转换成JSON,并提供可视视图。有了转换后的JSON,可以粘贴到任意你喜欢的可视工具进行分析,最简单的就是使用chrome浏览器的devtools,粘贴到console执行。

数据库文件目录在”我的文档“下,”WeChat Files\config\“。其中AccInfo.dat对应AccoutService类,aconfig.dat对应AccoutStorageMgr类。

本篇相继介绍了微信如何使用sqlcipher,AccoutService类,基于protobuf的key-value数据库,ConfigInfoStorage类。数据库存储在我们的电脑磁盘,而类运行在我们的内存。通过扫描这些东西,就可以搜集个人信息。AccoutService类还包含了绑定的手机号。又例如,单纯扫描磁盘,不扫描微信进程,不扫描sqlcipher数据库。也可以得到当前登陆的微信号,这个微信号使用了哪些小程序,这些小程序是哪些知名的小程序应用,是哪种类型的小程序应用,这个微信号有着一些使用习惯喜好以及需求,等等。(每个小程序有一个唯一的AppID,还有绑定的公众号)。配合扫描微信进程的DBKey,就可以直接窥探更加多内容。

在我的KTL工具ver0.9.1gitee仓库)添加了两个patch,patch.sqlcipher查看sqlcipher数据库,patch.protobuf查看protobuf数据(文件)。

 

另外直得一提。wechatwin.dll就像一个Library,静态编译进了不计其数的开源库。sqlcipher也是其中之一。我们也可以直接wechatwin.dll。

 

 

本篇到这里,下一篇再见。

逆向WeChat(七,查找sqlcipher的DBKey,查看protobuf文件)

逆向WeChat(六,通过嗅探mojo抓包小程序https,打开小程序devtool)

逆向WeChat(五,mmmojo, wmpfmojo)

逆向通达信 x 逆向微信 x 逆向Qt (趣味逆向,你未曾见过的signal-slot用法)

逆向WeChat(四,mars, 网络模块)

逆向WeChat(三, EventCenter, 所有功能模块的事件中心)

逆向WeChat (二, WeUIEngine, UI引擎)

逆向wechat(一, 计划热身)

我还有逆向通达信系列

我还有一个K线技术工具项目KTL可以用C++14进行公式,QT,数据分析等开发。你的代码JustInTime运行。

标签:逆向,微信,数据库,RSA,-----,KEY,WeChat
From: https://www.cnblogs.com/bbqzsl/p/18423518

相关文章

  • 【极客大挑战2023】- Re -点击就送的逆向题 WriteUp
    这道题给了一个.s文件解决方案有两个:1.利用gcc编译成可执行文件,然后反编译生成伪代码2.直接分析汇编(我不会。。。)1.利用gcc编译成可执行文件linux执行gcc-o1.s1IDA打开,分析并编写,注意一定要在字符串末尾加上\0结束符!!!点击查看代码#include<stdio.h>intmain(void){......
  • js逆向实战之酷我音乐请求参数reqId加密逻辑
    声明:本篇文章仅用于知识分享实战网站:https://www.kuwo.cn/search/list?key=可以不是你加密逻辑分析访问界面,根据数据包的回显内容判断哪个是我们需要的。找到相应的数据包,看下请求参数。发现reqId参数是一串随机字符串,所以就需要知道该参数的生成过程。全局搜索reqI......
  • “16*16逐行式顺向阴码”转“16*16列行式逆向阴码”字模C代码
    前段时间做的项目,从HZK16字库中读取的字模数据是16*16逐行式顺向格式的,传输给客户的设备无法显示,他们那边不能改变OLED屏显示的方式,所以写了一个简单的字模转换算法;HZK16的读取网上一搜就是一大堆,所以这里就不贴这串代码了;测试的时候可以使用PCtoLCD工具生成两种不同格式的字模......
  • 犀牛数据爬虫逆向分析
    目标网站aHR0cHM6Ly93d3cueGluaXVkYXRhLmNvbS9pbmR1c3RyeS9uZXdlc3Q/ZnJvbT1kYXRh一、抓包分析请求参数和响应数据都有加密二、逆向分析1、请求参数请求参数生成位置数据解密涉及到一个异步栈解密后的数据形式剩下的就是扣取代码了,很简单,缺啥补啥就行本地实现......
  • APP逆向实战:喜马拉雅(OLLVM混淆,字符串加密)
    喜马拉雅抓包:POST/mobile/login/pwd/v3HTTP/1.1Cookie:1&_device=android&fcecf4c4-5ddc-30e3-86b1-6e675f92bfd0&6.6.99;channel=and-f5;impl=com.ximalaya.ting.android;osversion=29;fp=009527657x2022q22564v0500000000000000000000000000000000000000;devic......
  • 某招标投标爬虫逆向分析
    目标网站aHR0cHM6Ly9jdGJwc3AuY29tLyMv一、抓包分析请求参数和响应数据都加密了二、逆向分析1、请求参数下xhr断点,此时Jk中已经携带了加密的请求参数,Jk刚好又是前面生成的打上断点,看下是什么逻辑进入方法内部第一个Jk是用于生成最终的Jk最终在这里生成扣取......
  • Reverse easyre一个非常简单的逆向
    PETools是一个Windows系统下的工具集合,主要用于分析、检测和处理Windows可执行文件(如.exe、.dll等)。其中包含的"ShellcodeAnalzyer"或"Shellcode识别器"功能,可以帮助用户检查可执行文件是否嵌入了壳码(shellcode),即一段小型的、独立于操作系统环境的程序代码,常用于恶意软件中,以......
  • gewechat微信机器人搭建 教程/开发
    GeWe开放平台是基于微信开放平台的二次封装API服务,开发者可以使用本服务来处理微信中的各种事件,并可以通过后台调用对应的API来驱动微信自动执行任务,如自动收发消息、自动化应答、自动群邀请、群管理等,封装了RPA技术流程,简化开发者二次开发难度,提供了开发者与微信对接的能力,使用......
  • 某片滑块验证码逆向
    目标网站aHR0cHM6Ly93d3cueXVucGlhbi5jb20vcHJvZHVjdC9jYXB0Y2hh一、抓包分析包含各种加密参数,包括轨迹的 二、逆向分析 请求参数,其中captchaId是固定不变的,token是上个接口返回的跟栈,最顶端堆栈机密参数已经生成往回跟栈,cb值、i和k的值是在这生成的此时e包含了......
  • 17xx 物流查询平台 last-event-id 参数逆向分析
    声明本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!本文章未经许可禁止转载,禁止任何修改后二次传播,擅自使用本文讲解的技术而导致的任何意外,作......