欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

【Python3爬虫】一次破解JS加密数据的记录

程序员文章站 2022-06-16 20:54:06
一、前言 本文是一次破解某网站 JS 加密数据的记录,网址为: https://www.qimingpian.cn/finosda/event/einvestment 要获取的是本页面上的投资事件信息,首先可以确定的是数据是通过 AJax 来传输的,并非直接写在网页源码中的。 二、步骤 1.抓包 打 ......

一、前言

  本文是一次破解某网站 js 加密数据的记录,网址为:

  要获取的是本页面上的投资事件信息,首先可以确定的是数据是通过 ajax 来传输的,并非直接写在网页源码中的。

 

二、步骤

1.抓包

  打开开发者工具,刷新页面,选择 xhr 选项,可以找到如下请求信息:

  【Python3爬虫】一次破解JS加密数据的记录

  可以看到返回结果中包含有状态码“status”、返回信息“message”和加密数据“encrypt_data”,这个 encrypt_data 是一个加密了的字符串,那要怎么解密呢?往下看。

2.分析

   这里猜测解密的方法包含在某个 js 文件里了,但又不可能打开每个文件去找。所以偷个懒,按 ctrl + f 全局搜索“encrypt_data”,得到如下结果:

  【Python3爬虫】一次破解JS加密数据的记录

   搜索的结果中只有一个 js 文件,打开它并格式化,然后在这个文件中搜索“encrypt_data”,虽然有六处匹配,但还是基本可以通过上下文定位到这一处:

  【Python3爬虫】一次破解JS加密数据的记录

   这里 e.encrypt_data 就是返回的加密数据了,因而猜测上面代码中的 object(u.a) 就是解密函数!

3.调试

,  在 source 中打开上述 js 文件,在10644行打上断点,刷新网页,可以看到变量 i 就是我们前面找到的接口“investeventvip”:

  【Python3爬虫】一次破解JS加密数据的记录

  然后要做的是就是定位到 object(u.a) 对应的函数,如下图:

  【Python3爬虫】一次破解JS加密数据的记录

  可以发现 s 函数的六个参数中有五个是有默认值的,而我们只需要得到 a.a.decode(t) 的结果,然后传入 s 函数中就行了。

  继续调试,在10940行打上断点,按 f8 继续运行,然后定位到 s 对应的函数,如下图:

  【Python3爬虫】一次破解JS加密数据的记录

   这里也不用管 s 函数具体是怎么运行的,先去找 a.a.decode() 对应的函数,如下图:

  【Python3爬虫】一次破解JS加密数据的记录

 

三、解密

  通过前面的抓包、分析和调试,我们已经知道了解密的方法是什么了,但这么多的 javascript 代码,如果要全部理解并且用 python 来实现的话,会耗费掉不少的时间,这里可以选择用一种比较偷懒的方法--使用第三方库 pyexecjs 直接运行 js 代码

1.pyexecjs 简介

  pyexecjs 是来自 ruby 的 execjs 的移植。pyexecjs 自动选择最佳的运行时来评估 javascript 程序,然后将结果作为 python 对象返回。如果还没有安装这个库,可以使用 pip 命令进行安装:

pip install pyexecjs

  pyexecjs 库三个常用的方法,如下:

  • eval() 用来执行一个字符串表达式,并返回表达式的结果。
  • compile() 用来编译 javascript 代码,例如定义函数和方法。
  • call() 用来调用通过 compile() 定义的函数和方法,可以传参。

  下面是使用该库的示例,可作了解:

 1 import execjs
 2 
 3 
 4 n1 = execjs.eval("1 + 2")
 5 print(n1)  # 3
 6 
 7 ctx = execjs.compile(
 8     """
 9     function add(x, y) {
10         return x + y;
11     }
12     """
13 )
14 n2 = ctx.call("add", 3, 4)
15 print(n2)  # 7

2.使用 python 解密

  要用 pyexecjs 来进行解密,需要把前面找到的 s 函数和 decode 函数复制过来,使用 compile 进行编译,如下:

