0%

js混淆-猿人学第10题

猿人学第十题

先说一下做这题的感受,就像是我们的目标是翻越这座山,但在翻越这座山的时候会遇见很多座山,翻越一座又来一座,最后通往山顶的时候发现是有捷径可以走的,但是中间过程遇到的山让我受益良多,十分推荐这道题。

1
https://match.yuanrenxue.cn/match/10

获取url的流程

这里简单说一下这道题的思路,我这道题做了三个星期才搞定的,慢慢来。考点是这三个。

  • 对极其复杂的 js的阅读能力
  • 对控制流平坦化的处理能力
  • 对js中多种动态参数的处理能力

首先拿到10这个源代码,请求几次,发现只有yuanrenxue_59这个参数是动态的,其他的都是静态的。

这题有很多debugger可以使用油猴脚本进行绕过

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// ==UserScript==
// @name yrx10-debug
// @namespace http://tampermonkey.net/
// @version 0.1
// @description try to take over the world!
// @author f19t
// @match https://match.yuanrenxue.cn/match/10
// @grant none
// @run-at document-start
// ==/UserScript==

function_hook=Function;
Function=function(a){
if (a!=='debugger') {return function_hook(a)}
}
Function.prototype.constructor_hook=Function.prototype.constructor;
Function.prototype.constructor=function(x){
if(x!=="debugger"){
return Function.prototype.constructor_hook(x)
}
}
eval_hook=eval;
eval=function(a){
if (a!=='debugger') {
return eval_hook(a)
}
}
setInterval=function(){};
console.log_hook=console.log;

首先看一下这个html

可以发现他的执行顺序是先执行rs.js、rsnkw2ksph、和匿名函数。
我们可以把匿名函数抠出来单独看一下。


可以看到大多数都是函数不会执行的,唯一可以执行的是这里的while,这里考点:对极其复杂的js的阅读能力

这个地方的while会调用下面的yuanrenxue_31,为了更好的调试,大家可以把if-else还原成swich,因为他取值是数组下标,数组是不变得。
这里考点:对控制流平坦化的处理能力。
其实这里是可以合并这些case的。比如调用yuanrenxue_31(5)
然后5这个整体总共访问了 比如case 32 68 56 44 68。期间做了自增自减 没关系,再比如中间又调用了yuanrenxue_31(5) 把他的走过的流程取出来就可以了。有兴趣的可以尝试一下。

跟进到yuanrenxue_31的里面有个最关键的位置,是解密rsnkw2ksph这个文件的,好像自始至终rs.js我是没有用到的。

可以写成py代码

这里得到yuanrenxue_18之后,他是调用了

1
yuanrenxue_31(78, yuanrenxue_18);

跟进去会发现他会执行这个.call,也就是eval执行这个字符串,不知道我的表述对不对。
我在他执行之前进行了格式化代码和ast注入了代码。

这里的yuanrenxue_62就是我们的yuanrenxue_18,因为

我是注入的这么两段代码
第一处

第二处在js文件最后注入

然后使用jsdom去获取bbx的结果就可以了。这里考点:对js中多种动态参数的处理能力

简化流程

其实做出这道题之后是可以简化流程的,可以获取yuanrenxue_59和rsnkw2ksph用来生成vm代码,获取offset,然后直接使用ast注入代码,使用jsdom直接运行vm代码就可以了。获取数据留念。

纪念

通过纪念。