文章来源:网友投稿
0x00适用场景本文所采用技术,仅用来实现自定义功能,适用场景仅为自己两台电脑使用聊天软件互发消息学习研究使用。
*本文仅限技术研究与讨论,严禁用于非法用途,否则产生的一切后果自行承担。
0x0需求产生某聊天软件有已读回执功能,可以通过查看标记,判断对方是否读了你的消息:
经常出现这样一种情况,联系人发来几条消息,啊T.T,我好想看看他说了什么:
然后点开看了一下,完蛋,又是借钱的:
这个辩解苍白无力~
那么伟大的需求就此诞生:如何偷偷看他消息,而不让他知道我已读了?
0x02探究原理盲猜原理一定是这样:
客户端查看了消息-客户端发送已读回执到服务器-服务器向消息发送者发送已读状态
那也就是说,只要我们使用的PC客户端不发送已读回执,服务器就永远不知道我们读了该条消息,对放也就不会知道我们看过了。
一开始想看有没有人造过轮子,于是github上翻了翻,但没什么收获。不过在翻的过程中发现了一个有意思的项目:dingtalk-interceptor,但该项目删除了,于是就去网上翻了翻,果然找到了相关的文章,针对的是老版的客户端(3.x),该版本就是Electron包装的一层网页,项目实现原理是通过拦截所有包含updateToRead的请求,从而实现永远未读消息的。
因此我们要寻找的突破口就在这个关键字上:updateToRead
0x03环境准备调试环境:
winx64
x96dbg
ida7.0
顺便推荐个工具,可以让ida和od/xdbg/lldb等同步调试:
通过不断尝试,发现该聊天软件的核心逻辑都在MainFrame.dll中,因此只针对MainFrame.dll进行搜索,关键字:updateToRead。
先定位到模块中:
后在该模块中搜索updateToRead,并全部设置断点
发送两条消息并阅读测试,命中断点如下:
关闭其他断点,并用另一个号给调试的账号发送消息,并查看:
在第一个断点处,消息依然是未读状态
在第二个断点处,消息依然是未读状态
在第三个断点处,消息依然也是未读状态
在断到第四个断点处,消息依然是未读状态,但放过断点,消息就变成了已读:
解决方案有几个:
.破坏原有数据包,使其服务器无法正确更新状态
2.在发送前拦截该数据包,使其不发送
3.不进入检测消息是否未读状态
此处通过调用该接口“/r/IDLMessageStatus/updateToReadV2”向该接口发送请求,来告诉服务器,消息已经被读了。此处可以直接暴力将接口修改,修改成错误的地址,也可以实现看了消息不显示已读。但直接通过该种方式修改,有两个弊端,
.会向服务器发送一条数据,虽然服务器没能正确处理,但会返回一个异常。
2.客户端收到该错误响应后会认为自己与服务器断开连接,会经常认为自己掉线了从而发不出去消息
路线走不通,因此继续寻找突破点,使用ida反编译该模块,查找该接口:
发现该接口是出自sub_27B20函数:
进入sub_27B20内容:
往上跟踪,发现sub_0BA调用了sub_27B20
往上跟踪,发现sub_E0调用了sub_0BA
sub_E0函数内容:
其中包含多个接口,作用是向服务器发送一个包含消息id的请求包,从而实现消息已读。
此时已经基本了解大概情况,继续用x64dbg调试,在调试过程中发现在执行完sub_E0消息并未直接变成已读,而是继续向上层函数继续返回,直到返回了这样一个函数:
伪代码:
该函数
sub_0C77E70在if(v3)
处存在两个分支,一个分支调用sub_0CD0(i,v4),
另一个分支即已读分支sub_0C(i),也就是我们的call所调用的函数。因此,v3是一个关键判断点
v3所对应汇编代码为:jzshortloc_0C77EAC
偏移为:C
在C上下断点,通过修改寄存器zf标志位,使其进入sub_0CD0(i,v4)
修改后发现,后续发送的消息均不显示已读,且不会再进入该判断,因此只要让v3永远=True,即可永不进入sub_0C(i)分支,即修改该处条件跳转为jmp
修改后Patch到dll上即可。
特征码:
CD45F08BCE50E8CEFFFFFDFBCE
修改后:
C0EBD45F08BCE50E8CEFFFFFDFBCE
0x05已读不回0x07免责申明
本文是作者闲暇之余,方便自己搞的一个小功能。如果对其他人/公司造成不好的影响请联系我们处理。
推荐文章++++
*一份礼物.apk的逆向分析
*逆向分析CobaltStrike安装后门
*菜鸡开始学习逆向工程,首先是最简单的题目
预览时标签不可点收录于合集#个上一篇下一篇