【python爬虫】js逆向分析及AES解密

一、原理简述:

1.首先查看需要获取的数据即热门评论是否在源代码中,如果在源代码中就可以直接xpath等方式进行抓取

2.但是发现在网页和框架源代码里面都无法搜到评论内容,此时,使用网络抓包工具即:查看network中的XHD,在js代码中:get?csrf_token=中找到了hotComments

【python爬虫】js逆向分析及AES解密_第1张图片

3.同时可以在headers里得到get包里请求的url,在payload中可以看到传递了两个加密的参数:params,encSecKey,说明真实的参数params是被加密了,网页收到后会根据这个key还原真实的参数,还原出来之后再去做解锁呀,查询等各种的操作

4.所以我们爬评论的话,首先需要想办法找到没加密之前数据以及加密过程,然后在我们的程序里来模拟网易的加密过程,进行手工加密,加密完成后再进行传递

5.因此,我们打开initiator逐个查找加密时是在哪个js里面

callstack为调用栈,这是一个当请求发送至get?csrf_token=时,程序经过哪些js脚本执行的过程,栈帧从下至上传递的,因此请求从底部开始调用至第一条最后发送到get?csrf_token=,因此我们可以看到调用过程

【python爬虫】js逆向分析及AES解密_第2张图片

 6.首先查看第一条即:最后执行的动作(美化一下js代码)

【python爬虫】js逆向分析及AES解密_第3张图片

7. 可以看到在此处,程序将请求send出去:

【python爬虫】js逆向分析及AES解密_第4张图片

 8.在此处打断点,刷新页面可以查看断点之前程序执行函数的所有变量,发现request请求的url并不是我们需要的get?csrf_token=,所以放开进行下一次拦截:

【python爬虫】js逆向分析及AES解密_第5张图片

9.最后找到目标js: 可以看到data被加密了,也就是说该函数所执行的为加密数据

【python爬虫】js逆向分析及AES解密_第6张图片

10.因此需要逐个回查,查看e8e的data在进入该函数前的哪个函数中的data为未加密数据,同样,在callstack中往下挨个查看data是否被加密,可以看到d8f参数依旧被加密,因此继续慢慢查找。 

【python爬虫】js逆向分析及AES解密_第7张图片

11.最终查找到这个函数的时候发现数据在此时为未加密数据,在进入t8l.be8W函数之后data进行了加密:

【python爬虫】js逆向分析及AES解密_第8张图片

 12.因此我们回到t8l.be8W,查看参数在哪个阶段进行了加密。在t8l.be8W函数处重新打断点,刷新页面(breakpoint中释放原来的端断点),同样方法找get 【python爬虫】js逆向分析及AES解密_第9张图片 13.但此时数据依旧未加密,因此执行"下一步",直到找到加密数据 

【python爬虫】js逆向分析及AES解密_第10张图片

 加密数据找到在这里:

【python爬虫】js逆向分析及AES解密_第11张图片

14.因此在此函数之前的函数打断点,重新刷新:

【python爬虫】js逆向分析及AES解密_第12张图片

i8a里是我们的真实参数,进行下一步可以看到bVj2x有数据,也就是说:当参数i8a传递进入window.asrea进行加密,执行之后得到两个参数encseckey和enctext。

【python爬虫】js逆向分析及AES解密_第13张图片

 15.接着看函数,可以看到,这两个参数被重新传递给了e8e的data中的params和encSecKey:因此,关键点找到了,我们需要的params和其实就是encText和encSecKey

