使用x64dbg分析微信聊天函数并实现发信息
1.引言
我们知道微信现在不光在手机上很常用,在电脑也是非常常用的,尤其是使用微信联系客户和维护群的人,那这个时候每天都会定期发送一些信息,如果人工操作会很累,所以自动化工具是王道,本节就使用x64dbg让你看看怎么完成发消息。本节完整源码在github:https://github.com/15pb/wechat_tools
2. 网络协议分析模型
首先我们讲一些理论知识,在开发中,网络通信的协议最常见的有tcp,udp,http等,而在通信时使用的模型(这里的模型说的是代码执行方式)也不尽相同,我们在分析微信协议的时候第一要确定微信是什么通信协议,第二要确定使用的是哪种模型。第三再分析微信的私有通信协议完成调用。
2.1 PC微信通信协议的识别
PC端微信使用的协议我们可以通过对每种协议相关的API设置断点来确定是哪个协议。一般PC端客户端程序的通信协议常用的是tcp和udp。
关于tcp,udp的API:
| 协议 | 函数 |
|---|---|
| tcp | send |
| udp | sendto |

2.2 通信模型的识别
知道了通信协议之后,再说说通信协议的模型。一般我们在开发网络程序时,会采用两种方式来与网络进行通信,第一种是就是直接从UI获取数据然后发送数据,第二种是有单独的工作线程负责发送数据,两种通信模型我把它们分别称为同步模型,异步模型。 这两种模型中异步模型是比较复杂的,为了方便大家理解,我们将两种模型最简单的雏形给大家梳理一下:
① 同步模型

这种模型的优点在于UI操作完就可以立即发送,非常适合我们做逆向分析,通过栈回溯一般都可以找到字符串的踪迹,从而找到发送消息的函数,剩下的就是分析其参数,完成调用即可。一些网络负载不是太大的程序,比如普通软件、2D网络游戏,大多会采用这种方式,实时的获取
② 异步模型

这种模型通常在UI线程中发送数据时会添加到一个队列中,然后在工作线程中不停的从队列中读取数据,然后发送数据。在逆向分析时,我们要做的就是通过在send设置断点,然后可以通过观察send的参数缓冲区,再对缓冲区或是与缓冲区关联的地址设置访问或写入断点,断到写缓冲区,添加队列的地方。之后在去找调用函数。由于这个过程比较复杂,有时需要多次设置断点才可以找到我们想要的信息。
3. 使用x64dbg分析微信模型与定位关键函数
基于上面的理论,我们实际去分析一下微信的通信模型。
3.1 使用x64dbg分析微信网络发包线程
首先我们还是在send设置断点,然后等断下之后观察堆栈窗口中有没有敏感字符串,我们使用PC版微信中的文件传输助手来测试

当send断下之后,我们查看堆栈窗口中的信息,观察有无我们输入的字符串

实际观察会发现堆栈中没有我们想要的字符串,一般这个时候可以大致确定发送数据的这个线程与UI线程不是一个线程,通信的模型属于异步模型。
3.2 使用x64dbg定位UI线程的队列添加
确定了异步模型,我们下一步做的就是在send的参数buf上设置硬件写入断点,看看哪里给这个buf写入了信息,找到那个队列信息。
在send函数断下返回上层的代码中,发现buf的传递经过了好几层,而这几层当中有一个地址中的内容是随着消息的改变而变化的,所以我们可以对这个地址设置硬件写入断点,而不是buf。

我在图中的04EEECA8地址设置硬件写入断点,然后重新发送消息,看断下之后填充值的代码,然后观察堆栈信息,如果没错的话,这个堆栈应该是UI线程,其中应该能找到我们刚刚发送的字符串。

当我们设置了硬件写入断点,等断点断下时观察堆栈,发现堆栈中并没有刚刚输入的字符串,观察许久发现只有一些和发送消息有关的字符串

这个时候说明我们发送的信息可能被包装起来了,因为程序会将我们的字符串放在结构体中或是某些数据结构中进行传递,只是查看堆栈可能看不到,需要查看堆栈中看起来像地址的值的内容,才可能找到。
3.3 使用x64dbg定位关键函数
我们刚刚在分析堆栈时发现的字符串:”/cgi-bin/micromsg-bin/newsendmsg” 看起来像是发生信息时信息的类型字符串。我们可以使用x64dbg查看模块wechatwin.dll中的所有和newsendmsg字符串,在其上所有相关字符串设置断点,然后再次发消息测试。

以上的动图可以看到,我们通过搜索newsendmsg字符串,定位到一处代码,设置断点后,再次发送消息,可以在堆栈中找到我们发送的内容。只要找到内容,其实离成功就不远了。在堆栈中我们去寻找和内容有关的调用CALL,需要由下而上一一查看调用CALL的参数,分析之后,可以发现有一个CALL的调用参数非常适合我们的需求。其有5个参数,如下图:

