卧槽迅雷的代码结构竟然被扒了精光

admin 2024-10-08 01:57:01 0

扫一扫用手机浏览

文章目录 [+]

  配景

  之前扒过飞书的源码,从代码设计架构层面里里外外进修一把,飞书照样挺 “年夜方” 的,源码在客户端和网页端都一目了然,不外宛如新版本已经看不到了。相关的文章因为在内网技术论坛发过了未便于再发出来(泄露内部材料会被查水表的),是以此次周末抽光阴换一个鸟窝来掏一掏。

  一不当心发现迅雷的客户端竟然也是基于 Electron 开发的,那代码就好扒拉了。(先吐槽一下这新版本的某 lei 为什么要抄钉钉的界面,这些年某 lei 都不知道本身要干什么了,每个版本都招人嫌)。

卧槽迅雷的代码结构竟然被扒了精光
(图片来源网络,侵删)

  

  拆解篇

  1、一点配景常识阐明

  基于前端技术栈 Electron 构建的桌面利用,本色上都是加载当地前端资本文件,而这些文件通常是用 asar 格局(相似 windows iso 镜像)的方式进行打包,然后运行时再经由过程挂载到内存实现前端资本文件 js/css/html/img 等文件的读取。

  这么说 asar 想方法挂载就可以随便浏览源码了吗。不是的。同时 asar 会提供一套经由过程加密方式防止随意率性解压,飞书便是这么做的,直接经由过程 asar extract 的方式无法解包出来。然则因为 node 端和 rust 构建的二进制文件假如打包到 asar 会导致无法链接到这些二进制文件,是以必要从 asar 中自力出来,因而导致有部门 js 文件仍旧暴露在表面。不外即便没有任何 js 是裸露的仍旧是有方法爆破的。

  啊,跑偏了,先不谈飞书,本日的主菜是迅雷。

  那迅雷的前端资本文件是怎么治理的呢。

  

  是在下想多了,欠好意思,迅雷梅川酷子,都摊着在那呢,基本没用 asar 打包 / 加密。

  2、开撬

  既然 js 都裸露了,也没什么好绕的,直接植入代码吧。我们都知道 Electron 是有 render 过程和 Node 过程的,接下来这一步必要猜猜看哪个文件是卖力 render 主过程的。

  好吧不消猜,名字都异常人类可读,就 main-renderer(主窗口衬着过程)。打开找到 html 文件(js 也可以)插入如下这串。

  

  双击启动,调试窗口出来了,可以年夜致看到整体页面布局了。

  

  然后看了一下,迅雷的悬浮小圆圈和主窗口,分离用一个 BrowserWindow 来实现。有趣的是谁人小圆圈窗口实在并不小,鼠标悬停出来的谁人浮窗也是它的一部门,为了让小圆圈在屏幕的任何地位都可以看到悬浮窗,以是整个小圆圈的 BrowserWindow 是年夜约 4 倍的悬浮窗口年夜小。

  

  自力窗口的检视界面 - 窗话柄际是 4 倍 浮窗年夜小,灰色部门全都是这个 “小” 浮窗所使用的 BrowserWindow 区域。

  

  3、一点防御步伐

  从代码来看,nodejs 过程只有一个文件 main.js ,是 webpack 的构建产品,看源码这里的 BrowserWindow 的 webPreference 参数是把 devTools 禁用失落的,导致直接在敕令行里敲 openDevTools 是不克不及检视随意率性窗口的。

  

  当然了,这里即就是殽杂过了也不要紧,究竟照样明文,把 1 改成 0,把它打开就好(双叹号 /true/1 啥都行,开心就好)。不外因为迅雷的窗话柄在是太多了,下载弹窗是自力窗口,选择文件夹是自力窗口,各类告白窗口也是,必要改的设置装备摆设点许多,这里就不列了,统共有 10 个窗口,这个设置装备摆设点按需打开(批量替换也行,谨严操作就行)。

  过程布局

  呃…… 然后要干啥…… 宛如也没什么悦目的了,代码是殽杂过的,也没有 map 文件。并且前端部门的代码也没什么技术含量可以说的,哪个 web 页面都那样。那看看过程分工吧。

  1、过程树

  在过程树里可以看出来,险些全体的过程都是 Thunder.exe,可见 Thunder.exe 作为过程派发进口(相似 server 的网关,而并不直接是营业自己),用户启动的时刻传参是 --StartType:DesktopIcon,随后它唤起了两组过程,一组是 Electron main 过程,main 过程唤起相关的 renderer;然后是下载的 SDK 服务 DownlaodSDKServer。

  那么迅雷的过程关系差不多是清晰了:多个 Electron 窗口,对应一个 DownloadSDK。

  

  2、通讯方式

  那么 Electron 的过程(甭管 main-process 照样 renderer-process,统称 electron 过程) 和 DownloadSDK 是若何通讯的呢。

  过程间通讯一样平常都是寄托 ipc 管道的情势来实现。不外迅雷彷佛没按套路来,它的 DownloadSDK 是节制台法式,意味着很有可能是经由过程 stdio 的方式来进行交互的(后续证实不是)。

  经由过程察看过程打开的句柄,看到很诡异的一个征象:DownloadSDK 并没有打开任何 ipc 管道,反却是前端过程打开了一个。

  

  3、前真个 ipc

  而 Electron 打开的这个 handler 过程名称,查了一下,竟然满是 Electron 过程使用的,并且是所有过程。

  

  那么不妨做出一个年夜胆的推想:前端多窗口之间是靠自建的 ipc 通道实现的,而 ipc 是 1 server 对 N client 的方式,那么 server 很有可能便是在主窗口上的,也便是前文看到谁人及其显著的 main-renderer 过程,经由过程节制台查看,确切如斯,nodejs 的 net 方式创立了一个 server,而且将一个叫做 __xdasIPCServerInstance 的工具裸露在全局情况供前端 js 挪用,也即 jsapi。

  

  而小窗口并不存在上述 server 实例,而相对应的有一个 client 实例。

  

  4、和 DownloadSDK 的通信方式

  如许看起来就很奇葩了,前端过程之间是经由过程自建的 ipc 管道通讯的,然则并没有跟 DownloadSDK 有任何通讯管道,岂非它俩是心有灵犀无言自通。啊这…… 法式员是唯物主义的。

  那怎么查它到底是怎么跟前端过程交互的呢。既然前端裸露了 server sdk instance,那意味着 DownLoadSDK 确定因此一种 proxy 的方式裸露在这上面作为 jsapi 的。可以拿【创立一个下载义务 api】来顺藤摸瓜。看了主窗口的 server instance 一下公然有这个办法:createTask ,应该便是前端用于创立下载义务用的 api。

  

  chrome 阅读器里查代码不便利,转战 vscode 看源码,搜刮 createTask 这个函数的声明地位,看到这一段(篇幅节制,此处删减了部门代码)。

  createTask(e, t){return n(this, void 0, void 0, function* () {switch (e) {case h.DownloadKernel.TaskType.P2sp:...case h.DownloadKernel.TaskType.Bt:...case h.DownloadKernel.TaskType.Emule:...case h.DownloadKernel.TaskType.Group:...case h.DownloadKernel.TaskType.Magnet:...default:i = !1;}return(... _.fireTaskEvent(h.DownloadKernel.TaskEventType.TaskCreated, [ ); }); }

  没跑了,证明了我前面的料想,这个 __xdasIPCServerInstance 便是 download sdk 封装到前真个 proxy。

  继续查,这个 fireTaskEvent 是怎么处置的,浏览代码进程繁琐按下不提,就看这两段代码 (有删减整顿)。

  // 片断一(e.getDownloadSdkVersion = function () {let e = a.join(__rootDir, 公众../bin/SDK/DownloadSDKServer.exe"大众);return v.getFileVersion(e);}),// 片断二y = l.default(o.join(__rootDir, "大众../bin/ThunderHelper.node"大众));let F = "大众/ssdkver 公众 + u.DownloadKernelManager.getDownloadSdkVersion();B.push(F)y.shellExecute(0, "大众open"大众, o, B, H, 公众SW_SHOW"大众);

  很显然,DownloadSDK 是经由过程一个 ThunderHelper.node 的 nodejs addon 模块来启动、通讯的。

  我们知道,nodejs 可以经由过程 ffi 等方式实现内存共享,以到达两个过程不必要经由过程 pipe/sock 等管道就到达通讯的目标。而经由过程对象察看 Thunder.exe 的唤起关系、句柄关系,两者的关系就加倍一览无余了:ELectron 前端过程加载 DownloadSDK 过程,而且经由过程 \Sessions\5\BaseNamedObjects\xx@22123720|SendShareMemory 这种内存通道来实现的通讯,句柄逐一对应上了。

  

  总结

  扒拉了半天,扒完了有点空虚是怎么回事。

  迅雷的代码架构关系是轻 node 而重前端,把所有的 node 加载、过程治理、多窗口通讯都放在前端过程的主窗口过程里。关于这个做法,我尊敬而不认同。前端过程不该该做太重的底层交互,尤其是 js 这种单线程语言,自然的就运行效力低,并且主窗口使用这么频仍就不怕卡住吗

  Electron 自然就有 ipc 通讯才能,完全可以在 node 端做一个新闻网关,杀青每个窗口通讯的才能,完全不必要自建一个 ipc server-client 系统。可能这也是一开端就把年夜量事情放在前端 (主窗口) 了导致后期的法式设计受限。说不定是个汗青累赘

  用一个 node addon 的方式来跟 DownloadSDK 来通讯,这点是可以点个赞的,固然是业界尺度(飞书是经由过程 rust,根本原理相似),然则我今朝所卖力的营业并没有做到如许,以是在忸捏的同时也给它点个赞

  迅雷使用的 Electron 版本是 9.2.1,vscode 也是这个版本,好神奇。异常好奇为何业界都用这个版本,事实上 electron 9.x 最新版本已经更新到 9.3.3 了(2020 年 10 月 28 日)这个 9.2.1 有什么魔力让业界都用它吗

  这里阐明一下,Electron 从 6.0 开端就不支撑 windows7 (非 sp1) 及以下的版本了。

  我在 win7 体系上用迅雷安装器安装迅雷最新版本,发现 electron 用的是 1.8.6 版本

  Electron 的主进口是处置过了的,经由过程 Thunder.exe 法式干了许多除了启动前端以外的工作,这个定制照样挺棒的,由于如许就可以把各类过程模块治理起来,不会呈现多个自力过程。就我所看到的不少 Electron 利用实在都没有定制过。

  以上是纯洁技术发掘,没有破坏到迅雷的焦点秘密,仅做进修交流使用哈~

  迎接参加法式员交流群

  起源:juejin.im/post/6890344584078721031

相关文章

清苑新能源车,引领绿色出行新潮流

随着全球气候变化和能源危机的日益严峻,绿色出行已成为全球共识。作为我国新能源产业的佼佼者,清苑新能源车凭借其卓越的性能和环保理念,...

家电资讯 2024-12-29 阅读5 评论0