Python爬取js加密后的图片

 

  在使用Python想爬取某网站的图片,使用Python的requests模块的get()后,获取到了html文件。结果发现图片的src是动态加载,而且还加密了。

在img标签下发现一个className=lazy:

Python爬取js加密后的图片

 

 

在script标签下发现:

Python爬取js加密后的图片

 

 

  查阅资料后发现这是一个lazyload插件的启动代码。

  在f12检查元素的资源下找到lazyload.js,可以发现:

Python爬取js加密后的图片

 

  在$.ajax()中可以看到参数url是密文的地址,success的匿名函数的参数res是访问url后的返回结果,可以看到该方法中调用了一个desDecrypt(res),解密密文的函数,返回结果是base64加密后的一段字符串。

 

 

  图片的密文被放在一个.txt的文件中,利用抓包工具可发现一个encrypt.min.js的js文件,格式化后如下

eval(function(p, a, c, k, e, r) {
    e = function(c) {
        return (c < a ? '' : e(parseInt(c / a))) + ((c = c % a) > 35 ? String.fromCharCode(c + 29) : c.toString(36))
    }
    ;
    if (!''.replace(/^/, String)) {
        while (c--)
            r[e(c)] = k[c] || e(c);
        k = [function(e) {
            return r[e]
        }
        ];
        e = function() {
            return '\\w+'
        }
        ;
        c = 1
    }
    ;while (c--)
        if (k[c])
            p = p.replace(new RegExp('\\b' + e(c) + '\\b','g'), k[c]);
    return p
}('1 e="B";1 8="G";f N(a){1 5=0.2.3.4(8);1 7=0.2.3.4(e);9 b=0.u.v(a,7,{l:5,6:0.6.n,o:0.p.q,r:0.k.m});1 x=b.h();d x}f F(a){1 5=0.2.3.4(8);1 7=0.2.3.4(e);9 b=0.u.y(a,7,{l:5,6:0.6.n,o:0.p.q,r:0.k.m});d 0.2.3.J(b)}f C(a){1 5=0.2.3.4(8);1 7=0.2.3.4(e);9 b=0.u.v(a,7,{l:5,6:0.6.n,o:0.p.q,r:0.k.m});d b.A.h(0.2.z)}f D(a){a=a.E(/\\s*/g,"");1 5=0.2.3.4(8);9 b=0.2.3.4(e);9 c=0.H.y({A:0.2.z.4(a)},b,{l:5,6:0.6.n,o:0.p.q,r:0.k.m});d c.h(0.2.3)}f I(a,b){1 j=(K L()).M();1 t=0.O("i"+b+"P"+j+"Q").h();1 w=a+"?j="+j+"&t="+t;d w}', 53, 53, 'CryptoJS|let|enc|Utf8|parse|tmpiv|mode|key|base_lv|var||||return|asc_key|function||toString||ts|format|iv|OpenSSL|CBC|padding|pad|Pkcs7|formatter||token|AES|encrypt|result_url|result|decrypt|Base64|ciphertext|jeH3O1VX|desEncrypt|desDecrypt|replace|aesDecrypt|nHnsU4cX|DES|desVideoUrl|stringify|new|Date|getTime|aesEncrypt|MD5|am|IronMan'.split('|'), 0, {}))

  显然上面的js代码是加密过后的,百度搜索js在线解密,可以恢复原来的js代码,发现其中有个desDecypt(a)的方法,也就是上面提到的方法,该方法用于解密密文,该js插件依赖于crypto-js.js文件。

let asc_key = "********"; //8位秘钥
let base_lv = "********";    //8位秘钥偏移量

function desDecrypt(a) {
    a = a.replace(/\s*/g, "");
    let tmpiv = CryptoJS.enc.Utf8.parse(base_lv);
    var b = CryptoJS.enc.Utf8.parse(asc_key);
    var c = CryptoJS.DES.decrypt({
        ciphertext: CryptoJS.enc.Base64.parse(a)
    }, b, {
        iv: tmpiv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7,
        formatter: CryptoJS.format.OpenSSL
    });
    return c.toString(CryptoJS.enc.Utf8)
}

 

 

  那么js插件加密的密文怎么解码呢?查阅资料发现在python中有一个可以调用js文件的模块PyexecJs

  在cmd使用 pip install PyexecJs 安装模块

import execjs
import base64

#实例化一个node对象
node = execjs.get()
#要调用的js文件
file = 'mm.js'
#编译js文件
cjs = node.compile(open(file, encoding='utf-8').read())
#js中要执行的函数 其中res就是密文
js = 'desDecrypt("{0}")'.format(res)'
#执行js代码
dec_data = cjs.eval(js)
#将解密后的明文执行base64解码,并生成图片
b64_data = dec_data.split(';base64,')[1]
data = base64.b64decode(b64_data)
with open(filename,'wb') as file:
    file.write(data)

   事先把desDecrypt(a)函数和crypto-js.js的核心代码写入mm.js,方便execjs模块的调用。

 

大体思路就如上所述~~

 

上一篇:java – 在AES解密时,给定Final Block未正确填充


下一篇:SHA512哈希在android,php和javascript上有所不同