题目地址:aHR0cHM6Ly9tYXRjaDIwMjMueXVhbnJlbnh1ZS5jbi90b3BpYy8y
本题的核心代码是经过OB混淆的,可读性很差。不过网站本身也提供了反混淆的工具,所以这道题其实技术难度并不大。
一、OB反混淆
1)通过调试分析,可以很容易知道:该题目的核心代码位于 corejs/match2.js 中,文件中的代码都是经过混淆的;
2)将经过混淆的代码复制到反混淆工具中进行解析。
这一步并不轻松,因为解析过程相当漫长,如果使用猿人学的在线反混淆工具,那么网页会进入假死状态,中途还可能发生网页崩溃。这里我使用的是自己写的离线工具,原理是参考上述的在线反混淆工具,所以效果应该是一样的。
但是意外不期而至,经过20分钟左右,代码在执行 decodeObject 的时候报错了。
一番搜索无果,也没其他办法,所以就调整了下解析流程,暂且将 decodeObject 这一步跳过,继续后面的解析。
顺利完成后面的步骤后,代码缩小了些,但可读性还是很差,于是我将 decodeObject 步骤恢复,并对刚才解析后的代码进行反混淆。
第二次整个流程没再报错。之后,我又将解析后的代码反复解析了两次。
在上述操作中,前两次时间消耗都在半个小时以上,后面越来越快,直到最后代码从30000多行缩减到8000多行,当再次对结果进行反混淆时,基本是秒完的。
二、调试分析
1)用Fiddler对网页中的JS文件进行拦截,替换为我们反混淆后的代码;
2)通过简单调试,可以很容易定位到接口返回成功后的回调函数,在右侧面板中,可以看到接口返回的数据;
3)找到回调函数以后,我们即可着手将回调函数中的内容修改掉,将返回的数据存储到全局变量中,并在5页数据都收集全了以后,求和并输出(至于接口传参,包含page和token,但token具体怎么生成我们不用管,都包含在反混淆后的代码中了)。
// 变量声明:请求成功的次数
let count = 0;
// 变量声明:所有请求到的数据
let dataList = [];
// 修改后的corejs/match2.js代码,执行后会在全局定义一个名为call的接口请求函数
// ...前方代码省略
_0x1334dd = _0x5e2c92[_0x40c757](_0x3bb6a5 => {
data = (_0x3bb6a5.data['data'] || []).map(v => v.value);
dataList = [...dataList, ...data];
count++;
if (count >= 5) {
let sum = dataList.reduce((a, b) => (a + b), 0);
console.log('sum:', sum)
}
}
// ...后方代码省略
// 开始运行:循环依次发送各个页面的数据请求
for (let i = 1; i <= 5; i++) {
setTimeout(() => {
call(i) // 反混淆代码声明的接口请求函数
}, i * 200)
}
三、验证代码
将修改后的代码放在浏览器控制台执行,即可得到最终结果。