簡介
網址:https://music.163.com/#/song?id=1492319432
效果:破解JS加密,爬取評論
使用框架:requests
難度系數:????
一、網站分析
目標網址:https://music.163.com/#/song?id=1492319432
按 F12 進入 Network,發現評論資料都在 get?csrf_token= 這個請求中,觀察請求頭:

觀察請求頭發現該請求是一個 POST請求,表單中提交了一個 params 和 encSecKey,這兩個資料都是一串密文,只能弄清楚它的加密程序才能構造,
接下來的作業就是摸清楚這兩個引數的加密程序了!
二、JS加密
1. 除錯 JS 代碼

Ctrl+Shift+F 查找引數,進入 JS 代碼:

由于這些 JS代碼都是被丑化壓縮過的,原始的 JS代碼不適合我們觀察,因此我們有必要將丑化的 JS代碼進行美化,按下那個 **“{}”**鍵即可將丑化的 JS代碼進行美化,

在美化后的代碼里,按 Ctrl+F 查找關鍵字,找尋JS的加密程序,
2. 整理得到 JS 加密部分代碼
var bZj7c = window.asrsea(JSON.stringify(i8a), bkk7d(["流淚", "強"]), bkk7d(YR2x.md), bkk7d(["愛心", "女孩", "驚恐", "大笑"]));
e8e.data = j8b.cr9i({
params: bZj7c.encText,
encSecKey: bZj7c.encSecKey
})
!function() {
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,
window.ecnonasr = e
}();
function encryptedString(a, b) {
for (var f, g, h, i, j, k, l, c = new Array, d = b.length, e = 0; d > e; )
c[e] = b.charCodeAt(e),
e++;
for (; 0 != c.length % a.chunkSize; )
c[e++] = 0;
for (f = c.length,
g = "",
e = 0; f > e; e += a.chunkSize) {
for (j = new BigInt,
h = 0,
i = e; i < e + a.chunkSize; ++h)
j.digits[h] = c[i++],
j.digits[h] += c[i++] << 8;
k = a.barrett.powMod(j, a.e),
l = 16 == a.radix ? biToHex(k) : biToString(k, a.radix),
g += l + " "
}
return g.substring(0, g.length - 1)
}
找到 JS 的加密代碼之后就需要用 Python 來實作了,
三、JS斷點除錯
在分析 JS 代碼的時候,我們對于代碼中某些函式或者某些值不清楚,這個時候我們就可以在谷歌瀏覽器中使用斷點除錯的方式來幫助我們理解 JS 代碼,
下面簡單介紹一下斷點除錯的步驟:
1. 打斷點


在箭頭指向的位置點擊一下即代表打下了一個斷點,
2. 重繪網頁

回到原網頁中,重繪網頁,此時可以發現網頁沒有全部加載,這是因為JS代碼只運行到我們打下斷點的位置就沒有運行了,
3. 觀察值

此時在右側即可發現運行到當前位置時各個變數的值,此時即可對值進行分析,
4. 單步除錯

