Chapter 5 进阶开箱技术简介

5.1 名竞网页的改造

我们都知道,传统开箱器的工作方式是使用 js 脚本自动模拟人类点击鼠标的操作,在开箱时你也可以通过屏幕上窗口的快速闪烁直观地感受到这一点。这种开箱器的原理简单粗暴,但也有明显的缺点,比如依赖带有图形界面的浏览器、在网页渲染上浪费不必要的算力等。如何使开箱器摆脱网页界面的限制,像测号器一样在命令行终端中运行呢?答案就藏在网页背后的文件结构中。

当你在浏览器中游玩名竞时,实际上是在与游戏的 HTML 文件进行交互。玩家的输入并不会由它直接处理,而是会被发送到游戏的核心程序,一个名为 md5.js 的脚本中计算。计算得出的战斗过程与结果将被反馈给 HTML 网页,最终显示在屏幕上。

既然实际的战斗计算并不在 HTML 网页中进行,那么如果我们绕过这个“中间人”,直接与 md5.js 通信,是否就能免去渲染网页的环节呢?答案是肯定的。通过玩家们的逆向工程研究,我们成功破译了游戏网页与 md5.js 之间的通信方式,并且在此基础上将原 md5.js 改造封装为一个对外暴露 API 接口的“黑箱子”。这样,玩家只需使用脚本调用 API 接口,就能直接得到战斗和评分结果。由于新的 js 脚本通过 Node.js 解释器环境在命令行终端中运行,这一技术被称为“node 开箱技术”。

图片

传统开箱脚本(左)和 node 开箱技术(右)的原理

5.2 node 开箱生产中的调优处理

在无头终端中开箱的想法确实令人兴奋,但当玩家们将其投入大规模应用时,却遇到了严重的问题:内存泄漏。在 md5.js 自身缺陷和侵入式逆向改造的双重作用下,长期运行的开箱脚本无法回收占用的内存,导致 Node.js 内存栈溢出崩溃。为解决这一问题,我们采用了“定期重启”的策略:在原有的开箱器结构顶层添加用于调度的主程序,每开完一小批号之后通过终端指令自动重启 js 开箱脚本,从而避免了长期运行单个 js 脚本导致的内存泄漏问题。新的调度架构还有另外一方面的优势:让主程序同时管理多个 js 脚本,就能自动地多开运行,免去了手动创建窗口的麻烦。目前的 node 开箱器,使用的都是这种架构。

图片

现代 node 开箱器的结构

5.3 反混淆工作与未来展望

如何让开箱器跑得更快?在剥去了网页渲染的外壳之后,玩家们开始向 md5.js 内部进军。在游戏开发初期,为了防止算号过程被破解,作者对 md5.js 进行了混淆处理,使用混淆加密工具将变量和函数名等信息用随机乱码替代,使得人类难以理解。尽管现在的算号技术早已不是秘密,混淆防御措施却仍未解除,这使研究 md5.js 变得极为困难。名竞逆向工程的核心工作,就是将混淆后的乱码 md5.js 还原为人类可读形式的过程,是为“反混淆”。

由于 md5.js 文件过于庞大,在现有条件下只凭借人工对其进行完全反混淆如同愚公移山,虽然理论可行但效率过低,不切实际。因此,现阶段的反混淆工作主要聚焦于涉及战斗限速和技能作用的部分,以期通过尽可能少的人工成本实现“开箱加速”与“技能机理解析”两大实用性较强的目标。

在多名玩家的努力下,反混淆工作取得了辉煌的成果。在开箱加速方面,我们不仅能被动去除作者故意设置的限速机制,还能在计算密集部分主动出击,通过局部优化手段进一步提速;在战斗机理方面,我们已在代码层面上成功解释了多种技能的作用机制,并对号在战斗中的决策过程有了基本的了解。可以说,没有反混淆工作,就没有如今先进的开箱技术和基于它们的深入游戏理解。

