文章目录

  • 定位微信的消息接收函数
    • 定位消息接收函数的相关思路
    • 定位消息内容的地址
    • 分析接收消息函数
      • 好友消息
      • 群消息
    • 总结
    • 代码实现
  • 定位微信的消息发送函数
    • 定位消息发送函数的相关思路
    • 过滤当前聊天窗口的微信ID
    • 定位当前聊天窗口的ID
    • 定位发送消息的函数
    • 分析发送消息的函数
      • 普通消息
      • 艾特某人消息
    • 总结
    • 代码实现
  • 最终效果

定位微信的消息接收函数

我们先来定位一下消息接收函数,这对我们后面分析消息发送函数会有所帮助

定位消息接收函数的相关思路

与接收消息函数最直接相关的东西肯定是消息本身,所以消息本身的内容就是我们的切入点。我们可以首先找到存放消息内容的地址,然后对地址下断,通过栈回溯最终定位到接收消息的函数

定位消息内容的地址

首先用另外一个微信给自己发一条消息,在不点开消息的状态下用CE搜索消息内容

然后再发送一条消息

此时有效结果只剩下3个,把这三个地址加入到下方地址栏,右键->更改记录->类型

将显示范围调大

其中有一个是最原始的未经处理的消息,也是显示的最全的那一条,剩下的两条是经过处理的。我们需要中间那个未经任何处理的消息

### 定位接收消息函数的地址

既然消息内容的地址找到了,那么接下来就通过这个内容来找到接收消息的函数

在OD中找到这个地址,下内存写入断点。为什么是写入不是访问?因为这个是最原始的的消息,要想对这条消息进行处理就必须改写当前的这条消息,所以在这个位置下内存写入断点,当客户端对这条原始消息进行处理时,断点就会断下。

此时,再次发送一条消息,程序断下,删除内存写入断点,这个时候堆栈的返回地址里面一定有一个函数是用来接收消息的。我们点击K查看调用堆栈。

经过排查确认是这个call,大家可以根据我图中的函数特征直接找到这个call。我们在这个函数下断点,让程序再次断下,分析附近的代码。

分析接收消息函数

好友消息

此时我们点击查看堆栈中esp寄存器的值,数据窗口跟随

此时[esp+0x40]的位置是发送者的微信ID,[esp+0x68]的位置是消息内容(通过这个call我们还可以拿到文件助手的ID是filehelper,这对后面分析消息发送会有用,大家可以去试验一下)

[esp+0x114]的位置是0,[esp+0x128]的位置是一串未知数据。

群消息

然后我们再发送一条群消息,看看有什么区别

此时[esp+0x40]的位置是群ID,[esp+0x68]的位置是消息内容

[esp+0x114]的地址不再是零,而是消息发送者的ID,[esp+0x128]的位置依旧是一串未知数据。大家可以用同样的方式分析处图片和表情在内存中的表现形式。

那么我们只要记录下这个call的地址+偏移,然后写一个dll注入到微信进程空间中,HOOK这个函数,就能拦截所有的消息,并显示到我们的程序中。

总结

总结一下思路,寻找切入点->找地址->下断->栈回溯分析。就是这么简单粗暴

代码实现

注入之后接收消息的代码如下:

