V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
anhkgg
V2EX  ›  微信

微信 PC 端技术研究-消息防撤销(提供工具)

  •  
  •   anhkgg · 2018-12-06 15:03:29 +08:00 · 2239 次点击
    这是一个创建于 1968 天前的主题,其中的信息可能已经有所发展或是发生改变。

    微信 PC 端技术研究-消息防撤销
    by anhkgg
    2018 年 11 月 30 日

    0x1. 写在前面

    不知道大家有没有遇到过这种情况,微信收到消息,但是没有及时查看,然后闲暇时去看的时候,消息被撤销了,撤销了!

    那时肯定是无比无语,挠心挠肺,究竟发了什么?

    有没有一种神器可以防消息撤销呢,有的!其实移动端和 mac 上已经有人做了相关的插件,但是 PC 端貌似没人来啃这块骨头。

    当然也可能是我没找到,不过不管怎样,对我来说就是没有。

    既然如此,小生来!

    0x2. 技术分析

    先理一下思路:

    1.对方发送消息之后,我收到消息并在消息窗口显示
    2.然后对方点击菜单选择撤销
    3.我会收到发来的撤销通知,然后删除消息窗口显示的消息

    所以分析方向就基本定为两个方向了:

    1.一个是通过分析网络消息找到撤销消息,然后拦截该消息阻止消息被撤销
    2.另一个是找到撤销消息的界面操作,patch 掉这个撤销消息的操作即可

    开始之前,先了解一下微信主要模块都实现什么功能。

    |模块|功能| |----|----| |WeChat.exe|主程序,初始化操作,加载 WeChatWin.dll| |WeChatWin.dll|主要功能模块,包括界面、网络、功能| |wechatresource.dll|保存资源的模块,包括界面资源|

    主要分析目标就是 WeChatWin.dll ,其实很早之前就想分析这个东西了,但是那时候的老版本 vmp 壳加的更严重(映像中是,无法考证),所以搁置很久。

    当前我分析的版本应该是最新的2.6.5.38,目前来看加壳程度还行,基本都是比较好分析的代码,没有经过加壳处理,不过听说核心代码还是处理过的。

    1. 界面入手

    首先试试从界面入手,都知道微信界面使用 duilib 实现的,所以可以从它的某些特征入手分析,比如字符串click等,可以快速找到功能函数。

    想的是通过click找到整个窗口响应函数,然后再分析找到撤销操作的代码位置。

    确实很快就看到了窗口响应函数,不过大概有 119 个相关函数,所以无奈放弃。

    换一个方向,通过菜单入手,搜索menu找到menuCmdDeletemenuCmdRevoke等字符串,menuCmdRevoke就是撤销菜单对应的名字。有 29 个相关函数,还行。结合调试,尝试了几个函数,果然找到了删除、撤销对应的响应函数。然后想通过删除菜单来找到删除界面消息的代码,而被撤销消息其实也是删除界面消息,不过折腾了一圈未果。

    2. 网络入手

    通过recv回溯到接收网络消息的函数中,40 个,有点多。找了个 tcp 抓包工具,想抓到撤销消息的调用堆栈,结果一直被其他消息干扰,无果。

    3. 取巧

    函数太多,分析很费实践,想看看有没有其他路可以走。在字符串中搜索revoke发现很多看起来有用的调试信息,不过也有 79 条之多。然后通过筛选和调试确认,找到了On RevokeMsg svrId : %d,然后回溯到撤销消息处理的函数中。

    if ( sub_10247BF0((wchar_t *)v258, (int)v259, (int)v260, v261) )
    {                             // 撤销消息
    *(_OWORD *)&v259 = xmmword_10E6A278;
    v257 = xmmword_10E6A278;
    v256 = xmmword_10E6A278;
    v255 = xmmword_10E6A278;
    *(_OWORD *)&v251 = xmmword_10E6A278;
    sub_1007E090(&v247, v353, SHIDWORD(v353));
    f_log_10471580(
      (int)"02_manager\\SyncMgr.cpp",
      2,
      1357,
      (int)"SyncMgr::doAddMsg",
      (int)"SyncMgr",
      "On RevokeMsg svrId : %d",
    

    经过调试发现sub_10247BF0返回 1 则进入撤销消息处理中,消息被撤销,跳过此段代码,消息不会被撤销,所以 patch 掉sub_10247BF0这个函数的返回值使其一直为 0 即可完成防撤销的功能。

    当然也不能太随意了,还是看看这个函数大概做了些什么处理吧。关键参数第一个,调试中发现值如下:

    <sysmsg type="revokemsg">
        <revokemsg>
            <session>wxid_0811111140112</session>
            <msgid>1111000048</msgid>
            <newmsgid>11411701182813217</newmsgid>
            <replacemsg><![CDATA["xxx" 撤回了一条消息]]></replacemsg>
        </revokemsg>
    </sysmsg>
    

    sub_10247BF0解析发现type="revokemsg"即判断为撤销消息操作,返回 1,很明了。

    小结:此次分析运气较好,通过 revoke 找到关键代码,少花了很多时间,其实通过网络方向堆栈筛选确认应该也是可以找到这段代码的,但是通过结果去看,发现有近 10 层调用栈,肯定会花成倍的时间才能找到关键代码。

    0x3. 实现

    分析是为了最后能够用起来,所以用上一篇文章《一种通用 Dll 劫持技术》写了一个简单的包含 patch 代码(没有用 hook )的 dll 模块,劫持微信的 WeChatResource.dll 来完成加载。

    关键代码如下所示,patch 了sub_10247BF0返回值所在代码,让其 eax 永远为 0。

    bool FakeRevokeMsg()
    {
    	if (!IsSupportedWxVersion()) {
    		return false;
    	}
    
    	//33 C0                xor eax,eax 
    	BYTE code[] = { 0x33, 0xc0, 0x90 };
    	HMODULE hMod = GetModuleHandle(WECHATWINDLL);
    	DWORD offset = 0x247EF1;//返回值处
    	if (!hMod) {
    		return false;
    	}
    
    	PVOID addr = (BYTE*)hMod + offset;
    	Patch(addr, 3, code);
    
    	return true;
    }
    

    最后惯例,放上 github 地址:https://github.com/anhkgg/multi_wechat_pc

    网盘地址直接下载编译好的工具,不过要去 github 给我点星星哦

    链接: https://pan.baidu.com/s/1S4UdcPOORdmzE69TzD-eRA 提取码: ry4g

    广告:欢迎关注公众号汉客儿和 QQ 群(753894145),一起交流学习

    2 条回复    2018-12-07 21:23:35 +08:00
    iX
        1
    iX  
       2018-12-07 20:45:39 +08:00
    然而确实多年前就有了。。
    http://www.423down.com/8718.html
    anhkgg
        2
    anhkgg  
    OP
       2018-12-07 21:23:35 +08:00
    @iX 很赞,不过这种非开源软件还是谨慎使用吧
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   926 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 21:23 · PVG 05:23 · LAX 14:23 · JFK 17:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.