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分析微信聊天函数并实现发信息的更多相关文章

  1. 微信聊天测试脚本 wx_sample.php

    <?php </FuncFlag>                             </xml>);         curl_setopt($ch, CURLO ...

  2. 关于微信聊天与朋友圈如何快速切换 Mark

    用微信时,你是否遇到这样的情况.你正刷着朋友圈,享受着各种鸡汤,这时候,你收到一条微信,一看是女王大人,不得不回.你诚恳的回了一条,等了二十秒不见有什么回应,于是就退了出来,进入朋友圈找到那篇没看完的 ...

  3. Android几行代码实现实时监听微信聊天

    实现效果: 实时监听当前聊天页面的最新一条消息,如图:            实现原理: 同样是利用AccessibilityService辅助服务,关于这个服务类还不了解的同学可以先看下我上一篇关于 ...

  4. iOS 即时通讯 + 仿微信聊天框架 + 源码

    这些你造吗? 即时通讯(IM),在IOS这片江湖里面已经算是一个老者了,我这小旋风也是在很早以前巡山的时候,就知道有即时通讯这个妖怪,以前也多多少少接触过一些,在造APP的时候用过,哎呀,说着说着就感 ...

  5. 【Python撩妹合集】微信聊天机器人,推送天气早报、睡前故事、精美图片分享

    福利时间,福利时间,福利时间 如果你还在为不知道怎么撩妹而烦恼,不知道怎么勾搭小仙女而困惑,又或者不知道怎么讨女朋友欢心而长吁短叹. 那么不要犹豫徘徊,往下看.接下来我会分享怎么使用 Python 实 ...

  6. Android几行代码实现监听微信聊天

    原创作品,转载请注明出处,尊重别人的劳动果实. 2017.2.7更新: *现在适配微信版本更加容易了,只需要替换一个Recourse-ID即可 *可以知道对方发的是小视频还是语音,并获取秒数. *可以 ...

  7. 查看图片插件--Viewer(类似于qq和微信聊天 的查看图片)

    Viewer的github地址:https://github.com/fengyuanchen/viewer  下载该插件(在文件夹dist里面) 具有参考价值的几个网站:http://www.dow ...

  8. SAP成都研究院飞机哥: SAP C4C中国本地化之微信聊天机器人的集成

    今天的文章仍然来自Jerry的老同事,SAP成都研究院的张航(Zhang Harry).关于他的背景介绍,请参考张航之前的文章:SAP成都研究院飞机哥:程序猿和飞机的不解之缘.下面是他的正文. 大家好 ...

  9. uni-app聊天室|vue+uniapp仿微信聊天实例|uniapp仿微信App界面

    一.介绍 运用UniApp+Vue+Vuex+swiper+uniPop等技术开发的仿微信原生App聊天室|仿微信聊天界面实例项目uniapp-chatroom,实现了发送图文消息.表情(gif图), ...

随机推荐

  1. BZOJ 100题纪念

  2. 安全测试===Mysql 注入技巧学习 MySQL注入技巧(1)

    默认存在的数据库: mysql 需要root权限读取 information_schema 在5以上的版本中存在 测试是否存在注入方法 假:表示查询是错误的 (MySQL 报错/返回页面与原来不同) ...

  3. C++实现高斯滤波器

    在matlab中,我们经常用到高斯滤波器,生成滤波器一般都是这样的函数psf =   fspecial('gauss', GaussSize, sigma),但是在vs2010中用到的高斯滤波器不能自 ...

  4. shell 通过ANSI转换颜色

    格式: echo -e "\033[字背景颜色;字体颜色m字符串\033[控制码" 如果单纯显示字体颜色可以固定控制码位0m. 格式: echo -e "\033[字背景 ...

  5. javascript中a标签把href属性设置为“javascript:void(0)”还是会打开空白页面的问题

    在项目中有个位置的点击a标签这里要加一个权限判断,但是之前使用的是js动态添加a标签,href的属性值是一个url,但是我要做权限判断之后,我的url就不能设置在href属性中了,这样的话我可以在a标 ...

  6. hdu 3768(spfa+暴力)

    Shopping Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  7. Java多态机制和继承中重写重载

    关于Java中多态机制 http://www.cnblogs.com/chenssy/p/3372798.html 这篇博文讲的很透彻 大体意思是 多态定义: 多态就是指程序中定义的引用变量所指向的具 ...

  8. 【hdoj_1049】Climbing Worm

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1049 以 上升-下降 一次为一个周期,一个周期时间为2分钟,每个周期上升距离为(u-d).先只考虑上升,再 ...

  9. 浅谈C#多线程与UI响应

    www.educity.cn     发布者:shenywww                    来源:网络转载                     发布日期:2014年10月06日      ...

  10. MySQL 8.0.13安装教程(windows 64位) (转)

    官先去网下载点击MySQL的下载 下载完成后解压 解压完是这个样子 配置初始化的my.ini的文件解压后的目录并没有my.ini文件,没关系可以自行创建.在安装根目录下添加my.ini(新建文本文件, ...