最近在爬某网站的时候,发现不能网页不能返回正常的html
1.分析js
通过抓包发现,请求状态码为521,该网站会返回的是一段js内容,每次返回的js都会有些许的差异,
这里就用某次抓包的内容作为示例:
<javascript>
var x = "@@@toString@@attachEvent@replace@@if@@String@@href@RegExp@charCodeAt@@createElement@toLowerCase@chars@catch@@@JgSe0upZ@1@new@qiR4@a@return@d@@cpJRpX@@try@@20@@@fromCharCode@B5@else@@GMT@23@f@@Apr@3@H8@@@@@@window@var@Array@1587610665@pathname@onreadystatechange@parseInt@@while@match@split@3D@@@36@rOm9XFMtA3QKV7nYsPGT4lifyWwkq5vcjH2IdxUoCbhERLaz81DNB6@false@search@charAt@g@0xFF@e@reverse@@@@@function@ZV@@https@substr@416@45@innerHTML@4@challenge@DOMContentLoaded@captcha@@@@@2@Path@addEventListener@Expires@@57@03@@@@for@K@document@div@Thu@eval@location@@firstChild@@join@setTimeout@8@@0@@1500@cookie@length@@__jsl_clearance@0xEDB88320".replace(/@*$/, "").split("@"),
y = "T 1A=1l(){1W('1R.d=1R.W+1R.1b.7(/[\\?|&]1w-1u/,\\'\\')',23);1N.24='27=V.1q|21|'+(1l(){T 5=[1l(1A){s 1A},1l(5){s 5},1l(1A){1L(T 5=21;5<1A.25;5++){1A[5]=10(1A[5]).4(18)};s 1A.1V('')}],1A=[(-~{}+(-~-~[])*[(-~!![[]][(+!!{})]<<-~-~[])]+[]+[]),(~~{}+[]),[1X],(-~-~[]+[]+[[]][21]),[-~[-~-~[]]],((-~{}+[-~[]-~[]])/[-~[]-~[]]+[]+[]),[-~!![[]][(+!!{})]],[-~!![[]][(+!!{})]]+(-~-~[]+[]+[[]][21]),(((+!!{})|-~-~[])+(-~[]-~[])*[-~[]-~[]]+[]+[]),[-~!![[]][(+!!{})]]+(~~{}+[]),[-~!![[]][(+!!{})]]+[-~!![[]][(+!!{})]],[-~!![[]][(+!!{})]]+[-~[-~-~[]]],[(-~[]<<-~[])+L],(1t+[[]][21])];1L(T a=21;a<1A.25;a++){1A[a]=5[[o,21,o,1B,o,1B,o,21,1B,21,o,21,1B,o][a]]([(+{}+[]+[]).1c(-~[]-~[]),'1M',[(-~-~[]+[]+[[]][21])+(((+!!{})|-~-~[])+(-~[]-~[])*[-~[]-~[]]+[]+[])],'D','q%15',[(-~-~[]+[]+[[]][21])+(((+!!{})|-~-~[])+(-~[]-~[])*[-~[]-~[]]+[]+[]),[-~!![[]][(+!!{})]]+[-~[-~-~[]]]],[(-~-~[]+[]+[[]][21])+[1X]],[(-~-~[]+[]+[[]][21])+(((+!!{})|-~-~[])+(-~[]-~[])*[-~[]-~[]]+[]+[]),[-~!![[]][(+!!{})]]+(-~-~[]+[]+[[]][21])],'1m','v',((-~{}+[-~[]-~[]])/[-~[]-~[]]+[]+[]),'M',((-~{}+[-~[]-~[]])/[-~[]-~[]]+[]+[]),[-~[-~-~[]]]][1A[a]])};s 1A.1V('')})()+';1E=1P, H-K-z 1H:1G:1r G;1C=/;'};9((1l(){x{s !!S.1D;}k(1f){s 1a;}})()){1N.1D('1v',1A,1a)}E{1N.6('X',1A)}",
f = function (x, y) {
var a = 0,
b = 0,
c = 0;
x = x.split("");
y = y || 99;
while ((a = x.shift()) && (b = a.charCodeAt(0) - 77.5)) c = (Math.abs(b) < 13 ? (b + 48.5) : parseInt(a, 36)) + y * c;
return c
},
z = f(y.match(/\w/g).sort(function (x, y) {
return f(x) - f(y)
}).pop());
while (z++) try {
eval(y.replace(/\b\w+\b/g, function (y) {
return x[f(y, z) - 1] || ("_" + y)
}));
break
} catch (_) {} </javascript>
看着像是乱码一样。
解决:1.将这对标签去掉
2.将代js中的eval替换为return或者console.log
3.将替换后的代码放到node环境,或者浏览器的console里面去运行就可以得到加密后的代码
如下:
var _1A = function () {
setTimeout('location.href=location.pathname+location.search.replace(/[\?|&]captcha-challenge/,\'\')', 1500);
document.cookie = '__jsl_clearance=1587610665.416|0|' + (function () {
var _5 = [function (_1A) {
return _1A
}, function (_5) {
return _5
}, function (_1A) {
for (var _5 = 0; _5 < _1A.length; _5++) {
_1A[_5] = parseInt(_1A[_5]).toString(36)
};
return _1A.join('')
}],
_1A = [(-~{} + (-~-~[]) * [(-~!![
[]
][(+!!{})] << -~-~[])] + [] + []), (~~{} + []), [8], (-~-~[] + [] + [
[]
][0]), [-~[-~-~[]]], ((-~{} + [-~[] - ~[]]) / [-~[] - ~[]] + [] + []), [-~!![
[]
][(+!!{})]],
[-~!![
[]
][(+!!{})]] + (-~-~[] + [] + [
[]
][0]), (((+!!{}) | -~-~[]) + (-~[] - ~[]) * [-~[] - ~[]] + [] + []), [-~!![
[]
][(+!!{})]] + (~~{} + []), [-~!![
[]
][(+!!{})]] + [-~!![
[]
][(+!!{})]],
[-~!![
[]
][(+!!{})]] + [-~[-~-~[]]],
[(-~[] << -~[]) + 3], (4 + [
[]
][0])
];
for (var _a = 0; _a < _1A.length; _a++) {
_1A[_a] = _5[[1, 0, 1, 2, 1, 2, 1, 0, 2, 0, 1, 0, 2, 1][_a]]([(+{} + [] + []).charAt(-~[] - ~[]), 'K', [(-~-~[] + [] + [
[]
][0]) + (((+!!{}) | -~-~[]) + (-~[] - ~[]) * [-~[] - ~[]] + [] + [])], 'B5', 'qiR4%3D', [(-~-~[] + [] + [
[]
][0]) + (((+!!{}) | -~-~[]) + (-~[] - ~[]) * [-~[] - ~[]] + [] + []), [-~!![
[]
][(+!!{})]] + [-~[-~-~[]]]],
[(-~-~[] + [] + [
[]
][0]) + [8]],
[(-~-~[] + [] + [
[]
][0]) + (((+!!{}) | -~-~[]) + (-~[] - ~[]) * [-~[] - ~[]] + [] + []), [-~!![
[]
][(+!!{})]] + (-~-~[] + [] + [
[]
][0])], 'ZV', 'cpJRpX', ((-~{} + [-~[] - ~[]]) / [-~[] - ~[]] + [] + []), 'H8', ((-~{} + [-~[] - ~[]]) / [-~[] - ~[]] + [] + []), [-~[-~-~[]]]
][_1A[_a]])
};
return _1A.join('')
})() + ';Expires=Thu, 23-Apr-20 03:57:45 GMT;Path=/;'
};
if ((function () {
try {
return !!window.addEventListener;
} catch (e) {
return false;
}
})()) {
document.addEventListener('DOMContentLoaded', _1A, false)
} else {
document.attachEvent('onreadystatechange', _1A)
}
这里就很明显了,document.cookie = ‘__jsl_clearance=1587610665.416|0|’ + …
2.改写
方式1.
这段代码里面有window对象,而在node环境下没有window对象
比如上面代码中的document.cookie,其实就是window.document.cookie,还有上面代码中的addEventListener和attachEvent,都是如此。而node底下是没有window和那一大坨东西的,只有一个空空如也的global。所以,浏览器下的js需要加工一下才能在node中执行
所以可以让window=global,其他的就自己去改
方式二
最后的if-else是判断一些条件然后执行这个函数,生成cookie,这里我们直接去掉,然后把上面的setTimeout也去掉,就扣除了我们的代码。直接运行函数就可以得到__jsl_clearance
但是这里是运行出来都是固定的,而网页都是动态返回的。所以我们还要对代码进行加工一下,
如下:
f = function (x, y) {
var a = 0,
b = 0,
c = 0;
x = x.split("");
y = y || 99;
while ((a = x.shift()) && (b = a.charCodeAt(0) - 77.5)) c = (Math.abs(b) < 13 ? (b + 48.5) : parseInt(a, 36)) + y * c;
return c
}
function getJsl(x,y) {
x = x.replace(/@*$/,"").split("@")
var z = f(y.match(/\w/g).sort(function (x, y) {
return f(x) - f(y)
}).pop());
var data = "";
var initZ = z;
while (data.indexOf("document.cookie='__jsl") == -1 && z++ - initZ < 20) {
data = y.replace(/\b\w+\b/g, function (y) {
return x[f(y, z) - 1] || ("_" + y)
});
};
return eval(data.slice(data.indexOf("'__jsl_clearance"), data.indexOf("+';Expires")));
}
每次获取到网页返回的状态玛为521的js中的var x="",y=""
将x,y这两个值传入getJsl函数就可以了。