打下另一個斷點后,點擊箭頭指向處按鈕即可運行至下一個斷點處,
四、Python 構造加密
1. 函式 a
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
}
該函式主要作用是 回傳一個隨機產生的16位字串,
def func_a(self, a):
b, c = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", ""
for d in range(a):
e = random.random() * b.__len__()
e = math.floor(e)
c += b[e]
return c
2. 函式b
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()
}
查詢了一下,這個函式的主要目的是對引數 b 以 CBC 模式進行 AES 加密,然后回傳加密后的結果,
密碼學中的高級加密標準(Advanced Encryption Standard,AES),又稱Rijndael加密法,是美國聯邦政府采用的一種區塊加密標準,
AES加密程序是在一個4×4的位元組矩陣上運作,這個矩陣又稱為“體(state)”,其初值就是一個明文區塊(矩陣中一個元素大小就是明文區塊中的一個Byte),
Python 中的 Crypto庫 實作了多種加密程序,我們可以使用它進行 AES加密,這個需要自己 pip 安裝一下:
pip install Crypto
def func_b(self, a, b):
iv = "0102030405060708"
pad: int = 16 - len(a) % 16
a += pad * chr(pad)
encrypt = AES.new(b.encode('utf-8'), AES.MODE_CBC, iv.encode())
encrypt_text = encrypt.encrypt(a.encode())
encrypt_text = base64.b64encode(encrypt_text)
return encrypt_text.decode('utf-8')
3. 函式c
function c(a, b, c) {
var d, e;
return setMaxDigits(131),
d = new RSAKeyPair(b,"",c),
e = encryptedString(d, a)
}
function encryptedString(a, b) {
for (var f, g, h, i, j, k, l, c = new Array, d = b.length, e = 0; d > e; )
c[e] = b.charCodeAt(e),
e++;
for (; 0 != c.length % a.chunkSize; )
c[e++] = 0;
for (f = c.length,
g = "",
e = 0; f > e; e += a.chunkSize) {
for (j = new BigInt,
h = 0,
i = e; i < e + a.chunkSize; ++h)
j.digits[h] = c[i++],
j.digits[h] += c[i++] << 8;
k = a.barrett.powMod(j, a.e),
l = 16 == a.radix ? biToHex(k) : biToString(k, a.radix),
g += l + " "
}
return g.substring(0, g.length - 1)
}
該函式主要實作的是對 引數a 以從后向前的方向 進行 RSA加密,
本來還是想利用 Crypto庫 進行 RSA加密 的,但是在使用的時候由于版本問題出現了一些問題,于是采用手工實作的方法進行 加密了,
RSA公開密鑰密碼體制是一種使用不同的加密密鑰與解密密鑰,“由已知加密密鑰推匯出解密密鑰在計算上是不可行的”密碼體制,
RSA演算法的原理:
加密:m^e % n = c
解密:c^d % n = m
m:原始資料;c:密文;n、e:公鑰;n、d:私鑰
def func_c(self, a, b, c):
num = pow(int(a[::-1].encode().hex(), 16), int(b, 16), int(c, 16))
return format(num, 'x')
4. 函式d
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
}
該函式的主要作用是呼叫其它的三個函式實作加密程序,
def func_d(self, d, e, f, g):
h, i = {}, func_a(16)
h['encText'] = self.func_b(d, g)
h['encText'] = self.func_b(h['encText'], i)
h['encSecKey'] = self.func_c(i, e, f)
return h
五、中途遇到的問題
開始以為 函式d 中的 變數d 為 {“csrf_token”:""},然后將該變數進行參與加密,加密結果與 JS除錯時得到的值一毛一樣,說明我們構造的函式是正確的,
但是將得到的引數帶入表單進行爬取時,給我們的回傳值卻總是:
{"msg":"引數錯誤","code":400}
心態有點炸了,
然后觀察網頁請求的 params,發現它是 256位 的,但是我們加密得到的卻是 64位 的!
這就說明我們加密的引數長度不夠啊!
經過多次斷點除錯,發現 引數d 是變化的!!!
{“csrf_token”:""} 只是它第一次的值,它的值后面還會變化,,,
多次斷點除錯后發現 d值為:
1. "{"csrf_token":""}"
2. "{"platform":"web","product":"cloudmusic","csrf_token":""}"
3. "{"rid":"R_SO_4_1492319432","threadId":"R_SO_4_1492319432","pageNo":"1","pageSize":"20","cursor":"-1","offset":"0","orderType":"1","csrf_token":""}"
4. "{"id":"1492319432","lv":-1,"tv":-1,"csrf_token":""}"
5. "{"logs":"[{\"action\":\"commentimpress\",\"json\":{\"type\":\"song\",\"cid\":3599061418,\"sourceid\":\"1492319432\"}},{\"action\":\"commentimpress\",\"json\":{\"type\":\"song\",\"cid\":3599127936,\"sourceid\":\"1492319432\"}},{\"action\":\"commentimpress\",\"json\":{\"type\":\"song\",\"cid\":3599056529,\"sourceid\":\"1492319432\"}},{\"action\":\"commentimpress\",\"json\":{\"type\":\"song\",\"cid\":3599043614,\"sourceid\":\"1492319432\"}},{\"action\":\"commentimpress\",\"json\":{\"type\":\"song\",\"cid\":3599041736,\"sourceid\":\"1492319432\"}},{\"action\":\"commentimpress\",\"json\":{\"type\":\"song\",\"cid\":3599111999,\"sourceid\":\"1492319432\"}},{\"action\":\"commentimpress\",\"json\":{\"type\":\"song\",\"cid\":3599095072,\"sourceid\":\"1492319432\"}},{\"action\":\"commentimpress\",\"json\":{\"type\":\"song\",\"cid\":3599094042,\"sourceid\":\"1492319432\"}},{\"action\":\"commentimpress\",\"json\":{\"type\":\"song\",\"cid\":3599042584,\"sourceid\":\"1492319432\"}},{\"action\":\"commentimpress\",\"json\":{\"type\":\"song\",\"cid\":3599032785,\"sourceid\":\"1492319432\"}},{\"action\":\"commentimpress\",\"json\":{\"type\":\"song\",\"cid\":3599075137,\"sourceid\":\"1492319432\"}},{\"action\":\"commentimpress\",\"json\":{\"type\":\"song\",\"cid\":3599024799,\"sourceid\":\"1492319432\"}},{\"action\":\"commentimpress\",\"json\":{\"type\":\"song\",\"cid\":3599061249,\"sourceid\":\"1492319432\"}},{\"action\":\"commentimpress\",\"json\":{\"type\":\"song\",\"cid\":3599102881,\"sourceid\":\"1492319432\"}},{\"action\":\"commentimpress\",\"json\":{\"type\":\"song\",\"cid\":3599110809,\"sourceid\":\"1492319432\"}},{\"action\":\"commentimpress\",\"json\":{\"type\":\"song\",\"cid\":3599105822,\"sourceid\":\"1492319432\"}},{\"action\":\"commentimpress\",\"json\":{\"type\":\"song\",\"cid\":3598993744,\"sourceid\":\"1492319432\"}},{\"action\":\"commentimpress\",\"json\":{\"type\":\"song\",\"cid\":3599055174,\"sourceid\":\"1492319432\"}},{\"action\":\"commentimpress\",\"json\":{\"type\":\"song\",\"cid\":3599039376,\"sourceid\":\"1492319432\"}},{\"action\":\"commentimpress\",\"json\":{\"type\":\"song\",\"cid\":3599071873,\"sourceid\":\"1492319432\"}}]","csrf_token":""}"
最后發現,當 d為
{"rid":"R_SO_4_1492319432","threadId":"R_SO_4_1492319432","pageNo":"1","pageSize":"20","cursor":"-1","offset":"0","orderType":"1","csrf_token":""}
時,得到的是正確的加密結果!
六、完整代碼
完整代碼
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/209988.html
標籤:其他
上一篇:2020九華論道——數字經濟產業峰會將于11月13日在安徽池州隆重舉行
下一篇:滑動平均濾波器與CIC濾波器
