声明
- 仅仅是个人兴趣,没有任何特殊目的。
- 研究的平台是 Windows。
- 无法“防止撤回”所有消息,目前只支持文本,没有深入研究了,有兴趣的朋友可以继续挖掘下,如果可以,分享下成果,哈哈!
- 分析的版本Windows_pc5.1.28
思路
- 一般就是找到钉钉客户端,处理服务器返回数据包的函数,然后手动触发撤回消息,跟踪分析……
分析过程
简单分析
- 知己知彼才有可能百战百胜。 先调查下钉钉的框架。Procexp:
可以看到,钉钉是个多进程的程序,有可能是基于Libcef 或者 Electron开发的,判断方法比较简单,看下是否有加载libcef.dll 。如果有,就是基于libcef开发的……
- 本人对libcef不熟悉,但是稍微有开发过基于Electron的应用,大致了解libcef也是基于浏览器的应用,也是基于JS、C++的混合开发的应用。 所以,应该会有一些JS代码的资源文件,不过可能被加密了。 看看程序的安装目录有没有什么新发现:
这里有个很大的pak后缀文件,成功的引起了我的注意。尝试用7z打开,结果:
诶嘛真香???双击查看试试:
好吧,果然加密了。 不过作为本地资源,钉钉肯定会解密这个pak文件,加载其中的页面展示。索性直接上调试器,找解压缩密码!
这里插播一句废话,这个世界的确是存在捷径的,如果没有人告诉你,那么你就只能自己去发现、开辟它。
动态调试
- 根据某个特征下断点,直接拿密码就好:
关于这个断点,我只能附上一个截图了,剩下的靠读者自己摸索吧:
- 拿到密码,提取资源:
静态分析
- 不能做无头苍蝇。根据钉钉收到撤回消息的提示: XXX 撤回了一条消息,直接在解压缩的资源文件夹下,搜索所有文件:
这时候就要有逆向的敏感嗅觉,看下这个字符串的引用:
一坨打包的代码,直接js美化再看下引用(这里直接走“人生捷径了哈”):
这里应该就是展示撤回消息的js代码了。构造一个DOM节点,设置文字内容。通过多次分析尝试,得到了如下代码,可以防撤回文本消息:
{
s = void 0;
s = o ? "dt_message_recall_message_file_format" : "pc_im_recalled_a_message";
var c = b.i18next.t(s);
try {
c = " 撤回的消息为: " + a.baseMessage.content.textContent.text;
}
catch(e) {
c= " 读取撤回消息失败。"
}
t = I.createElement("span", null, r, " ", c)
}
改好以后,重新打包一份web_content.pak文件,用7zip打包压缩:
修改后缀为.pak文件,然后直接替换掉原始的:
- 展示成果:
总结
钉钉是基于libcef开发的应用程序,其加载的核心资源文件,存放在安装目录下的web_content.pak加密压缩文件中。通过解密该资源文件,根据关键字“撤回了一条消息”,定位到处理撤回消息的相关代码,并通过修改代码,重打包并替换资源文件的方式,实现了文本消息的“防撤回”。 不过还是有一定缺陷的,因为只是在界面层防撤回,而不是真正的在处理数据包的native层,做消息防撤回处理。 由于时间关系,就不深入研究了,有兴趣的朋友可以基于以上分析做更深入的文件、@消息、富文本消息的防撤回。 各位大佬,请不吝赐教!