對網易雲評論 JS加密 進行破解爬取評論


爬過網易雲評論的都知道,網易雲的歌曲都是通過 <iframe> 便簽進行層層迭代,而且數據都是異步加載的,就算是使用Selenium也要進行框架的轉換,非常麻煩,且效率低下。

 

 

 

 

通過Chrome抓包得到評論的URL

 

可以看到評論的URL使用POST傳進了兩個參數,這一看就是加密過的,直接訪問肯定是進不去的,猜測應該是JS加密,要破解只能去查看JS源碼了。

在Initiator中可以看到 JS 目錄的位置,在

 

 

格式化后放到本地,查找參數關鍵字以找到相關的JS代碼,比如查找 “encSecKey”

 

運氣不錯一下就找到了,可以看到參數的值分別是bYc1x.encText,bYc1x.encSecKey,而bYc1x是由asrsea()方法傳進4個參數構建的,再查找asrsea,

得到一長串混淆的JS代碼,根本沒法解析變量的意思,但是似乎找到了加密的方式 CryptoJS.mode.CBC。

 

 

要是想完全解密經過多層混淆的代碼估計JS功底得非常深厚,所以這里取巧直接在本地輸出參數看下參數的值,然后進行反加密。

這里我使用的是 Fiddler 去替換原來的JS代碼,在控制台輸出參數的值。因為服務器的資源是先放到瀏覽器上,瀏覽器再展示給我們,所以可以替換掉服務器的代碼,輸出參數的值。

打開 Fiddler,點擊AutoResponser, 把Enable rules , Unmatched requests passthrough和 Enable Latency全部勾上。

然后刷新頁面,在下方輸入 Select Script 

 

 

找到我們需要更改的JS源碼,拖到右側AutoResponser界面。

其中左邊是你需要替換掉的JS文件,右邊是你想要應用的文件路徑。

 

 

我們想要輸出未經加密的參數,所以在源碼中添加

console.log(i3x);console.log(bkY2x(["流淚", "強"]));console.log(bkY2x(VM8E.md));console.log(bkY2x(["愛心", "女孩", "驚恐", "大笑"]));
View Code

PS:我是在沒有格式化JS代碼的時候就要添加了,格式化后會報錯變量未定義什么的,所以是直接在源碼適當的地方直接插入。報錯的可以試着換個位置插入。

 

 

然后在AutoResponse中點擊 save ,刷新網易雲的頁面,點擊控制台,會看到:

 

 

多次輸出檢驗可以后3個參數是定值,而第一個參數就包含了歌曲信息:

rid:就是歌曲的 id信息。

offset:用作評論的分頁,比如offset=100,就是從第101條評論開始。

limit:限制的評論數,上限為100,超過會變成20,限制輸出的評論數。 

其他參數暫時還沒有發現其用處。

 

部分源碼分析:提取的源碼如下:

function a(a) {
        var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
        c = "";
        for (d = 0; a > d; d += 1) e = Math.random() * b.length,
        e = Math.floor(e),
        c += b.charAt(e);
        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);
        return h.encText = b(d, g),
        h.encText = b(h.encText, i),
        h.encSecKey = c(i, e, f),
        h
    }
    function e(a, b, d, e) {
        var f = {};
        return f.encText = c(a + e, b, d),
        f
    }
    window.asrsea = d,
View Code

函數 asrsea() 傳進了4個參數,然后asrsea 調用了 函數 a() ,閱讀a()的代碼,可以知道返回的是一個長度為 16 的隨機字符串。那么我們可以給它一個定值。

再看對象 h,易知 h.encSecKey = c(i, e, f)是一個定值,最后就是帶有歌曲參數的屬性 h.encText,這個屬性是通過兩次加密后得到的。

研究加密算法后,知道 “0102030405060708” 是 vi偏移量,加密模式是 CryptoJS.mode.CBC。

 

 

 然后回到反加密的過程,這里使用python編寫解密過程。參考了網上的教程和該加密算法的加解密過程,代碼如下:

PS:需要 Crypto 包 

 

from Crypto.Cipher import AES
import base64
import json
# limit里面可以得到更多的評論,rid后加歌曲id
# 下面參數通過控制台可以得到大部分,都是定值
# offset可以
first_param = '{rid: "R_SO_4_167844", offset: "120", total: "false", limit: "100", csrf_token: ""}'
second_param = '010001'
third_param = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'
fourth_param = '0CoJUm6Qyw8W8jud'

def get_params():
    #根據該加密算法做出解密
    iv = '0102030405060708'
    first_key = fourth_param
    second_key = 16 * 'F'
    h_encText = AES_encrypt(first_param, first_key, iv)
    h_encText = AES_encrypt(h_encText, second_key, iv)
    return h_encText

def get_encSeckey():
    #這個也是定值
    encSecKey = "257348aecb5e556c066de214e531faadd1c55d814f9be95fd06d6bff9f4c7a41f831f6394d5a3fd2e3881736d94a02ca919d952872e7d0a50ebfa1769a7a62d512f5f1ca21aec60bc3819a9c3ffca5eca9a0dba6d6f7249b06f5965ecfff3695b54e1c28f3f624750ed39e7de08fc8493242e26dbc4484a01c76f739e135637c"
    return encSecKey

def AES_encrypt(text, key, iv):
    if type(text) == type(b'123'):
        #這是判斷當前變量的類型是bytes還是字符串,因為pycryptodome要        
        #求參數要是字節類型
        text = text.decode('utf-8')

    pad = 16 - len(text) % 16
    text = text + pad*chr(pad)

    iv = iv.encode('utf-8')
    key = key.encode('utf-8')
    encryptor = AES.new(key, AES.MODE_CBC, iv)
    text = text.encode('utf-8')
    encrypt_text = encryptor.encrypt(text)
    encrypt_text = base64.b64encode(encrypt_text)
    return encrypt_text

if __name__ == '__main__':
    params = get_params()
    encSecKey = get_encSeckey()
    print(params.decode('utf-8'))
    print(encSecKey)
View Code

 

 

參考文章:

  知乎:https://www.zhihu.com/question/36081767/answer/386606315

  csdn:https://blog.csdn.net/weixin_40444270/article/details/81260638


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM