xxxx(四):接受消息hook地址分析

摘要:
向测试帐户发送高度可识别的消息。此时,不要在测试帐户上打开邮件。CPU通过数据总线将数据从网卡的缓存中读取到内存OS,根据数据包的端口号找出数据包属于哪个进程,然后将其发送给进程。在接收到数据后,内存缓存进程根据业务需求处理数据,因此可以通过发送不同的数据来确定缓存地址;那么存储在内存中的地址肯定会改变。此时,您无法通过不同的消息找到真正的缓存地址!

   今天来分析一下xxxx接受消息的call;测试的账号在虚拟机,发消息的账号在物理机;

   1、老规矩:逆向分析的起点都从CE开始;给测试账号发送辨识度高的消息,这时暂时不要在测试账号打开消息。因为此时的消息刚经过网络传输,还是ASCII格式,所以千万不要勾选UTF-16,只能找ASCII码找(下面详细解释原因)!

xxxx(四):接受消息hook地址分析第1张

 重复发送0000000000、1111111111、2222222222、3333333333等辨识度很好的字符串,最终锁定3个地址:

 xxxx(四):接受消息hook地址分析第2张

  这里再详细解释一下用ASCII码找的逻辑,先介绍一下数据包整体的处理过程,如下:

  •   数据通过网络到达网卡后,会暂时存在网卡的缓存;网卡此时通过控制总线通知cpu来取数据;
  •   cpu通过数据总线把数据从网卡的缓存读取到内存
  •   os再根据数据包的端口号找到这个数据包属于哪个进程,然后再发送给进程在内存的缓存
  •   进程收到数据后根据业务需求处理数据,具体到这里就是在界面展示出来

  由此可以得出以下几点结论:

  •    同一份数据在好几个不同的地方都存了,原因就是上述各种转手、倒腾导致的
  •    数据都是通过ASCII发送的,os和进程的缓存也都是ASCII格式,并且缓存的地址是不变的,所以才能通过发送不同的数据来确定缓存的地址;一旦在页面展示出来,消息就是一条一条的了,那么在内存存放的地址肯定会改变,绝对不会再让不同的消息共用同一块内存,此时再通过不同的消息查找是找不到真正哪个缓存地址的!

 2、目前看不出是哪个是消息接受函数写入的地址,只能3个地址都下断点试试;正当对第二个地址下断点时,下面内存展示的内容引起了我的注意: 第一个内存只展示了收到的消息,但这个内存还展示了msgsource、疑似MD5等,这个是原始消息接受内存的可能性最大,果断下内存写入断点

  xxxx(四):接受消息hook地址分析第3张

   继续给测试账号发消息,成功断下:从寄存器看,是edi指向了这块内存区域;rep movs是连续写入的指令,应该就是这里没错了!

   xxxx(四):接受消息hook地址分析第4张

   核心dll的基址是711B0000, 断点指令的地址是724472AE,offset=0x724472AE-711B0000=0x12972AE,记住这个base,以后重新打开的时候就能直接通过偏移找到这行代码了;

   xxxx(四):接受消息hook地址分析第5张

   这个时候就可以通过栈回溯一层一层查找函数调用了;理论上可以在栈上找到xxxx软件的每个函数然后下断点,但这样做效率太低。继续挨个往下回溯栈时发现了一个关键词:”lass SyncMgr“, 这个从字面看是疑似是最后同步消息的函数,这个字符串也是ASCII码,所以跳到这里观察一下这个函数:

   xxxx(四):接受消息hook地址分析第6张

   返回处是一个push指令,该指令前面有一个call调用,在这里下个断点,断下来如下:

   xxxx(四):接受消息hook地址分析第7张

    继续向下观察堆栈:找到了发送消息的id(已经打码)和消息本身;为了证实,这里可以继续发其他的消息,看看下面”eeeeeeeeee“会不会变成发送的消息。我这里已经尝试过了,确实是这样的,这个call就是发消息的call了,edi指向了消息的结构体!这个call的调用地址是0x7157CB6B-0x711B0000(核心dll的基址)= 0x3CCB6B;以后如果重新加载了xxxx,可以直接根据这个基址找这个call;后续代码也要hook这个地址!

   这个call有个特点:跳转地址是[eax+0x8],而eax又来自另一个内存地址[0x72A52BF0],属于间接call;每次重新加载dll的时候,由于OS的随机地址分配基址,可能地址都不一样,因此直接找call的入口不太合适,就死死守住这里调用call的地方!

   xxxx(四):接受消息hook地址分析第8张

   接下来就是计算关键数据的偏移了:

  •     发消息ID(有可能是群,也有可能是个人)的偏移=[[esp]]+(0x76AD70-0x76AD30)= [[esp]]+0x40
  •     消息内容的偏移 = [[esp]]+(0x76AD98-0x76AD30)= [[esp]]+0x68
  • xxxx(四):接受消息hook地址分析第9张
  • 群里发张图片还会注明是哪个用户发的;
  • xxxx(四):接受消息hook地址分析第10张
  •     如果是群消息,那么这里是个人ID = [[esp]]+(0x76AE94-0x76AD30)==  [[esp]]+0x164;如果是个人消息,这里直接是00;
  •    [[esp]]+0x178处还有一串疑似MD5的字符串,个人猜测有可能是校验的MD5,防止消息内容被第三方截取后篡改内容(有点类似https证书的认证)

        xxxx(四):接受消息hook地址分析第11张

        消息最后以<msgsource>结尾!

       大家有没有主注意到:账号的id、消息内容、md5这些字符串后面紧接着都会有两个4字节数字? 这些数字的大小刚好等于字符串的长度!个人猜测这是对字符串做长度校验的,避免字符串过长覆盖了某些重要的数据,比如返回地址等,造成栈溢出攻击

        至此,接受消息call的偏移地址找到了,消息存放的地址也找到了,下一步写代码hook消息的接受!

