openlaw.cn首次打开时通过一段js生成两个加密cookie。这是该网站惟一的反爬手段。

测试链接
http://openlaw.cn/justic/courts

目标

第一次打开得到加密js, 其计算两个cookie: s_token、c_token。带上这两个cookie后可以正常访问。

分析过程

js可以分成下面几个部分

  1. 数据部分
    var _001var _005是数据部分(这里只用到_003,作为key)

  2. 第一个eval
    eval(…) 中代码解密后内容var _$=['openlaw.cn','412237401@qq.com'];var a=_$[0];var b=_$[1];,猜测是作者联系方式,没用。

  3. part3(固定)

    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
    $ = ~ [];
    $ = {
    ___: ++$,
    $$$$: (![] + "")[$],
    __$: ++$,
    $_$_: (![] + "")[$],
    _$_: ++$,
    $_$$: ({} + "")[$],
    $$_$: ($[$] + "")[$],
    _$$: ++$,
    $$$_: (!"" + "")[$],
    $__: ++$,
    $_$: ++$,
    $$__: ({} + "")[$],
    $$_: ++$,
    $$$: ++$,
    $___: ++$,
    $__$: ++$
    };
    $.$_ = ($.$_ = $ + "")[$.$_$] + ($._$ = $.$_[$.__$]) + ($.$$ = ($.$ + "")[$.__$]) + ((!$) + "")[$._$$] + ($.__ = $.$_[$.$$_]) + ($.$ = (!"" + "")[$.__$]) + ($._ = (!"" + "")[$._$_]) + $.$_[$.$_$] + $.__ + $._$ + $.$;
    // $.$_='constructor';
    $.$$ = $.$ + (!"" + "")[$._$$] + $.__ + $._ + $.$ + $.$$;
    // $.$$='return';
    $.$ = ($.___)[$.$_][$.$_];
    // $.$=0['constructor']['constructor']

    这一部分用于初始化$对象(一个字典),用于下面还原加密算法

  4. 还原算法并执行
    根据$对象还原加密代码,并通过0['constructor']['constructor'](${code})()运行。
    这部分代码结构为$.$($.$(...)())(),中间省略部分的代码eval后为

    1
    return"\166a\162\40\147et\107lobal=fu\156ct\151o\156(){\151f(t\171\160eof\40\163elf!=='u\156def\151\156ed'){\162etu\162\156\40\163elf};\151f(t\171\160eof\40\167\151\156do\167!=='u\156def\151\156ed'){\162etu\162\156\40\167\151\156do\167};\151f(t\171\160eof\40\147lobal!=='u\156def\151\156ed'){\162etu\162\156\40\147lobal};t\150\162o\167\40\156e\167\40\105\162\162o\162('u\156able\40to\40locate\40\147lobal\40ob\152ect')};fu\156ct\151o\156\40_a(\163)\40{\162etu\162\156\40\163.\163ub\163t\162\151\156\147(1,\403).co\156cat('\147').co\156cat(\163.\163ub\163t\162\151\156\147(10,\4011)).co\156cat('\152').co\156cat(\163.\163ub\163t\162\151\156\147(5,\409)).co\156cat('a').co\156cat(\163.\163ub\163t\162\151\156\147(1)).co\156cat('f').co\156cat(\163.\163ub\163t\162\151\156\147(7,\4015));};\166a\162\40_\163\167\151tc\150=fal\163e;\151f((\147et\107lobal()===\167\151\156do\167)){_\163\167\151tc\150=t\162ue}el\163e{_\163\167\151tc\150=fal\163e};\151f(_\163\167\151tc\150){docu\155e\156t.coo\153\151e='\163_to\153e\156='+_003;docu\155e\156t.coo\153\151e='c_to\153e\156='+_a(_003);\163et\124\151\155eout(\"locat\151o\156.\162eload();\",100);}"

    还原后为

    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
    var getGlobal = function() {
    if (typeof self !== 'undefined') {
    return self
    };
    if (typeof window !== 'undefined') {
    return window
    };
    if (typeof global !== 'undefined') {
    return global
    };
    throw new Error('unable to locate global object')
    };
    function _a(s) {
    return s.substring(1, 3).concat('g').concat(s.substring(10, 11)).concat('j').concat(s.substring(5, 9)).concat('a').concat(s.substring(1)).concat('f').concat(s.substring(7, 15));
    };
    var _switch = false;
    if ((getGlobal() === window)) {
    _switch = true
    } else {
    _switch = false
    };
    if (_switch) {
    document.cookie = 's_token=' + _003;
    document.cookie = 'c_token=' + _a(_003);
    setTimeout("location.reload();", 100);
    }

    上面这段代码中除function _a是变化的, 其他代码都是一样的,所以可以根据这个特征截取变化的函数。

总结

这个网站的反爬比较一般,除去混淆,其加密核心只是对key进行了一种特定的运算,即_a函数。它通过动态变化_a函数中各函数调用的参数实现加密动态变化。另外在释放代码时使用的不是常用的eval函数,而是通过对象构造函数的构造函数0['constructor']['constructor'](${code})(), 这种方式比较少见。