void RecieveMsg()
{wstring receivedMessage = L"";BOOL isFriendMsg = FALSE;//[[esp]]//信息块位置DWORD** msgAddress = (DWORD * *)r_esp;//消息类型[[esp]]+0x30//[01文字] [03图片] [31转账XML信息] [22语音消息] [02B视频信息]//感谢:.順唭_自嘫ɑ、unravel提供类型消息。DWORD msgType = *((DWORD*)(**msgAddress + 0x30));receivedMessage.append(L"消息类型:");switch (msgType){case 0x01:receivedMessage.append(L"文字 ");break;case 0x03:receivedMessage.append(L"图片 ");break;case 0x22:receivedMessage.append(L"语音 ");break;case 0x25:receivedMessage.append(L"好友确认 ");break;case 0x28:receivedMessage.append(L"POSSIBLEFRIEND_MSG ");break;case 0x2A:receivedMessage.append(L"名片 ");break;case 0x2B:receivedMessage.append(L"视频 ");break;case 0x2F://石头剪刀布receivedMessage.append(L"表情 ");break;case 0x30:receivedMessage.append(L"位置 ");break;case 0x31://共享实时位置//文件//转账//链接receivedMessage.append(L"共享实时位置、文件、转账、链接 ");break;case 0x32:receivedMessage.append(L"VOIPMSG ");break;case 0x33:receivedMessage.append(L"微信初始化 ");break;case 0x34:receivedMessage.append(L"VOIPNOTIFY ");break;case 0x35:receivedMessage.append(L"VOIPINVITE ");break;case 0x3E:receivedMessage.append(L"小视频 ");break;case 0x270F:receivedMessage.append(L"SYSNOTICE ");break;case 0x2710://系统消息//红包receivedMessage.append(L"红包、系统消息 ");break;case 0x2712:receivedMessage.append(L"撤回消息 ");break;default:break;}receivedMessage.append(L"\r\n");//dc [[[esp]] + 0x114]//判断是群消息还是好友消息//相关信息wstring msgSource2 = L"<msgsource />\n";wstring msgSource = L"";msgSource.append(GetMsgByAddress(**msgAddress + 0x168));if (msgSource.length() <= msgSource2.length()){receivedMessage.append(L"收到好友消息:\r\n");isFriendMsg = TRUE;}else{receivedMessage.append(L"收到群消息:\r\n");isFriendMsg = FALSE;}//好友消息if (isFriendMsg == TRUE){receivedMessage.append(L"好友wxid:\r\n").append(GetMsgByAddress(**msgAddress + 0x40)).append(L"\r\n\r\n");}else{receivedMessage.append(L"群号:\r\n").append(GetMsgByAddress(**msgAddress + 0x40)).append(L"\r\n\r\n");receivedMessage.append(L"消息发送者:\r\n").append(GetMsgByAddress(**msgAddress + 0x114)).append(L"\r\n\r\n");receivedMessage.append(L"相关信息:\r\n");receivedMessage += msgSource;receivedMessage.append(L"\r\n\r\n");}receivedMessage.append(L"消息内容:\r\n").append(GetMsgByAddress(**msgAddress + 0x68)).append(L"\r\n\r\n");//文本框输出信息USES_CONVERSION;SetWindowText(GetDlgItem(hWinDlg, IDC_MSG), W2A(receivedMessage.c_str()));
}

定位微信的消息发送函数

定位消息发送函数的相关思路

一个发消息的函数,至少需要两个参数。第一个是发送给谁,第二个是发送的内容,所以我们可以从参数入手,然后通过栈回溯的方式找到发送消息的call。

至于突破口我们可以从发送的消息内容和消息的接收者的微信ID入手,比如文件传输助手的微信ID是filehelper,这个可以在接收消息的call中拿到。以这个微信ID为突破口会比从文本来追溯方便。

过滤当前聊天窗口的微信ID

首先将当前聊天窗口设置为文件传输助手,搜索filehelper

除了文件传输助手,我们还知道个人的微信ID都是以wxid_开头的,所以将窗口切换到微信好友,搜索wxid_

接着我们选中所有地址,加入到下方地址栏

然后选择全部地址右键->更改记录->类型

将长度修改为50以显示更多的内容

此时你会看到微信好友的ID,记录下这个ID,待会有用

再将窗口切回文件助手,下方地址栏的ID会发生变化,将数值不是filehelper的全部剔除掉。剩下的地址中的某一个是当前窗口的微信ID,它会随着你当前微信窗口ID进行变换。

定位当前聊天窗口的ID

这个当前聊天窗口的ID到底有什么作用呢?我们来测试一下

选中所有地址,右键->更改记录->数值,将当前聊天窗口的ID改为filehelper,然后在当前好友的聊天窗口发送一条消息,你会发现此时消息发到了文件传输助手

当前聊天窗口的ID是谁 谁就会接收到这条消息,利用这个特性我们来找出那个唯一的当前窗口ID

选中一半地址,将其更改为filehelper,然后在当前窗口发送消息。如果消息发给了filehelper,那么选中的地址里面就有真正的当前聊天窗口的ID。重复这个步骤,可以找到真正的当前窗口ID

定位发送消息的函数

