聲明:本文只作學(xué)習(xí)研究,禁止用于非法用途,否則后果自負(fù),如有侵權(quán),請(qǐng)告知?jiǎng)h除,謝謝!
1、前言
相信各位小伙伴在寫爬蟲的時(shí)候經(jīng)常會(huì)遇到這樣的情況,一些需要攜帶的參數(shù)一直在變化,今天逆向的這個(gè)網(wǎng)站某道翻譯也如此:
可以發(fā)現(xiàn)變的就兩個(gè)參數(shù),一個(gè) sign,一個(gè)是 mysticTime,mysticTime 一看就是時(shí)間戳,所以只要逆向 sign 參數(shù)就行了。
2、步驟
可以直接全局搜索 sign:
,加一個(gè)冒號(hào)可能好搜一點(diǎn)。搜索返回的結(jié)果比較少,多的話就每個(gè)sign都打上斷點(diǎn),點(diǎn)擊翻譯看看停在哪里。如果實(shí)在是太多了,就采用跟棧的方法,準(zhǔn)確無(wú)誤,慢慢的,我們找到了 sign 的位置:
t 是個(gè)時(shí)間戳,方法就是 (new Date).getTime()
。e 是個(gè)固定值 "fsdsogkndfokasodnaso"
,h 函數(shù)傳入了 t 和 e 后就生成了 sign,進(jìn)入 h 函數(shù),發(fā)現(xiàn)就在上面。而 d 和 u 這兩個(gè)參數(shù)也是固定的。并且 h 函數(shù)里面有調(diào)用了一個(gè) v 函數(shù),進(jìn)入 v 函數(shù),原來(lái) v 函數(shù)也在上面。這 v 函數(shù)太熟悉了啊,標(biāo)準(zhǔn)的 MD5 加密。
整理一下完整的 js 代碼就如下圖所示:
測(cè)試完沒(méi)問(wèn)題后,就可以封裝為 Python 進(jìn)行請(qǐng)求了,如下圖:
現(xiàn)在可以開(kāi)始編寫爬蟲程序,寫完運(yùn)行一下,發(fā)現(xiàn)返回的不是翻譯后的內(nèi)容,而是一串字符,那就需要我們來(lái)解密一下了:
我們用跟棧的方法看密文在哪里出現(xiàn)的和在哪里發(fā)生了變化,一步一步往下跟,最先調(diào)用的函數(shù)放在最下面,我們只需要跟到明文出現(xiàn)的那一刻就行了。
我們先復(fù)制請(qǐng)求的 URL:
切換到源代碼,在XHR/提取斷點(diǎn)把剛才復(fù)制的網(wǎng)址加上去,重新點(diǎn)一下翻譯
可以看到這個(gè) send 就是發(fā)請(qǐng)求,現(xiàn)在主要要找返回的數(shù)據(jù),我們一步步進(jìn)入下一個(gè)函數(shù)調(diào)用看看
不過(guò)一會(huì)咱們可以看見(jiàn),咱們剛才爬蟲請(qǐng)求返回的字符出現(xiàn)了,接下來(lái)咱們要注意看了,因?yàn)橐_(kāi)始處理這個(gè)返回的字符串
跟到這邊的話,可以發(fā)現(xiàn)在這字符串成功翻譯出來(lái)了,如圖所示:
可以看到起作用的是這個(gè) decodeData
,我們進(jìn)入那個(gè) js 文件
把其他斷點(diǎn)取消,這邊打上斷點(diǎn),重新翻譯一下,一步一步往下跟,我們只需要跟到明文出現(xiàn)的那一刻就行了。
到 t 的時(shí)候還是一串字符串,繼續(xù)往下走
可以看到到 s 的時(shí)候已經(jīng)翻譯出來(lái)了
我們把代碼扣下來(lái)放到 js 文件中去執(zhí)行應(yīng)該就差不多了
看到了 r.a.createDecipheriv,就可以用 node 中內(nèi)置的加密庫(kù) crypto 庫(kù)去執(zhí)行,當(dāng)然也可以硬扣,就是有點(diǎn)費(fèi)時(shí)間,而且還可能出現(xiàn)各種報(bào)錯(cuò)。
運(yùn)行報(bào)錯(cuò)缺 g ,去代碼再摳出來(lái),記得 r.a.createHash("md5").update(e).digest()
改為 node 中內(nèi)置的加密庫(kù) crypto 庫(kù):
運(yùn)行報(bào)錯(cuò)缺了 o ,直接把 o 復(fù)制進(jìn)來(lái),
再次運(yùn)行報(bào)錯(cuò)沒(méi)有 e.alloc 函數(shù) ,這就需要補(bǔ)充一點(diǎn) node.js 的相關(guān)知識(shí)了:
逆向改寫知識(shí)補(bǔ)充之 Node.js
Buffer.alloc() 方法:用于創(chuàng)建指定大小的新緩沖區(qū)對(duì)象。
此方法比 Buffer.alloconsafe() 方法慢,但它確保新創(chuàng)建的 Buffer 實(shí)例永遠(yuǎn)不會(huì)包含可能敏感的舊信息或數(shù)據(jù)。
語(yǔ)法:Buffer.alloc(size, fill, encoding)
參數(shù)三個(gè)參數(shù):
- 大小:指定緩沖區(qū)的大小。
- 填充:為可選參數(shù),指定填充緩沖區(qū)的值。其默認(rèn)值為 0。
- 編碼:如果緩沖區(qū)值是字符串,它是指定值的可選參數(shù)。其默認(rèn)值為‘utf8’。
返回值:
- 這個(gè)方法返回一個(gè)新的指定大小的初始化緩沖區(qū)。
- 如果給定的大小不是數(shù)字,將引發(fā)類型錯(cuò)誤。
故我們只需要修改 js 代碼為如下:
function data(t) {
// const a = e.alloc(16, g(o))
// , c = e.alloc(16, g(n))
const a = Buffer.alloc(16, g(o))
, c = Buffer.alloc(16, g(n))
, i = crypto.createDecipheriv("aes-128-cbc", a, c);
//, i = r.a.createDecipheriv("aes-128-cbc", a, c);
let s = i.update(t, "base64", "utf-8");
return s += i.final("utf-8"),
s
}
再次運(yùn)行,缺少 n ,返回復(fù)制補(bǔ)到 js 代碼中:
最后咱們的 js 代碼如下,測(cè)試之后,確實(shí)沒(méi)有問(wèn)題,直接用 Python 封裝起來(lái):
const crypto = require('crypto')
const o = 'ydsecret://query/key/B*RGygVywfNBwpmBaZg*WT7SIOUP2T0C9WHMZN39j^DAdaZhAnxvGcCY6VYFwnHl';
const n = 'ydsecret://query/iv/C@lZe2YzHtZ2CYgaXKSVfsb7Y4QWHjITPPZ0nQp87fBeJ!Iv6v^6fvi2WN@bYpJ4';
function data(t) {
const a = Buffer.alloc(16, g(o))
, c = Buffer.alloc(16, g(n))
, i = crypto.createDecipheriv("aes-128-cbc", a, c);
//, i = r.a.createDecipheriv("aes-128-cbc", a, c);
let s = i.update(t, "base64", "utf-8");
return s += i.final("utf-8"),
s
}
function g(e) {
return crypto.createHash("md5").update(e).digest()
// r.a.createHash("md5").update(e).digest()
}
text = 'Z21kD9ZK1ke6ugku2ccWu4n6eLnvoDT0YgGi0y3g-v0B9sYqg8L9D6UERNozYOHqnYdl2efZNyM6Trc_xS-zKtfTK4hb6JP8XwCzNh0avc8qItQUiIU_4wKKXJlIpvMvfKvJaaZzaX6VEtpkr2FdkfoT_Jgbm2GRSVj3r40autIdlImENG8hC0ZH4ww7utwuTt3Oo_ZpXg0BSq9wePSAB75-ChkiGKF9HTIPeCl2bl84SBD1XDfFCZpkKQhecYSs0JLoXOqP2ltavxRrg58Hp1q5uIgZZ_Oo2-Jmd-t1r4es40drcAq5bjmS62M2VJF8D6ojtOh9JTfNwgzD3CxYn-Pd7-TgHMyNEJEkFXTAyxzpjlFqtrCYDE3SZUYlENkqsL8Wrra1hM-1nTfiB-BLcWAdRBynNpP5_54aq_-GBsq8bB_9yEX5ovzDB4_Ry_spVVuUnb39iplMHCdCnjOD3ngiIDbl9SUz-9npjBX05ZYRdPmFPAl424qdoaxeVqnVoH8jQFPZVqaHMzu4mJg0SICDWFH7GP1zqGRbXd3ESjT_iBInl3gICt2XVuhh_nubcELkTEC6xbqEDRQkPUNMpzXJHjcvsLHtcmSW0S9F0445ho9kT2qZYdMBC3Fs0OaHpUtFu77gZpQn7sGiqh8VliXIcUtfvvop-1c-Vu5QjfUbLn2-s5POR9fGYG6rt6ioe_PGmwWj-Cc00zUM7FybfarKTr4D3Rk57R72qpXN4Ja86ZsCAMmDG-m5z31RQh_V7echJ8Kna3Go3yWKCK4vtSwOWrFhiS5RTz6EkrGc3SkFKbb5vp8Wop_84myBtgnBmj4CczhTq2HcOxrJf4def6yDt2uBxyv4bTVGx9Yx3uB4Gx0iK5kYvfma6B_LnkRWk331wjuXKQtBGYIuWkR8J5QtvBmIRVaa7AA19Z4xMIEAqbcuQ5p4I9FCElthBrJd9YOcouHK4U27xxYWJJXcJoTvzG7zWtiV76fHDeQLgAWvJJ7ww4NFgjhqc6AKA_2afxa4c_lAvVZgFuKL3XSCL7PfKxp6GhjcGKeSRr80PT1gfFw2xi8X4ejjNm_prsUZ\n'
console.log(data(text))
用 json.loads 解析一下解密后的數(shù)據(jù),即可獲取翻譯的正文,
def get_explain_data(data):
with open('./youdao.js', 'r', encoding='utf-8') as file:
result = file.read()
context1 = execjs.compile(result)
explain_data = context1.call('data', data)
explain_data = json.loads(explain_data)
eng = explain_data['translateResult'][0][0]['tgt']
return eng
最終效果如下:
3、源碼
Github:網(wǎng)易有道翻譯逆向
CSDN:有道翻譯sign解密,js逆向資源文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-606756.html
4、號(hào)外
如果我的博客對(duì)你有幫助、如果你喜歡我的博客內(nèi)容,請(qǐng) “??點(diǎn)贊” “??評(píng)論” “??收藏” 一鍵三連哦!
【????????????關(guān)注我| 獲取更多源碼 | 定制源碼】大學(xué)生畢設(shè)模板、期末大作業(yè)模板 、Echarts大數(shù)據(jù)可視化、爬蟲逆向等! 「一起探討 ,互相學(xué)習(xí)」!(vx:python812146)
以上內(nèi)容技術(shù)相關(guān)問(wèn)題??歡迎一起交流學(xué)習(xí)??????????????文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-606756.html
到了這里,關(guān)于【爬蟲逆向案例】某道翻譯js逆向—— sign解密的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!