js = execjs.compile(r"""
//解密函数
function my_decrypt(t) {
    return new buffer(s("5e5062e82f15fe4ca9d24bc5", my_decode(t), 0, 0, "012345677890123", 1)).tostring("base64")
}

//解密函数依赖项
function my_decode(t) {
    c = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789+/"
    f = /[\t\n\f\r ]/g
    var e = (t = string(t).replace(f, "")).length;
    e % 4 == 0 && (e = (t = t.replace(/==?$/, "")).length),
    (e % 4 == 1 || /[^+a-za-z0-9/]/.test(t)) && l("invalid character: the string to be decoded is not correctly encoded.");
    for (var n, r, i = 0, o = "", a = -1; ++a < e; )
        r = c.indexof(t.charat(a)),
            n = i % 4 ? 64 * n + r : r,
        i++ % 4 && (o += string.fromcharcode(255 & n >> (-2 * i & 6)));
    return o
}

function s(t, e, i, n, a, s) {
    var o, r, c, l, u, d, h, p, f, v, m, g, b, y, c = new array(16843776,0,65536,16843780,16842756,66564,4,65536,1024,16843776,16843780,1024,16778244,16842756,16777216,4,1028,16778240,16778240,66560,66560,16842752,16842752,16778244,65540,16777220,16777220,65540,0,1028,66564,16777216,65536,16843780,4,16842752,16843776,16777216,16777216,1024,16842756,65536,66560,16777220,1024,4,16778244,66564,16843780,65540,16842752,16778244,16777220,1028,66564,16843776,1028,16778240,16778240,0,65540,66560,0,16842756), _ = new array(-2146402272,-2147450880,32768,1081376,1048576,32,-2146435040,-2147450848,-2147483616,-2146402272,-2146402304,-2147483648,-2147450880,1048576,32,-2146435040,1081344,1048608,-2147450848,0,-2147483648,32768,1081376,-2146435072,1048608,-2147483616,0,1081344,32800,-2146402304,-2146435072,32800,0,1081376,-2146435040,1048576,-2147450848,-2146435072,-2146402304,32768,-2146435072,-2147450880,32,-2146402272,1081376,32,32768,-2147483648,32800,-2146402304,1048576,-2147483616,1048608,-2147450848,-2147483616,1048608,1081344,0,-2147450880,32800,-2147483648,-2146435040,-2146402272,1081344), w = new array(520,134349312,0,134348808,134218240,0,131592,134218240,131080,134217736,134217736,131072,134349320,131080,134348800,520,134217728,8,134349312,512,131584,134348800,134348808,131592,134218248,131584,131072,134218248,8,134349320,512,134217728,134349312,134217728,131080,520,131072,134349312,134218240,0,512,131080,134349320,134218240,134217736,512,0,134348808,134218248,131072,134217728,134349320,8,131592,131584,134217736,134348800,134218248,520,134348800,131592,8,134348808,131584), x = new array(8396801,8321,8321,128,8396928,8388737,8388609,8193,0,8396800,8396800,8396929,129,0,8388736,8388609,1,8192,8388608,8396801,128,8388608,8193,8320,8388737,1,8320,8388736,8192,8396928,8396929,129,8388736,8388609,8396800,8396929,129,0,0,8396800,8320,8388736,8388737,1,8396801,8321,8321,128,8396929,129,1,8192,8388609,8193,8396928,8388737,8193,8320,8388608,8396801,128,8388608,8192,8396928), k = new array(256,34078976,34078720,1107296512,524288,256,1073741824,34078720,1074266368,524288,33554688,1074266368,1107296512,1107820544,524544,1073741824,33554432,1074266112,1074266112,0,1073742080,1107820800,1107820800,33554688,1107820544,1073742080,0,1107296256,34078976,33554432,1107296256,524544,524288,1107296512,256,33554432,1073741824,34078720,1107296512,1074266368,33554688,1073741824,1107820544,34078976,1074266368,256,33554432,1107820544,1107820800,524544,1107296256,1107820800,34078720,0,1074266112,1107296256,524544,33554688,1073742080,524288,0,1074266112,34078976,1073742080), t = new array(536870928,541065216,16384,541081616,541065216,16,541081616,4194304,536887296,4210704,4194304,536870928,4194320,536887296,536870912,16400,0,4194320,536887312,16384,4210688,536887312,16,541065232,541065232,0,4210704,541081600,16400,4210688,541081600,536870912,536887296,16,541065232,4210688,541081616,4194304,16400,536870928,4194304,536887296,536870912,16400,536870928,541081616,4210688,541065216,4210704,541081600,0,541065232,16,16384,541065216,4210704,16384,4194320,536887312,0,541081600,536870912,4194320,536887312), a = new array(2097152,69206018,67110914,0,2048,67110914,2099202,69208064,69208066,2097152,0,67108866,2,67108864,69206018,2050,67110912,2099202,2097154,67110912,67108866,69206016,69208064,2097154,69206016,2048,2050,69208066,2099200,2,67108864,2099200,67108864,2099200,2097152,67110914,67110914,69206018,69206018,2,2097154,67108864,67110912,2097152,69208064,2050,2099202,69208064,2050,67108866,69208066,69206016,2099200,0,2,69208066,0,2099202,69206016,2048,67108866,67110912,2048,2097154), l = new array(268439616,4096,262144,268701760,268435456,268439616,64,268435456,262208,268697600,268701760,266240,268701696,266304,4096,64,268697600,268435520,268439552,4160,266240,262208,268697664,268701696,4160,0,0,268697664,268435520,268439552,266304,262144,266304,262144,268701696,4096,64,268697664,4096,266304,268439552,64,268435520,268697600,268697664,268435456,262144,268439616,0,268701760,262208,268435520,268697600,268439552,268439616,0,268701760,266240,266240,4160,4160,262208,268435456,268701696), s = function(t) {
        for (var e, i, n, a = new array(0,4,536870912,536870916,65536,65540,536936448,536936452,512,516,536871424,536871428,66048,66052,536936960,536936964), s = new array(0,1,1048576,1048577,67108864,67108865,68157440,68157441,256,257,1048832,1048833,67109120,67109121,68157696,68157697), o = new array(0,8,2048,2056,16777216,16777224,16779264,16779272,0,8,2048,2056,16777216,16777224,16779264,16779272), r = new array(0,2097152,134217728,136314880,8192,2105344,134225920,136323072,131072,2228224,134348800,136445952,139264,2236416,134356992,136454144), c = new array(0,262144,16,262160,0,262144,16,262160,4096,266240,4112,266256,4096,266240,4112,266256), l = new array(0,1024,32,1056,0,1024,32,1056,33554432,33555456,33554464,33555488,33554432,33555456,33554464,33555488), u = new array(0,268435456,524288,268959744,2,268435458,524290,268959746,0,268435456,524288,268959744,2,268435458,524290,268959746), d = new array(0,65536,2048,67584,536870912,536936448,536872960,536938496,131072,196608,133120,198656,537001984,537067520,537004032,537069568), h = new array(0,262144,0,262144,2,262146,2,262146,33554432,33816576,33554432,33816576,33554434,33816578,33554434,33816578), p = new array(0,268435456,8,268435464,0,268435456,8,268435464,1024,268436480,1032,268436488,1024,268436480,1032,268436488), f = new array(0,32,0,32,1048576,1048608,1048576,1048608,8192,8224,8192,8224,1056768,1056800,1056768,1056800), v = new array(0,16777216,512,16777728,2097152,18874368,2097664,18874880,67108864,83886080,67109376,83886592,69206016,85983232,69206528,85983744), m = new array(0,4096,134217728,134221824,524288,528384,134742016,134746112,16,4112,134217744,134221840,524304,528400,134742032,134746128), g = new array(0,4,256,260,0,4,256,260,1,5,257,261,1,5,257,261), b = t.length > 8 ? 3 : 1, y = new array(32 * b), c = new array(0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0), _ = 0, w = 0, x = 0; x < b; x++) {
            var k = t.charcodeat(_++) << 24 | t.charcodeat(_++) << 16 | t.charcodeat(_++) << 8 | t.charcodeat(_++)
                , t = t.charcodeat(_++) << 24 | t.charcodeat(_++) << 16 | t.charcodeat(_++) << 8 | t.charcodeat(_++);
            k ^= (n = 252645135 & (k >>> 4 ^ t)) << 4,
                k ^= n = 65535 & ((t ^= n) >>> -16 ^ k),
                k ^= (n = 858993459 & (k >>> 2 ^ (t ^= n << -16))) << 2,
                k ^= n = 65535 & ((t ^= n) >>> -16 ^ k),
                k ^= (n = 1431655765 & (k >>> 1 ^ (t ^= n << -16))) << 1,
                k ^= n = 16711935 & ((t ^= n) >>> 8 ^ k),
                n = (k ^= (n = 1431655765 & (k >>> 1 ^ (t ^= n << 8))) << 1) << 8 | (t ^= n) >>> 20 & 240,
                k = t << 24 | t << 8 & 16711680 | t >>> 8 & 65280 | t >>> 24 & 240,
                t = n;
            for (var a = 0; a < c.length; a++)
                c[a] ? (k = k << 2 | k >>> 26,
                    t = t << 2 | t >>> 26) : (k = k << 1 | k >>> 27,
                    t = t << 1 | t >>> 27),
                    t &= -15,
                    e = a[(k &= -15) >>> 28] | s[k >>> 24 & 15] | o[k >>> 20 & 15] | r[k >>> 16 & 15] | c[k >>> 12 & 15] | l[k >>> 8 & 15] | u[k >>> 4 & 15],
                    i = d[t >>> 28] | h[t >>> 24 & 15] | p[t >>> 20 & 15] | f[t >>> 16 & 15] | v[t >>> 12 & 15] | m[t >>> 8 & 15] | g[t >>> 4 & 15],
                    n = 65535 & (i >>> 16 ^ e),
                    y[w++] = e ^ n,
                    y[w++] = i ^ n << 16
        }
        return y
    }(t), z = 0, b = e.length, j = 0, i = 32 == s.length ? 3 : 9;
    p = 3 == i ? i ? new array(0,32,2) : new array(30,-2,-2) : i ? new array(0,32,2,62,30,-2,64,96,2) : new array(94,62,-2,32,64,2,30,-2,-2),
        2 == s ? e += "        " : 1 == s ? i && (c = 8 - b % 8,
            e += string.fromcharcode(c, c, c, c, c, c, c, c),
        8 === c && (b += 8)) : s || (e += "\0\0\0\0\0\0\0\0");
    var f = ""
        , o = "";
    for (1 == n && (f = a.charcodeat(z++) << 24 | a.charcodeat(z++) << 16 | a.charcodeat(z++) << 8 | a.charcodeat(z++),
        m = a.charcodeat(z++) << 24 | a.charcodeat(z++) << 16 | a.charcodeat(z++) << 8 | a.charcodeat(z++),
        z = 0); z < b; ) {
        for (d = e.charcodeat(z++) << 24 | e.charcodeat(z++) << 16 | e.charcodeat(z++) << 8 | e.charcodeat(z++),
                 h = e.charcodeat(z++) << 24 | e.charcodeat(z++) << 16 | e.charcodeat(z++) << 8 | e.charcodeat(z++),
             1 == n && (i ? (d ^= f,
                 h ^= m) : (v = f,
                 g = m,
                 f = d,
                 m = h)),
                 d ^= (c = 252645135 & (d >>> 4 ^ h)) << 4,
                 d ^= (c = 65535 & (d >>> 16 ^ (h ^= c))) << 16,
                 d ^= c = 858993459 & ((h ^= c) >>> 2 ^ d),
                 d ^= c = 16711935 & ((h ^= c << 2) >>> 8 ^ d),
                 d = (d ^= (c = 1431655765 & (d >>> 1 ^ (h ^= c << 8))) << 1) << 1 | d >>> 31,
                 h = (h ^= c) << 1 | h >>> 31,
                 r = 0; r < i; r += 3) {
            for (b = p[r + 1],
                     y = p[r + 2],
                     o = p[r]; o != b; o += y)
                l = h ^ s[o],
                    u = (h >>> 4 | h << 28) ^ s[o + 1],
                    c = d,
                    d = h,
                    h = c ^ (_[l >>> 24 & 63] | x[l >>> 16 & 63] | t[l >>> 8 & 63] | l[63 & l] | c[u >>> 24 & 63] | w[u >>> 16 & 63] | k[u >>> 8 & 63] | a[63 & u]);
            c = d,
                d = h,
                h = c
        }
        h = h >>> 1 | h << 31,
            h ^= c = 1431655765 & ((d = d >>> 1 | d << 31) >>> 1 ^ h),
            h ^= (c = 16711935 & (h >>> 8 ^ (d ^= c << 1))) << 8,
            h ^= (c = 858993459 & (h >>> 2 ^ (d ^= c))) << 2,
            h ^= c = 65535 & ((d ^= c) >>> 16 ^ h),
            h ^= c = 252645135 & ((d ^= c << 16) >>> 4 ^ h),
            d ^= c << 4,
        1 == n && (i ? (f = d,
            m = h) : (d ^= v,
            h ^= g)),
            o += string.fromcharcode(d >>> 24, d >>> 16 & 255, d >>> 8 & 255, 255 & d, h >>> 24, h >>> 16 & 255, h >>> 8 & 255, 255 & h),
        512 == (j += 8) && (f += o,
            o = "",
            j = 0)
    }
    if (f = (f += o).replace(/\0*$/g, ""),
        !i) {
        if (1 === s) {
            var $ = 0;
            (b = f.length) && ($ = f.charcodeat(b - 1)),
            $ <= 8 && (f = f.substring(0, b - $))
        }
        f = decodeuricomponent(escape(f))
    }
    return f
}
""")

  然后使用 call() 方法进行调用解密,使用方法为:

js.call('my_decrypt', encrypt_data)

  不过这一步得到的结果还是使用 base64 加密后的,所以还得用 base64.b64decode() 进行解密,就能得到最终的结果了。

 

  完整代码已上传到 github