接着载入OD,在找到的当前窗口ID的地址中下一个内存访问断点。为什么是内存访问断点而不是内存写入呢?因为当前微信窗口的ID肯定会被发送消息的当作参数传入到堆栈中,所以必定会访问这个ID,而不是写入ID。

给好友发送一条消息,点击发送,内存访问断点断下。

此时eax指向当前窗口ID,接着删除内存访问断点。点击K查看调用堆栈,在堆栈的返回地址中逐个排查每一个函数,这个函数必须有两个以上的参数,其中一个参数是消息内容,另外一个参数是消息ID

经过排查,可以在调用堆栈的第二层找到一个疑似发消息的call。在这个地方下断点,让程序断下,分析附近代码

分析发送消息的函数

普通消息

此时edx指向微信ID,[edx+4]保存的是微信ID的长度

ebx指向消息内容,[ebx+4]保存的是消息内容的长度。那么这个很有可能就是我们要找的发送消息的call。

找到了发送消息的函数,那么怎么验证呢?利用微信ID。将edx指向的微信ID的地址和我们之前在CE中找到的当前窗口的微信ID对比,你会发现两个地址是一样的。

改变这个地址的微信ID和内容,就能直接改变消息的接收者和内容,这个刚才我们已经实验过了。再结合这个函数传入的参数有当前消息的内容,就可以确定这个call就是微信发送消息的函数。

艾特某人消息

除了以普通文本的方式发送消息以外,还可以以艾特某人的方式发送消息。那么当发送的消息是艾特某人的时候,这个函数和发送普通文本消息有什么区别呢?区别就在于eax寄存器的值

先发送一条普通消息程序断下

此时eax的值为0,然后再发送一条艾特某人的消息

此时eax是有值的,数据窗口跟随,看看这个14704C40的地址保存的是什么内容

里面的被艾特的人的微信ID,普通消息与艾特消息的区别就在于eax是否保存了被艾特人的微信ID。大家可以用同样的方式分析处图片和表情在内存中的表现形式。

接下来我们只要记录下当前发送消息函数的地址+偏移,就能写一个dll注入到微信进程空间中,直接调用发送消息的函数,就能实现用自己写的程序给任何人发送消息。

总结

总结一下思路,寻找切入点->找地址->下断->栈回溯分析。跟接收消息的步骤是一致的。找call的关键在于你能不能找到一个好的切入点,并且利用切入点与call之间的关系。

代码实现

调用发送消息的函数代码如下:

void SendTextMessage(wchar_t* wxid, wchar_t* msg)
{//拿到发送消息的call的地址DWORD dwSendCallAddr = GetWeChatWinAddr() + 0x2EB4E0;//微信ID/群IDwxMsg id = {0};id.pMsg = wxid;id.msgLen = wcslen(wxid);id.buffLen = wcslen(wxid)*2;//消息内容wxMsg text = { 0 };text.pMsg = msg;text.msgLen = wcslen(msg);text.buffLen = wcslen(msg)*2;//取出微信ID和消息的地址char* pWxid = (char*)&id.pMsg;char* pWxmsg = (char*)&text.pMsg;char buff[0x81C] = { 0 };//调用微信发送消息call__asm {mov edx, pWxid;push 1;mov eax, 0;push eax;mov ebx, pWxmsg;push ebx;lea ecx, buff;call dwSendCallAddr;add esp, 0xC;}
}

最终效果

发送消息

接收消息

目前微信机器人的成品已经发布,需要代码请移步Github。还请亲们帮忙点个star

https://github.com/TonyChen56/WeChatRobot

