爬虫漫游指南:加速乐__jsl_clearance破解

爬虫漫游指南

JS破解之加速乐

本文会介绍加速乐cookie中的__jsl_clearance的生成方式。纯粹技术讨论,如果侵害到任何人的利益,请联系本人邮箱[email protected],会立刻删除。

如何识别加速乐

使用加速乐的网站,在没有cookie的情况下首次访问返回的状态码是521,这是一个非常有特征的状态码,看到521八成就是加速乐了,这个状态码在RFC2616里都没写,目前也就见过他家用了。

其次,就是cookie的名字,__jsl_clearance,说不定读者老爷就是搜这个关键词才看到这篇文章的。jsl很好理解嘛,就是加速乐的拼音首字母。

js分析

上面说到首次访问会返回521状态码,而返回的内容,是一段js,也正是这段js生成了__jsl_clearance这个cookie。这段js每次都有些许差异,这里就拿某一次抓包的来做讲解。返回是js是一行的,为了便于查看,这里做了代码格式化。

var x = "Sep@d@@06@href@p@@7@function@createElement@@@while@captcha@@false@@3@substr@471@length@Expires@Path@new@search@catch@e@@for@match@@36@@@@var@attachEvent@2FN@@firstChild@document@@@location@window@@try@JgSe0upZ@fromCharCode@30@@29@RegExp@https@08@@@0@replace@pathname@1y@1500@chars@addEventListener@onreadystatechange@else@0xFF@setTimeout@@@f@String@@challenge@DOMContentLoaded@@innerHTML@if@Sun@Zz@@toString@8@19@Array@g@@@@reverse@k@hTpB3@charAt@@@@1@@@__jsl_clearance@join@return@@@2@GMT@a@0xEDB88320@rOm9XFMtA3QKV7nYsPGT4lifyWwkq5vcjH2IdxUoCbhERLaz81DNB6@@@@@eval@@x@D@charCodeAt@1569742206@@toLowerCase@div@@split@parseInt@@cookie@".replace(/@*$/, "").split("@"),
y = "1f 62=9(){35('22.5=22.2i+22.14.2h(/[\\?|&]e-3b/,\'\')',2k);1k.61='4g=5e.k|2g|'+(9(){1f h=[9(62){4i 62},9(h){4i h},9(62){4i 59('39.27('+62+')')},9(62){18(1f h=2g;h<62.10;h++){62[h]=5k(62[h]).3j(1b)};4i 62.4h('')}],62=['2j',[[8]+[(-~[]<<-~-~{})]],'5b',(+[~~![], ~~![]]+[]+[[]][2g]).49(-~-~{}),[[-~[50]]+[(-~[]<<-~[])]],[(3k+[]+[[]][2g])+[(-~[]<<-~[])]],'%1h',[{}+[[]][2g]][2g].49(-~{}-~-~{}+(-~[]<<-~[])-~[(-~[]<<-~[])]),[[(-~[]<<-~[])]+[(-~{}+[50])/[50]],[(-~[]<<-~[])]+[~~'']],'47',[[-~[50]]+[-~[50]],[(-~[]<<-~[])]+(3k+[]+[[]][2g])],[[8]+[(-~{}+[50])/[50]]],'3h%50',[[(-~{}+[50])/[50]]+[(-~{}+[50])/[50]]],'6',[-~[50]],'48',[[8]+[8]],'%',[-~[50]],'5c'];18(1f 20=2g;20<62.10;20++){62[20]=h[[4d,50,4d,2g,i,50,4d,2g,i,4d,i,50,4d,50,4d,2g,4d,50,4d,2g,4d][20]](62[20])};4i 62.4h('')})()+';11=3g, 2a-1-40 2d:28:4 51;12=/;'};3f((9(){25{4i !!23.31;}15(16){4i g;}})()){1k.31('3c',62,g)}33{1k.1g('32',62)}",
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(_) {}

一个很有用的Tips:注意转义字符。

乍一看很吓人,跟乱码似的,稍微读一下,可以发现,就是把代码藏在字符串中,用某种方式取出来,然后拼好了eval一下,cookie就出来了,是不是惊人的简单。想要知道eval了什么内容,最简单的方法就是把eval换成console.log,在浏览器控制台替换eval后运行一下,就能得到如下的代码:

var _62 = function() {
    setTimeout('location.href=location.pathname+location.search.replace(/[\?|&]captcha-challenge/,'')', 1500);
    document.cookie = '__jsl_clearance=1569742206.471|0|' + (function() {
        var _h = [function(_62) {
            return _62
        },
        function(_h) {
            return _h
        },
        function(_62) {
            return eval('String.fromCharCode(' + _62 + ')')
        },
        function(_62) {
            for (var _h = 0; _h < _62.length; _h++) {
                _62[_h] = parseInt(_62[_h]).toString(36)
            };
            return _62.join('')
        }],
        _62 = ['1y', [[7] + [( - ~ [] << -~ - ~ {})]], 'x', ( + [~~ ! [], ~~ ! []] + [] + [[]][0]).charAt( - ~ - ~ {}), [[ - ~ [2]] + [( - ~ [] << -~ [])]], [(8 + [] + [[]][0]) + [( - ~ [] << -~ [])]], '%2FN', [{} + [[]][0]][0].charAt( - ~ {} - ~ - ~ {} + ( - ~ [] << -~ []) - ~ [( - ~ [] << -~ [])]), [[( - ~ [] << -~ [])] + [( - ~ {} + [2]) / [2]], [( - ~ [] << -~ [])] + [~~'']], 'k', [[ - ~ [2]] + [ - ~ [2]], [( - ~ [] << -~ [])] + (8 + [] + [[]][0])], [[7] + [( - ~ {} + [2]) / [2]]], 'Zz%2', [[( - ~ {} + [2]) / [2]] + [( - ~ {} + [2]) / [2]]], 'p', [ - ~ [2]], 'hTpB3', [[7] + [7]], '%', [ - ~ [2]], 'D'];
        for (var _20 = 0; _20 < _62.length; _20++) {
            _62[_20] = _h[[1, 2, 1, 0, 3, 2, 1, 0, 3, 1, 3, 2, 1, 2, 1, 0, 1, 2, 1, 0, 1][_20]](_62[_20])
        };
        return _62.join('')
    })() + ';Expires=Sun, 29-Sep-19 08:30:06 GMT;Path=/;'
};
if ((function() {
    try {
        return !! window.addEventListener;
    } catch(e) {
        return false;
    }
})()) {
    document.addEventListener('DOMContentLoaded', _62, false)
} else {
    document.attachEvent('onreadystatechange', _62)
}

这下就更清晰了,稍微会一丁点js的人都能看懂,document.cookie = '__jsl_clearance=1569742206.471|0|'这基本已经喂到嘴边了。直接复制进浏览器跑一下就能拿到cookie了。

感觉这段分析写的毫无含金量 (*-ω-) 不知道讲清楚了没。

如何获取cookie

在实际写爬虫的时候,光分析js是没用的,关键是如何把它跑起来,拿到返回值,主要有以下几种方法:

  • 模拟浏览器(如puppeteer)执行js,获取页面cookie;
  • PhantomJS,虽然这个项目已经黄了,但还是很好用的,像加速乐这样的用PhantomJS还是很好用的;
  • 在python中执行js,如execjs,js2py等,比较推荐execjs,配合node食用风味更佳;
  • nodejs中执行,和python中执行大同小异,但是可以用node部署一个服务,然后python来调用,而不是直接在python中执行js。

我更青睐下面两种方法,资源开销相对更低一点,速度也更快。

puppeteer和phantom这些简单无脑,各种初学者教程里都能看到,这里就不废话了,主要讲一下如何使用node获取cookie。

node和浏览器最大的区别,就是浏览器有window这个全局对象,window底下有茫茫多的东西,比如上面代码中的document.cookie,其实就是window.document.cookie,还有上面代码中的addEventListenerattachEvent,都是如此。而node底下是没有window和那一大坨东西的,只有一个空空如也的global。所以,浏览器下的js需要加工一下才能在node中执行。

首先,声明一个全局变量document,否则node中不会自带这个变量

global.document = {}

然后,那行setTimeout,一看就是生成完cookie做自动跳转的,获取cookie用不着,直接干掉。

最后的if-else,是判断一些条件然后执行_62这个函数来生成cookie的,花里胡哨的直接干掉,换成_62();执行以下就行了。最后的最后,得把cookie输出出来看一下,所以加上console.log(document.cookie)

改造完之后效果如下:

global.document = {}
var _62 = function() {
    // 干掉setTimeout那行,其余不变
};
_62();
console.log(document.cookie)

node执行一下,得到输出如下

__jsl_clearance=1569742206.471|0|1yJxNwR%2FNOqkkxsLZz%2Bp3hTpB3M%3D;Expires=Sun, 29-Sep-19 08:30:06 GMT;Path=/;

完美,搞定。

总结

其实我上面那种改动方法太粗暴了,实际写爬虫的时候,获取到js之后总不能一个个的手工修改吧,所以最好是有个简单通用,方便自动修改的改法。这里就讲一下思路,有兴趣的小老弟可以自己写一下,写完就不是小老弟,可以化身大佬了。

要在node中执行浏览器js最重要的就是处理用到的浏览器变量。上文中cookie变量只是一个字符串,不需要费什么心,真正需要费心的是addEventListenerattachEvent,所以我偷懒直接把他们干掉了。总之就随便写2个函数,无论如何能把_62();执行起来就OK了。上面费力气把js还原出来也是为了知道其中用到了哪些变量,知道了才能提前声明定义或者hook各种有针对性的操作。提前声明写好后和获取到的js拼接起来,再丢进node里跑一下,就能正常运行并拿到cookie啦。

发布了24 篇原创文章 · 获赞 39 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/shayuchaor/article/details/101762668