上图中的调用call 0x0F7F10C0应该就是发消息的代码,看起来非常幸运。当我们查看call内部的时候发现有大量的混淆代码,貌似这个函数被VM过了。查看wechatwin.dll模块的区段果然有有一个VMP的区段。不管怎么样,函数是定位到了,下一步就是调用函数了。
3.4 使用x64dbg分析关键函数的参数
定位到关键函数之后,观察函数的参数,发现有5个参数。
对每一个参数进行清除测试,即调试过程中分别将每一个参数清除,然后运行程序,发现参数4和参数5,可以没有值,而参数1、参数2、参数3必须有值,根据内容可知参数2是微信用户名,参数3是要发送的内容。而参数1看起来并没有什么含义,经过测试发现,其实这是一个传出缓冲区,其中存储的是加密的数据信息,即我们发送信息的加密版本,由此也可知,0x0F7F10C0函数被VM的理由是其中有加密信息的代码,即微信的私有加密通信协议。

不管怎么样,参数现在基本定了,剩下的就是只要能调用这个函数,其实就可以最初的设想了。
4.使用C++编写测试代码
代码使用的是一个MFC的DLL来完成的,我们只需注入到微信中,执行我们的代码就可以了。我们可以根据参数编写如下代码:
wchar_t* pUser1 = L"filehelper";
wchar_t* pContent1 = L"hello 15pb";
wchar_t* pUser = (wchar_t*)&pUser1;
wchar_t* pPass = (wchar_t*)&pContent1;
char buf[0x3d4] = { 0 }; // 传出buf
_asm {
push 1 // 参数5
push 0 // 参数4
push pPass // 参数3:发送的内容
push pUser // 参数2:用户名
lea eax, buf
push eax // 参数1:传出buf
mov eax, 0x0F7F10C0
call eax
}
使用上面代码会发现程序会出现异常,而出现异常的地方中,是在访问字符串指向的结构里,上面的代码微信用户名只是一个字符串指针,其他并没有,而观察原本调用时传递的参数可以发现,这是一个字符串结构体,其除了字符串指针之外还有字符串的长度,缓冲区最大长度等等。所以我们需要将整个结构都定义出来,然后测试,耐心排查直到测试完成。这个过程需要不停的修改我们定义的字符串结构体才行,或者分析代码中所有的引用点反推出字符串的结构。因此需要大量的时间才能最终完成。
这里注意一下,在测试的过程中,总结下来有两个需要注意的问题。第一,参数2和参数3都是二级指针且参数2和参数3是一个字符串结构体而非就一个指针,第二,参数1是传出参数。这三个参数传对,就不会有问题了。
经过测试以及对比内存中字符串周围的信息,最后定义的字符串数据结构如下:
struct WXString {
int num;
wchar_t* pString;
int nLen;
int nMaxLen;
int n1;
int n2;
int n3;
int n4;
WXString(wchar_t* pStr) {
int len = wcslen(pStr);
pString = new wchar_t[len + 1];
memset(pString, 0, len * 2 + 2);
memcpy(pString, pStr, len * 2);
nLen = len;
nMaxLen = len + 2;
n1 = 0;
n2 = 0;
n3 = 0;
n4 = 0;
}
~WXString() {
if (pString)
delete pString;
}
};
而最后执行的代码:
WXString szUser(L"filehelper");
WXString szContent(L"hello 15pb");
char* pAddr = (char*)&szContent + 0x14;
char* pUser = (char*)&szUser.pString;
char* pPass = (char*)&szContent.pString;
char buf[0x3d4] = { 0 };
_asm {
push 1
push 0
push pPass
push pUser
lea eax, buf
push eax
mov eax, 0xF7F10c0
call eax
}
5. 测试结果
我们可以使用x64dbg的插件Scylla完成注入完成,为了测试方便,我们注入之后会显示一个对话框,点击对话框中的按钮测试即可,执行我们上面的关键代码:

6. 总结
在分析微信的发送消息的函数过程中,我们使用x64dbg的功能有软件断点、硬件写入断点、查找字符串、插件注入等等功能,而且在分析时用到了堆栈分析,找数据时会对数据窗口各种切换。总体来说想要从源头一点一点实现本节的功能还是比较复杂的,祝大家好运!
使用x64dbg分析微信聊天函数并实现发信息的更多相关文章
- 微信聊天测试脚本 wx_sample.php
<?php </FuncFlag> </xml>); curl_setopt($ch, CURLO ...
- 关于微信聊天与朋友圈如何快速切换 Mark
用微信时,你是否遇到这样的情况.你正刷着朋友圈,享受着各种鸡汤,这时候,你收到一条微信,一看是女王大人,不得不回.你诚恳的回了一条,等了二十秒不见有什么回应,于是就退了出来,进入朋友圈找到那篇没看完的 ...
- Android几行代码实现实时监听微信聊天
实现效果: 实时监听当前聊天页面的最新一条消息,如图: 实现原理: 同样是利用AccessibilityService辅助服务,关于这个服务类还不了解的同学可以先看下我上一篇关于 ...
- iOS 即时通讯 + 仿微信聊天框架 + 源码
这些你造吗? 即时通讯(IM),在IOS这片江湖里面已经算是一个老者了,我这小旋风也是在很早以前巡山的时候,就知道有即时通讯这个妖怪,以前也多多少少接触过一些,在造APP的时候用过,哎呀,说着说着就感 ...
- 【Python撩妹合集】微信聊天机器人,推送天气早报、睡前故事、精美图片分享
福利时间,福利时间,福利时间 如果你还在为不知道怎么撩妹而烦恼,不知道怎么勾搭小仙女而困惑,又或者不知道怎么讨女朋友欢心而长吁短叹. 那么不要犹豫徘徊,往下看.接下来我会分享怎么使用 Python 实 ...
- Android几行代码实现监听微信聊天
原创作品,转载请注明出处,尊重别人的劳动果实. 2017.2.7更新: *现在适配微信版本更加容易了,只需要替换一个Recourse-ID即可 *可以知道对方发的是小视频还是语音,并获取秒数. *可以 ...
- 查看图片插件--Viewer(类似于qq和微信聊天 的查看图片)
Viewer的github地址:https://github.com/fengyuanchen/viewer 下载该插件(在文件夹dist里面) 具有参考价值的几个网站:http://www.dow ...
- SAP成都研究院飞机哥: SAP C4C中国本地化之微信聊天机器人的集成
今天的文章仍然来自Jerry的老同事,SAP成都研究院的张航(Zhang Harry).关于他的背景介绍,请参考张航之前的文章:SAP成都研究院飞机哥:程序猿和飞机的不解之缘.下面是他的正文. 大家好 ...
- uni-app聊天室|vue+uniapp仿微信聊天实例|uniapp仿微信App界面
一.介绍 运用UniApp+Vue+Vuex+swiper+uniPop等技术开发的仿微信原生App聊天室|仿微信聊天界面实例项目uniapp-chatroom,实现了发送图文消息.表情(gif图), ...
随机推荐
- CSS3 渐变(Gradients)
参考: http://www.runoob.com/css3/css3-gradients.html CSS3 渐变(gradients)可以让你在两个或多个指定的颜色之间显示平稳的过渡. 以前,你必 ...
- CTP多点触摸协议【转】
转自:http://blog.chinaunix.net/uid-26403844-id-5063920.html linux kernel 2.6.30开始对多点触摸支持,最近高通要求所有CTP器件 ...
- Pyhton-Requests之接口测试
非常感谢[百人计划]五娃的分享!下面是整理的笔记: 一.环境准备: Pyhton 2.x或者Pyhton 3.x.Requests库.(我安装的版本是Pyhton 3.4) 安装 Pyhton 3.x ...
- js中如何对时间进行设置
js中如何对时间进行设置 Js获取当前日期时间及其它操作var myDate = new Date();myDate.getYear(); //获取当前年份(2位)myDate.getF ...
- 《JavaScript模式》精要
P25. 如何避免eval()定义全局变量? 如: var jsstring = "var un = 1;"; eval(jsstring); console.log(typeof ...
- 【SQL】视图
一.虚拟视图 由create table定义的表:以物理形式存在,实际存储在数据库中 视图:虚拟的,并不是一个真正存在的表 1.视图定义 CREATE VIEW <视图名> AS < ...
- rest_framework 权限流程
权限流程 权限流程与认证流程非常相似,只是后续操作稍有不同 当用户访问是 首先执行dispatch函数,当执行当第二部时: #2.处理版本信息 处理认证信息 处理权限信息 对用户的访问频率进行限制 s ...
- Python 进阶 之 lambda 匿名函数
lambda 是个匿名函数,通常用于简单判断或者处理,例如判断一个数的奇偶性,过滤字符串,逻辑运算等等. lambda表达式: >>>lambda x:x*x >>> ...
- 关于 log4j.additivity的说明
log4j.additivity是 子Logger 是否继承 父Logger 的 输出源(appender) 的标志位.具体说,默认情况下 子Logger 会继承 父Logger 的appender, ...
- 【互动问答分享】第11期决胜云计算大数据时代Spark亚太研究院公益大讲堂
Q1:docker成熟度如何? Docker是2013年和2014年最火爆的云计算开源项目: Baidu公司是中国使用Docker最为深入和最大规模的公司,线上稳定运行数十万个Docker容器,目前已 ...