<dd id="yzu3f"><tr id="yzu3f"><kbd id="yzu3f"></kbd></tr></dd>

              安基网 首页 资讯 安全报 查看内容

              微信PC端技术研究:截获语音消息

              2019-2-25 17:28| 投稿: lofor |来自: 互联网


              免责声明:本站系公益性非盈利IT技术普及网,本文由投稿者转载自互联网的公开文章,文末均已注明出处,其内容和?#35745;?#29256;权归原网站或作者所有,文中所述不代表本站观点,若有无意侵权或转载不当之处请从网站右下角联系我们处理,谢谢合作!

              摘要: 最近又学习了某位大佬用CE的方法,大佬的一句话有点醍醐灌顶,然后有了新的感觉,然后开始尝试实践这篇文章。 自己总结一下CE用法的核心思路:通过各种技巧搜索找到内存中关键数据,然后结合动态调试找到操作数据 ...

              0×0. 前言

              最近又学习了某位大佬用CE的方法,大佬的一句话有点醍醐灌顶,然后有了新的感觉,然后开始尝试实践这篇文章。

              自己总结一下CE用法的核心思路:通过各种技巧搜索找到内存中关键数据,然后结合动态调试找到操作数据的函数。

              0×1. 了解CE

              官网:https://www.cheatengine.org/

              看看来自百科的介绍:

              Cheat Engine是一款内存修改编辑工具 ,它允许你修改你的游戏或软件内存数据,以得到一些其他功能。它包括16进制编辑,反汇编程序,内存查找工具。与同类修改工具相比,它具有强大的反汇编功能,且自身附带了外挂制作工具,可以用它直接生成外挂。

              在我看来,CE做的最好的就是各种策略的内存搜索能力:

              1.支持准确数据(整数、字符串、十六进制、浮点数、字节数组等等)搜索,针对目标数据明确效果显著,比如金币数;

              2.支持数据范围的搜索,比如大于某个值,小于某个值等?#21462;?#27604;如想找到没有显示数值的血量数据;

              3.支持多组数据同时搜索,针对数据结构复杂的情况;

              4.支持搜索结果的多次过滤(图中框选的Next Scan),最终找到目标数据。比如血?#35838;?#30693;时,通过加血、减血多次搜索最终找到血量地址。

              说到底CE内存搜索的能力就是通过各种策略帮助你找到游戏中需要修改的数据(比如血量、分数、金币等等),然后通过内存修改能力(直接改血量)打破游戏平衡,外挂制作工具生成外挂,助你超神!

              0×2. 分析

              进入正题,本文是要拿到微信聊天的语音消息,然后dump保存下来。

              要按以前我的思路,会通过网络通信找到接受消息的函数,然后找到语音数据,看起来很简单,但是有点?#36873;?/p>

              因为函数真的很多,网络消息?#19981;?#21463;到很多干扰。

              现在用CE了,应该怎?#31383;?#21602;?

              找到关键数据

              关键数据肯定是语音消息了,但是怎么搜索呢,肯定搜语音内容不现实,所以转了弯,先看看文字消息,找到接受文字消息处理函数之后,猜测语音处理函数会相同或者在不同?#31181;А?/p>

              接着,如何搜索文字消息呢?已经收到的显示在聊天窗口的内容当然可以通过CE找到,但是没用啊,它和接受文字消息处理函数已经没关系了,流程已经处理完成了。

              那么在测试中肯定知道发送的消息内容,通过CE来搜索可以吗?

              额,我觉得不行,还没收到消息呢,内存中也没有这个文字消息,搜索不到(如果可以,请大佬指点一下)。

              能想到的是,在接受到消息某一点通过调试器断下来,然后CE搜索,这样可以,但是这个断点找不到阿,放弃。

              那怎?#31383;?#21602;?

              看到左侧聊天列表中显示的最新一条消息,有了新的思路。

              ?#30475;?#25910;到新消息后,都会在列表中显示最新消息内容(图?#26032;?#26694;指示位置、注意是unicode字符)。

              那么,先用CE(First Scan)搜索当前搜到的消息内容,找到可能的内存地址。多次接受不同消息后,Next Scan按钮搜索?#30475;?#26032;的消息内容,最终确定聊天列表中显示的最新消息内容的内存地址。

              多次刷选之后,留下两个地址,通过CE修改内容,在界面中查看是否改变,最终确?#31995;?#20108;个地址就是我们的目标,暂把该地址记录为MsgAddr。

              分析消息接收函数

              关键数据地址已经找到,下面的工作复?#21491;?#19981;复杂,就看微信是如何实现的了。

              猜测微信实现消息显示的流程是这样的:

              1.recv收到消息,组装完整包后,分发给消息处理函数;

              2.根据wxid找到要显示消息的列表项,如果不在已聊天消息列表,就新建一个项;

              3.在列表中显示消息,如果是表情显示[文字],语音显示为[语音],消息插入wxid对应消息队列,或者存入数据库。

              步骤3中肯定要写前面找到的MsgAddr内存,把最新消息显示到界面中,这个流程肯定在消息处理函数内部。

              So,通过OD对MsgAddr下内存写入断点,回溯堆栈就可以找到消息处理函数。

              具体操作如下:

              OD挂载Wechat.exe进程后,在左下角内存窗口处Ctrl+G,输入找到的MsgAddr(11A11F34)回车,定位到该数据,然后再HEX数据处,右键弹出?#35828;ィ?#36873;择断点->内存写入。

              断点设置完成后,测试发送文字消息,OD断住,代码窗口显示的就是修改MsgAddr的代码位置,如上图10CE412C处。

              Alt+K查看当前堆栈:

              调用堆栈
              地址       堆栈       函数过程 / 参数                       调用来自                      结构
              0012E068   106BD6F3   WeChatWi.10CE4110                     WeChatWi.106BD6EE             0012E064 //wcsncpy
              0012E088   106BD769   WeChatWi.106BD67E                     WeChatWi.106BD764             0012E084
              0012E09C   1011DD8B   WeChatWi.106BD753                     WeChatWi.1011DD86             0012E098
              0012E0EC   10206C67   包含WeChatWi.1011DD8B                   WeChatWi.10206C64             0012E0E8
              0012E600   1020E8F1   ? WeChatWi.10206460                   WeChatWi.1020E8EC             0012E5FC //界面操作

              看到这个调用栈是不是感觉好少,分析起来肯定简单。但,其实是OD显示的并不全,此时真的很想用windbg。

              在OD的右下角堆栈窗口,可以看到当前调用栈的参数和预览数据。F8单步(或者Alt+F8执行到返回)逐步的回溯每层堆栈。关注MsgAddr的数据是如何生成的,也就是找到数据来源,然后找到消息处理函数。

              跟踪过程不赘述(需要熟悉汇编知识),直到看到的最顶层的WeChatWi.10206460处,发现?#21069;?#25910;到的消息内容显示到聊天列表处的一个界面功能函数。

              那这里不是可以拿到消息了吗,是的,普通文字消息已经可以拿到,但是语音内容不?#23567;?/p>

              通过观察内存窗口的数据,整理WeChatWi.10206460处的关于消息参数的大致结构。

              //聊天列表框信息
              
              struct chat_list_msg {
              DWORD unk;//
              wstring wxid;//
              //wchar_t* wxid;//4
              //int len;//8
              //int maxlen;//c
              DWORD unk1;//10
              DWORD unk2;//14
              wstring name;
              //wchar_t* name;//18微信名
              //int len;//1c
              //int maxlen;//20
              …
              wstring msg; //
              //wchar_t* msg;//3c
              //int len;//
              //int maxlen;
              }

              wstring msg字段就是文字消息内容,而语音消息则是预览中看到的[语音]两字,并没有实际能够听到的语音数据,所以还得继续往前找。

              继续往上回溯了3层左右,进入了102DDC50,找到了语音消息的新信息。

              struct msg_xx
              {
              char unk[0x40];//
              wstring wxid1;//40
              wstring wxid2;//4c
              char unk1[0x10];//58
              wstring msg;//68
              char unk2[0x10];//74
              ;//84
              }

              在wstring msg处就是普通文字消息内容,而语音消息并不是我想象的就?#20405;?#25509;语音的数据,而是…如下:

              <msg><voicemsg endflag="1" cancelflag="0" forwardflag="0" voiceformat="4" voicelength="1176" length="1334" bufid="147445261304397871" clientmsgid="416261363964373964444633636200230013013119fdd53b1f494102" fromusername="wxid_xxxxxxxxx" /></msg>

              真是一波三折,还不是语音的数据,而是关于语音信息的xml,有语音的大小,来自谁,在语音缓冲区中的id(bufid)等等信息。

              继续往前找呗,最后回溯到了所有消息处理的分发函数10323FF0中。这个函数处理逻辑很复杂,我并没有很快就找到如何生成语音消息的xml,以及处理语音数据的函数。

              一度卡住,重复分析了很多次。

              后来又回神想到了逆向神器IDA,xml中数据如voicemsg肯定是模块中会在代码中用到,看看有没有有用的信息。

              用IDA打开Wechatwin.dll,shift+F12分析出所有字符串,Ctrl+F找到关键字voicemsg,看来有戏。

              真的是柳暗花明又一村。

              点击字符串跳到代码窗口,按下x,跳到引用该数据的位置。

              找到了解析语音xml数据和解码语音数据的关键函数。

              f_parseVoiceXmlInfo_103148E0
              text:103149DD 0E4 0F 84 74 02 00 00                             jz      loc_10314C57
              .text:103149E3 0E4 68 D0 06 F0 10                                push    offset aVoicemsg ; "voicemsg"
              .text:103149E8 0E8 8B CF                                         mov     ecx, edi
              .text:103149EA 0E8 E8 31 28 3E 00                                call    f_xml_subnode_106F7220
              .text:103149EF 0E4 85 C0                                         test    eax, eax
              .text:103149F1 0E4 0F 84 60 02 00 00                             jz      loc_10314C57
              .text:103149F7 0E4 8D 70 2C                                      lea     esi, [eax+2Ch]
              .text:103149FA 0E4 68 C4 06 F0 10                                push    offset aClientmsgid ; "clientmsgid"
              .text:103149FF 0E8 8B CE                                         mov     ecx, esi
              .text:10314A01 0E8 E8 CA 3A 3E 00                                call    f_xml_getvalue_106F84D0

              函数103148E0解析xml拿到几个字段的内容,返回上层函数调用一个语音解码的函数进行处理,而这个解码函数?#31361;?#30452;接操作语音数据。

               (*(void (__thiscall **)(int *, _DWORD, _DWORD, int *, signed int))(*v7
                                                                                           + 28))(//
                            v7,
                            *(_DWORD *)(voice_msg + 48),      // 语音内容
                            *(_DWORD *)(voice_msg + 52),      // 语音长度
                            v17,
                            v4);

              函数103148E0回溯再看看,进入了分发函数10323FF0中,在一个循环中处理了多种流程,包括显示界面最新消息的流程和解码语音的流程。所以前面找的方向并没有问题,只是缺少认真分析数据和代码的耐心。

              不过,目的都达到了,找到了数据处理函数,最后通过hook这个函数就能拿到语音数据。


              小编推荐:欲学习电脑技术、系统维护、网络管理、编程开发和安全攻防等高端IT技术,请 点击这里 注册账号,公开课频道价值万元IT培?#21040;?#31243;免费学,让您少走弯路、事半功倍,好工作升职?#26377;劍?/font>



              免责声明:本站系公益性非盈利IT技术普及网,本文由投稿者转载自互联网的公开文章,文末均已注明出处,其内容和?#35745;?#29256;权归原网站或作者所有,文中所述不代表本站观点,若有无意侵权或转载不当之处请从网站右下角联系我们处理,谢谢合作!


              鲜花

              ?#24080;?/a>

              雷人

              路过

              鸡蛋

              相关阅读

              最新评论

               最新
              返回顶部
              十一选五奖金对照表