PC微信逆向:发送与接收消息的分析与代码实现相关推荐

  1. PC微信逆向:分析微信发送文件call

    文章目录 发送文件call的结构体参数分析 组合数据call的分析 定位发送文件的call 接上一篇文章,PCXX逆向:发送与接收消息的分析与代码实现:https://blog.csdn.net/qq ...

  2. PC微信逆向:分析@群成员call

    文章目录 发送消息函数的分析 定位组装的数据格式 追踪ebx+0x14 追踪esi+0x4 追踪eax 追踪ebp-0x24 分析组装数据的call 测试组装数据的call是否有效 接上一篇文章,PC ...

  3. 【译】 WebSocket 协议第六章——发送与接收消息(Sending and Receiving Data)

    概述 本文为 WebSocket 协议的第六章,本文翻译的主要内容为 WebSocket 消息发送与接收相关内容. 发送与接收消息(协议正文) 6.1 发送数据 为了通过 WebSocket 连接发送 ...

  4. PC微信逆向--调用sqlite3_exec执行SQL

    文章目录 写在前面 回顾 sqlite3_exec 回调函数 函数指针 编写代码 注入的DLL 注入程序 输出结果 写在后面 写在前面 上一篇文章,实现了定位保存微信数据库句柄的容器和微信内部的sql ...

  5. PC微信逆向:分析发送xml名片call

    文章目录 微信版本 定位发送xml名片call 发送xml名片call的切入点 定位选择联系人的call 定位发送xml名片的call 定位接收者的微信ID 定位发送xml名片的call 验证发送xm ...

  6. PC微信逆向--看看哪些好友删除了自己

    文章目录 写在前面 微信版本 资料 Duilib界面 定位发送CALL 具体原理 关键代码 写在后面 写在前面 搞微信逆向也有一段时间了,实现了发送文本.图片.文件.名片.xml文章消息,以及获取好友 ...

  7. PC微信逆向:实现自动保存加密的聊天图片

    文章目录 前言 基于保存语音的相关延伸 图片处理的相关流程 自动保存图片相关思路 实战保存聊天图片 对保存图片call的相关分析 代码实现保存聊天图片 实际效果 项目地址 前言 本文基于anhkgg大 ...

  8. pc微信逆向最新3.9.2.23版本

    最近想做个微信机器人,就研究了pc端的微信逆向,发现网上开源的项目挺多的,但是都是一些老版本的,3.7版本的基本上很少,3.8的更少了,现在3.9版本开源的很少.不过还是发现了两个开源项目,特分享备忘 ...

  9. 微信小程序接受服务器发过来的消息,微信小程序API 接收消息和事件

    接收消息和事件 当用户在客服会话发送消息.或由某些特定的用户操作引发事件推送时,微信服务器会将消息或事件的数据包发送到开发者填写的 URL,如果使用的是云开发,则可以推送到指定的云函数(详情请参考消息 ...

最新文章

  1. 卸载Office 2007 Beta2后,Outlook 2003无法启动的解决方法
  2. 数据全景洞察概念简介
  3. 卷积神经网络中的池化是什么意思
  4. 白居易最动人的10句诗
  5. 阿里撬得动“印度版”抖音吗?
  6. java EE :GenericServlet 抽象类、ServletConfig 接口
  7. LIS最长上升子序列详解+模板(dp和二分做法)
  8. mysql lock table阻塞读_MySQL的lock tables和unlock tables的用法【数据库锁表】
  9. icem网格数和节点数_icem如何查看网格数量
  10. ESP8266AT指令集学习笔记
  11. 异或(另类斐波那契数列题)
  12. Matlab处理阻尼振动数据,MATLAB计算方法和技巧6_2阻尼振动
  13. FAT学习笔记(四)——Dir Entry
  14. 你不知道的在线免费caj转Word
  15. 鹅厂打响互联网大厂校招第一枪!
  16. 安利这几个网站给需要的你
  17. python热更新原理_Python功能点实现:数据热更新
  18. java aes ecb_java使用AES加密解密 AES-128-ECB加密
  19. 55 非谓语动词语法
  20. 局域网访问提示无法访问检查拼写_无法访问局域网共享(win7访问xp):请检查名称的拼写.否则网络可能有问题. 错误代码0x80004005...

热门文章

  1. 禁用系统的Ctrl+Alt+Left/Right(方向键)
  2. 欧美项目的文字乱码问题
  3. 扫描件如何转换成word文档?扫描件转可编辑文本技巧
  4. Multisim基础 交流电源的三个参数的意义
  5. 关于原型图的深入理解
  6. womos D1 mini arduino IDE
  7. Linux镜像下载和网络配置配置
  8. 旅游消费券发放,驴妈妈造福旅游爱好者
  9. 2022年10月 亲测可用的rtsp流测试地址
  10. POJ_2031 Building a Space Station