说明:

1、xxxx版本号:3.1.0.41

参考:

1、https://www.bilibili.com/video/BV1Sg4y1b7uc?p=11 最新实战xxxx hook分析

 2、https://www.freebuf.com/articles/others-articles/210289.html   PC xxxx逆向:发送与接收消息的分析与代码实现

====================2021.2.6更新=================================

        互联网两大头部厂商这几天又在互相掐架,网传其中原因之一是:B厂家读取了T厂家xxxx关系链的数据,从本文逆向分析来看,技术上这个是完全可能的!关系链是T厂家最核心的资产和护城河,岂容他人觊觎? 

免责声明:文章转载自《xxxx(四):接受消息hook地址分析》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Linux添加用户组和删除用户组Maven 安装Jar包到本地仓库下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Django Restful Framework

你在浏览器中输入了一个地址的时候发生了什么事情? 1.HOST 2.DNS 3.HTTP/HTTPS协议 发送一个协议 4.进入了实现了WSGI协议的服务器(wsgiref uwsgi(C语言实现,多线程,多进程,PHP,TOMCAT)) 5.请求进入Django 6. 前后端不分离:中间件->路由分发->对应的视图函数->找到模板,渲...

Semantic UI 中文参考手册

一个拥有友好词汇表的前端框架,完全语义化的前端界面开发框架,为一组开发人员之间共享UI元素配备了规格。使用的词汇(类和ID)相比其它替代品更加简洁,从而降低了学习曲线。有许多HTML元素,UI元素和场景(按钮,表格,表格,手风琴,导航,注释..)的样式。使用LESS作为预处理器。 它有很多非常酷的元素,如可折叠功能、3D动画等,而且动画效果看起来比Boot...

织梦cms dedecms程序安装问题

织梦程序的安装及使用 程序安装使用 1.下载程序解压到本地目录; 2.上传程序目录中的/uploads到网站根目录 3.运行http://xxx.xxx.xxx/install/index.php(xxx.xxx.xxx表示你的域名) ,之后按照安装说明进行程序安装 注意事项: 1、安装时候,数据库地址、数据库用户、密码、数据库名这四项是空间商提供的,如果...

Linux Bond的模式与原理。

原理:   多块网卡虚拟成一张,实现冗余;多张网卡对外显示一张,具有同一个IP;网络配置都会使用Bonding技术做网口硬件层面的冗余,防止单个网口应用的单点故障。   对于多物理网卡的 Bond 网卡而言,其中一块物理网卡会被设置为 Master(主设备),其他的网卡都是 Slave(从设备),Bond 网卡的 MAC 地址取自标志为 Master 的...

JVM三种类型参数详解

一、概述   JVM参数调优是程序员必备的技能,JVM的参数主要分为三种类型:1、标准型:稳定,比如java -version   2、X:相对变化较少的  3、XX:JVM调优的主要部分 二、JVM调优参数   XX:型参数主要分为如下两种   2.1 Boolean类型的   a、使用方法是:-XX:[+/-] name     开启使用+:比如开启G...

后端接收前端传的数据方式

1. get方式获取:     res = request.GET.get("name",  " ")     GET提交,请求的数据会附在URL之后(就是把数据放置在HTTP协议头中),以?分割URL和传输数据,多个参数用&连接 2. 以表单方式传数据     name = request.POST.get("name", "") 3. 以jso...