e8e.data = j8b.cq8i({
                params: bVj2x.encText,
                encSecKey: bVj2x.encSecKey

二、加密过程分析:

1.接下来就是第二步,正向加密,在此之前需要逆向查找到加密函数,发现是d赋值给了windows.asrea,因此加密函数为d

【python爬虫】js逆向分析及AES解密_第14张图片

2.此时需要找到函数的参数d,e,f,g,可以查看windows.asrea函数:

var bVj2x = window.asrsea(JSON.stringify(i8a), bsR7K(["流泪", "强"]), bsR7K(Xp4t.md), bsR7K(["爱心", "女孩", "惊恐", "大笑"]));

可得:

JSON.stringify(i8a)==>d
bsR7K(["流泪", "强"])==>e
bsR7K(Xp4t.md)==>f
bsR7K(["爱心", "女孩", "惊恐", "大笑"])==>g

带入终端执行发现e,f,g为固定值

【python爬虫】js逆向分析及AES解密_第15张图片
3.分析加密函数:

    function a(a) {    //返回随机的16位字符串
        var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = "";
        for (d = 0; a > d; d += 1)   //循环16次
            e = Math.random() * b.length,   //e为随机数处理值
            e = Math.floor(e),    //取整:floor函数表示对x 的向下取整,返回≤x的最大整数
            c += b.charAt(e);     //取b的第e个数:charAt函数返回某个索引下的char值
        return c
    }
    function b(a, b) {
        var c = CryptoJS.enc.Utf8.parse(b)
          , d = CryptoJS.enc.Utf8.parse("0102030405060708")
          , e = CryptoJS.enc.Utf8.parse(a)
          , f = CryptoJS.AES.encrypt(e, c, {
            iv: d,
            mode: CryptoJS.mode.CBC
        });
        return f.toString()
    }
    function c(a, b, c) {    //一个加密算法(因为没有随机数产生,所以可以逆向)
        var d, e;
        return setMaxDigits(131),
        d = new RSAKeyPair(b,"",c),
        e = encryptedString(d, a)
    }
    function d(d, e, f, g) {
        var h = {}  //空对象
          , i = a(16);   //查看a函数
        return h.encText = b(d, g),   //h.encText返回的为params
        h.encText = b(h.encText, i),    //h.encSecKey返回的为encSecKey
        h.encSecKey = c(i, e, f),     //c由i决定,若将i固定则c固定,因此将i设置成定值
        h
    }
    function e(a, b, d, e) {
        var f = {};
        return f.encText = c(a + e, b, d),
        f
    }

4.因此需要固定encText和encSeckey:

1)获取encText

经过分析函数可知,encText进行了两次加密:

 return h.encText = b(d, g),   
 h.encText = b(h.encText, i)

首先将d和g进行函数b的运算,将返回的结果再和随机数i进行加密即为params

此时回到函数b,可知:

function b(a, b) {   
        var c = CryptoJS.enc.Utf8.parse(b)    //utf8转换
          , d = CryptoJS.enc.Utf8.parse("0102030405060708")
          , e = CryptoJS.enc.Utf8.parse(a)
          , f = CryptoJS.AES.encrypt(e, c, {   //AES加密算法
            iv: d,   //iv为AES加密的偏移量
            mode: CryptoJS.mode.CBC   //CBC加密模式
        });
        return f.toString()   //返回字符串

a为原始数据即需要加密的内容,f为AES加密算法,传递的参数为e,c,iv
e:utf转换后的a,因此推理可知c为密钥,所以b为原始密钥

因此,逆向回到第一步,return h.encText中,g和i为原始密钥,d为偏移量

2)获取encSeckey:

重点是找到i的值:

此时,在h.encText = b(h.encText, i)处打断点,刷新界面,一直放到该断点处,可以获取到i值:【python爬虫】js逆向分析及AES解密_第16张图片

5.同时在e8e.data打断点放行,可以得到该i值下的encSeckey的值:

【python爬虫】js逆向分析及AES解密_第17张图片

三、脚本撰写

注意两点:

1.构造加密函数时,由于参数的属性(按住ctrl点击函数可以查看到需要的参数),所以key要进行字节转换。

2.因为加密后数据不能被decode("utf-8")识别,不能直接转换成字符串,同时,加密内容必须为16倍数的字符串,具体原因参考AES加密规则,因此需要进行数据处理

def to_16(data):
    pad = 16-len(data) % 16
    data += chr(pad) * pad
    return data

成功爬取评论:

【python爬虫】js逆向分析及AES解密_第18张图片

你可能感兴趣的:(python爬虫,逆向工程,爬虫,python)