之前写过几篇使用OllyDbg进行逆向工程,并使用Frida编写HOOK注入程序的教程。后来有朋友寻求帮住,看看能不能帮忙做一个微信逆向的学习课程。由于这个涉及到一些法律风险,感觉不是很靠谱,因此并没有出这个学习课程。不过还是在网上找到了两篇比较有意思的文章。接下来通过分析这两篇文章中的逆向过程,比较一下两种方法的优劣,并探讨一下是否还有更优的方案。
方案一的优点与缺点
首先,CSDN的这篇文章《PC微信逆向发送与接收消息的分析》中使用了OllyDbg和Cheat Engine。首先从接收消息功能说,逆向分析的大致过程主要是以下几步:
- #1. 使用另一个账号往逆向微信客户端发送消息(最好用英文或者数字,方便分析内存地址)
- #2. 多次发送消息后筛选出高可疑存放消息的地址空间
- #3. 在该地址空间打写入断点并再次接收消息使得断点生效
- #4. 在调用堆栈中找到合适的调用入口
- #5. 确认调用入口并计算Hook内存偏移,数据内存偏移
注意:该文章中关于接收消息的逆向方案从一开始就有问题,最后找到的HOOK地址是错误的,会出现“同时接收多条消息时会有丢失,只能接收到一条”的问题。但是对于初学者,熟悉逆向操作和入门各种逆向工具的使用还是非常有帮助的。尤其是熟悉内存地址的概念,调用堆栈的概念,以及各种寄存器的概念,该篇文章这部分还是非常值得学习的。
以上5步中最复杂和费时的是第4步,当OllyDbg的内存写入断点生效时,函数调用堆栈中的每一个调用入口都是一个潜在的正确的Hook入口。下图是原文中的调用堆栈截图:
通常一个调用可能涉及到好几层函数过程调用,因此就只能把所有这些调用都打上调用断点(这个断点和内存写入断点是不一样的,需要注意),然后一句一句地去读汇编指令。大家千万不要觉得读汇编很复杂,其实就事论事地说,接收消息的逆向汇编相对简单很多。因为在读汇编的过程中需要关注的数据相对较小,我们只需要关注寄存器中会不会出现接收到的消息内容和消息发送好友的微信号。当某一个过程调用前,寄存器中已经准备好了消息数据,那么这个过程调用的内存地址大概率就是一个合适的HOOK地址。如下图中汇编窗口截图:
上图红框中出现了多个寄存器,其中包括eax,ebx,ecx。然而CSDN这篇教程中的文字说明说去找esp寄存器(亲测其实找EDI寄存器更合适),导致图片和文字说明完全对不上。我当时看的时候也是一头雾水。其实在实际操作过程中,每一个寄存器(右上角窗口中的EAX、EBX、ECX、EDX、ESP、EBP、ESI、EDI)都要留意。CSDN中这篇教程虽然最后被证明是存在问题的,但是思路和操作过程还是非常推荐学习以下,尤其是实际操作部分,对于掌握和熟悉OllyDbg非常有好处。
方案二的优点与缺点
下面我们还说说另外一篇博客园的教程《Windows逆向分析入门(八)——实战篇(收发文本消息)》。我最后通过该篇教程实现了自动接收消息,并且没有出现消息冲突问题。该篇教程中开头部分讲得比较笼统,对于初学者来说过于宏观,缺少细节,无从下手。该教程的主要思路如下:
- #1. 在微信界面发送消息
- #2. 在OllyDbg中观察日志模块的输出
- #3. 在OllyDbg中查找日志输出中的可疑字段并在汇编窗口打断点
- #4. 在调用堆栈中找到合适的调用入口
- #5. 确认调用入口并计算Hook内存偏移,数据内存偏移
由于该教程中使用的是爱破解版本OD并且安装了很多插件,我使用的是原版OllyDbg,因此也无法按照原文中的流程操作。我通过原版OllyDbg中的Search for->All referenced text strings功能,然后把所有的文本信息拷贝到文本编辑器中,再搜索所有“On MsgAdd PrefixId”的字符,最后发现3处汇编语句有这个文本赋值操作。因此再这三个语句上打调试断点。随后通过收发消息,观察功能函数过程调用情况。如图所示:
EBP寄存器是一个特殊的寄存器,上图中该断点位置可以看到微信消息被压入了EBP寄存器中。如果每次接收消息时,微信消息数据相对于EBP寄存器的内存偏移不变,那么这个地方可以作为HOOK的一个入口地址。
该方案中的方法论严重依赖微信的XLOG输出并且在代码中搜索对应的字符串。如果字符串不是按照常量的形式在寄存器中赋值(这个是我猜的),或者没有使用XLOG类了,这个方法就难在新版本中实施了。当然这个方法在当前的版本还是挺有效果的。通过这个方案定位HOOK入口,相比CSDN中的方案靠谱很多,目前检测没有发现丢数据的问题。
扫码联系船长