【中等】来自远古小恐龙的挑战书

出题组为了给大家整点简单又好玩的题,可谓是费劲了心思,甚至不惜在题面里整上了花里胡哨的排版。本题作为**“游戏”系列**的第一题,本来是可以整一些大作的,比如 GameMaker Studio。但是我一看这生成出来代码又是 webpack 又是 gms 自定义逻辑,完全不是人能看的,遂放弃之,采用了开源、更加简单的替代品。chrome://dino 相信是很多同学在上信息课时的娱乐方式,也算是家喻户晓了。本题的构想是引导玩家看懂 JS 代码,并使用 浏览器的 Console 控制台 功能进行作弊。

当然,什么都不改的话,一个 Runner.instance_.distanceRan = 99999999 就完事了,这显然太简单,于是我在代码里把原本下放到 window['Runner'] 里的实例修了。

image-20241021020159030

删去该行代码后,由于 Runner 是在 (function () { })() 里面构造的,作用域仅限于此,自然外边就访问不到了。

我相信各位大多数采用的解法都是肉眼或者 AI 观察法,一下就定位到了这段看起来非常可疑的代码上。

image-20241021020506161

无论是利用 Burpsuite 或者直接下载网站然后替换 JS 该行的检测逻辑,还是把这个复制出来,粘到控制台里执行,都是预期的解法。只不过我没想到大家或者 AI 眼睛看得也太精了,至少直接搜 flag 或者那个框的提示词文本都是找不到这里的。

image-20241021101639610

出题人的原本的打算呢,是教会大家使用 debugger 功能。但是善良的出题人还是手软了,没有给 JS 上加密。大家可以想一想,如果到这里(JS 的末尾)为止,上面有关 Runner 实际的代码全部都被加密了的话,本题又应该怎么做呢?

image-20241021102005809

不知道大家是否使用过这个在浏览器 Debugger 一栏右侧的小功能块。

image-20241021102241983

我们把 DOMContentLoaded 勾上,再刷新,会发生什么呢?

image-20241021102324041

在经历过几个插件之后(按 Resume F8 继续),会发现我们成功断在了创建新 Runner 实例的这一行。(或者可以直接在 Line 2793 处右键 Add Breakpoint)

image-20241021102650851

查看一下变量 Scopes,底下 window['Runner'] 是被替换过的 Proxy 对象,而上面那个 作用域的 Runner 自然是在 DOM 树中新创建的那个 Runner 实例对象!

image-20241021103528511

在控制台中,保持断点的状态,我们把这个 Runner 从当前的作用域中提取出来,即 let a = Runner; ,然后再继续,便可以跟最开始最简单的方法一样开挂了!

image-20241021103901965

思考题:若整个 JS 文件都被经过很强的加密了,又该怎么办?可以试着在 DOM 点击右键,Break on Subtree Modification,还是能在 Runner 内的某个地方下下断点,自然能获取其作用域。当然,这时候的变量名跟函数名就不一定会那么好看了,关于这一点,还只能自求多福 :)