虽然现在我们距离完全破译 md5.js 还有很长的路要走,但这始终是名竞逆向工程的终极目标。我们相信,在玩家社区的不懈努力与辅助编程工具的加持下,这一天终将到来。届时,md5.js 将不再是神秘的“黑箱子”,开箱器也将摆脱解释型语言的限制,像测号器一样自由地高速运行,而名竞这一历史悠久的游戏的命运,将第一次被彻底地掌握在我们——玩家社区——的手中。
(别做梦了,继续往下看)

5.4 diy 技术

以前我们经常口嗨“这个号如果某个属性+10/某个技能熟练度+10/添加某个新技能,会怎么样”。为了避免这方面的研究止于想象,diy 技术被开发了出来。

diy 技术的原理是通过代码注入劫持 md5.js 中载入名字字符串的部分,使它识别一个特定的装备格式 +diy[]{}。玩家将定制的名字属性和技能信息包含在这种装备名中输入游戏,被修改过的 md5.js 探测到特殊格式后就会读取信息,使用它们强行覆盖原有名字的属性和技能,达到“定制一个不存在的号”的效果。
只有经过特殊修改的 md5.js 才能识别 diy 格式,因此 diy 定制号的格式在原版名竞中只是一个带装备的普号,只有在 diy 改版网页中才能生成对应的“假人”。

目前较为常用的 diy 改版网页是 fast-namerena.pages.dev(同时添加了评分加速等功能)。除 diy 外,网站的其他正常操作和原版名竞一样,可以测评分、胜率等。

例如,name@team 这个号的属性为 HP 291 攻 68 防 49 速 72 敏 60 魔 60 抗 67 智 79,技能(注意顺序)为会心 11 铁壁 21 地裂 8 苏生 8。它的 diy 装备格式为:

  • +diy[68,49,72,60,60,67,79,291]{"SklCritical":11,"SklIron":21,"SklQuake":8,"SklRevive":8}

如果我们想要把它的 HP 增加 50 进行测试,将 diy 装备中的 291 改成 341 然后把装备附加在任意名字字符串后面,就能虚拟出一个这样的号。
需要注意的是,diy 无法定制召唤物的属性。也就是说,1+diy[...]{...} 召唤出的幻影/使魔/丧尸和 1 的召唤物是相同的,不受 diy 的影响。所以,对于有召唤类技能的号,不能随意改动原来的名字字符串。

由于技术原因,对一些分身号的 diy 会有较小的误差,暂时无法修复。

技能名称对照表(不区分大小写):

技能 火球术 冰冻术 雷击术 地裂术 吸血攻击 投毒 连击 会心一击 瘟疫 生命之轮
名称 SklFire SklIce SklThunder SklQuake SklAbsorb SklPoison SklRapid SklCritical SklHalf SklExchange
技能 狂暴术 魅惑 加速术 减速术 诅咒 治愈魔法 苏生术 净化 铁壁 蓄力
名称 SklBerserk SklCharm SklHaste SklSlow SklCurse SklHeal SklRevive SklDisperse SklIron SklCharge
技能 聚气 潜行 血祭 分身 幻术 防御 守护 伤害反弹 护身符 护盾
名称 SklAccumulate SklAssassinate SklSummon SklClone SklShadow SklDefend SklProtect SklReflect SklReraise SklShield
技能 反击 吞噬 召唤亡灵 垂死抗争 隐匿
名称 SklCounter SklMerge SklZombie SklUpgrade SklHide

一些工具可以方便地输出一个号的 diy 格式,从而进行修改。本教程的“资源文件下载”页面提供的 exe-tools 工具包中就包含一个这样的,名为 team_calc 的工具。输入单个号(多个号会自动组队并加成)然后运行工具,就能得到它的 diy 格式。
team_calc 工具以两种形式提供,team_calc.html 可以直接在浏览器中打开,而 team_calc.exe 需要在 input.txt 中输入后双击运行 exe(没有输入界面,只会看到一个空窗口一闪而过),输出在 team_calc.txt 中。

diy 技术用途广泛。它不仅可以测试组队加成后战组中每个单号的评分,也在研究属性对技能的作用和技能搭配等方面有着重要的作用。除此之外,diy 捏假人试验也为理论研究提供了精确的数据支撑,嘲讽值公式就是通过大量的 diy 属性滴定数据总结出来的。