Python模擬登陸,解密js代碼實例:知乎登陸

本文轉(zhuǎn)載自公眾號 | 日常學(xué)Python

作者 | sergiojune

如果你現(xiàn)在想模擬登陸知乎,會發(fā)現(xiàn) fromdata 是一串加密的字符串

image

看了之后是不是很痛苦?你是不是就想使用 selenium 來模擬登陸?不過好像知乎對 selenium 也進(jìn)行了相應(yīng)的反爬處理,哈哈。但是我不也想用 selenium,效率太慢了,直接破解 js 才是我最喜歡挑戰(zhàn)的。好,我現(xiàn)在教你如何用 js 硬擼破解,廢話不多說,直接進(jìn)入正題。

1. 找出signature加密

加密位置這個相對來說是比較難找的,需要自己對那些混淆過的 js 進(jìn)行一遍又一遍的搜尋,有時候你看到頭皮發(fā)麻也不一定找得到,再加上這個加密參數(shù)是一堆字符串,連個鍵都沒有,搜索的條件都沒有。這怎么辦呢?我們可以去百度或者谷歌看看前人是怎么搞的。

你直接搜索知乎模擬登陸的話,會發(fā)現(xiàn)以前的知乎的 fromdata 是鍵值形式的,有以下鍵值對

image

順便也可以看看之前的破解思路,看到了上面的 signature 是通過加密來的,猜測知乎應(yīng)該也是對之前的鍵值加密的 fromdata 進(jìn)行加密的,在控制臺搜搜 signature 看看有沒有線索

image

提示:按下 ctrl + shift + f 可出現(xiàn)搜索框

一搜,果然有,看了看,signature 的加密過程和以前的還是一樣的,證明我的猜想正確了,說明是通過之前的 fromdata 的鍵值對進(jìn)行加密成的一堆字符串,現(xiàn)在就看看 signature 是如何加密的。

image

如果你對加密有點了解的話,還容易知道通過上面代碼知道,很容易知道是通過 hmac 加密,哈希算法是 sha1,密鑰為 d1b964811afb40118a12068ff74a12f4,加密數(shù)據(jù)有四個,為 clientId、grantType、timestamp 和 source,這些值都可以在上面通過調(diào)試出來的,就不多說了,如下

image

2. 找出fromdata的完整鍵值對

在知道 signature 是如何加密的之后,我們還需要找出完整的 fromdata 先,不過在上面的調(diào)試中,你會發(fā)現(xiàn)也有幾個 fromdata 值,但是不全。

image

這時候如果我們得繼續(xù)搜索 signature 的話,找了一整天你都會發(fā)現(xiàn)不到什么線索,這時候我們可以通過登陸的 url 進(jìn)行突破,看看 url 是哪個路徑,然后一段搜。

其登陸url是 https://www.zhihu.com/api/v3/oauth/sign_in。那我們可以直接搜 sign_in 試試。搜了發(fā)現(xiàn)和上面的 signature 是在同一個 js 文件上的,感覺應(yīng)該有戲。

image

這個和登陸地址完全匹配,應(yīng)該就是這個了,可以進(jìn)行調(diào)試一波

image

這不出來了,經(jīng)過多次調(diào)試,發(fā)現(xiàn)大多數(shù)值都是固定的,只有 signature 和 timestamp 不是,其他的就是賬號密碼之類的,還有個驗證碼 captcha 以及它的類型 lang,signature 上面的已經(jīng)找出來了,timestamp 很明顯就是時間戳,其他的就不多說了。

現(xiàn)在的 fromdata 已經(jīng)全部找出來了,我們離加密字符串又近了一步,如果你直接用這個表單進(jìn)行模擬登陸,會給你返回下面錯誤


Missing argument grant_type

可見我們還得找出這個 fromdata 的加密方法。

3. 找出 fromdata 加密位置

如果你是第一次找這個,估計你得不斷地翻 js,也不一定能找得到,或者你可以根據(jù)下面這個調(diào)用函數(shù)過程來找

image

會發(fā)現(xiàn)很多,不過你懂套路的話都知道加密一般都用到 encrypt 名字之類的,可以直接根據(jù)這個名字搜

image

一搜果然有這個,通過查看你很容易就找到這個

image

這個一通過調(diào)試,你可以看到,我們的加密字符串出來了,是不是很激動,我當(dāng)時找到了這個的時候激動不得了。

image

這個是加密的字符串

image

這個就是我們需要找的

歷盡千辛萬苦,終于找出了廬山真面目,激動不?先不要激動先,這只是加密的位置,后面的才是最難的!

4. 找出 fromdata 加密的所有方法

知道位置后,我們可以直接把這個加密的 js 方法都扣出來,放在一個 html 文件內(nèi)執(zhí)行就好。

在上面找出位置之后,很容易就可以看到這個完整的一個的加密方法

image

按這個半括號向上找,你就可以找到一個完整的加密方法,這個就是整個 fromdata 的加密方法,挺容易找的,如果覺得不方便找的,可以先將這個 js 文件里面的代碼復(fù)制下來,然后到 Sublime Text 軟件上找,這個可以折疊,也比較容易找,找出來是這樣子

image

格式化之后有 400 多行,而且全是混淆,難看得一批。

為了看看這個正確不正確,我們可以把函數(shù)里面的內(nèi)容直接拿出來,就是去掉最外層的函數(shù),然后調(diào)用下面的函數(shù) Q,把我們的 fromdata 傳進(jìn)去

image

最后將上面的 JavaScript 給弄成一個 html 文件,放在 script 標(biāo)簽內(nèi)即可

image

格式就和上面一樣,然后直接用瀏覽器上打開這個 html 文件,你會看到這個

image

這個就是我們一直努力在找的 fromdata 加密字符串。

弄完這個之后,我們繼續(xù)使用 python 來操作了,因為這個 加密的方法格式化之后有 400 多行,實在太多,也全都是混淆,如果想用 python 來實現(xiàn)的話也不是不可能,就是成本太大了,需要的時間太多了,我們還不如直接使用 python 的 execjs 來執(zhí)行 JavaScript 代碼直接獲得就可以了,這個簡單方便。

(我們除了使用 execjs 來執(zhí)行,還可以使用 selenium 運行這個html 文件也是可以的,但是我并不想用 selenium 這個工具,還是喜歡折騰,所以忽略了,想用的可以試試。)

但是這里又會有一個問題,我們用瀏覽器打開的是為它提供了一個瀏覽器的運行環(huán)境,我們在 python 使用的 execjs 提供的是 node 環(huán)境,兩個環(huán)境的不一樣,就會產(chǎn)生不同的效果,下面我們可以選擇使用 webstorm 編輯器來提供 nodejs 環(huán)境來進(jìn)行嘗試以下。

5. 在 node 環(huán)境調(diào)試加密代碼

你可以拿上面的 JavaScript 代碼在 webstorm 運行,你就會看到

TypeError: __g._encrypt is not a function
image

所以我們需要調(diào)試,需要把那些在瀏覽器上只有的對象,比如 window、navigator之類的對象給弄掉,從而在 node 上用不用的代碼代替相同的效果即可。

要調(diào)試我們先要找到代碼運行的開端,可以很容易找到

image

可以看到,這里它會先去判斷有沒有 window 這個對象來判斷是不是在瀏覽器上面運行的,所以我們可以直接把它修改成 true 或者其他****表示成 true 的值都可以

image

再次運行,可以看到這個錯誤

ReferenceError: atob is not defined
image

這個 atob 是將 base64 加密的字符串給解密,在 node 環(huán)境下是沒有這個方法的,我們需要使用 Buffer.toString()替代即可。

image

運行之后,還是報這個錯誤

TypeError: __g._encrypt is not a function

注意:這個是大坑,估計一般人每個一兩天還搞不定,這個是因為上面的解密的,但是上面的并不一樣,你可以在上面的兩個函數(shù)加斷點,分別在瀏覽器和 node 環(huán)境下運行,可以看到解密的數(shù)據(jù)是不一樣的,是因為在瀏覽器上的 base64 加密的是 binary 編碼,解密之后也就同樣需要使用 binary 編碼,這個是我在知乎的資源文件上搜索 atob 這個方法,然后慢慢查找看到的,當(dāng)時也差不多心態(tài)崩了,還好堅持下來了。而我在 node 環(huán)境下解密之后使用了默認(rèn)的編碼,所以解密的數(shù)據(jù)出錯了。當(dāng)我們加上 binary 編碼之后,再運行

image

這時,錯誤不再是上面那個了,變成了另一個,證明解密正確了,再來看看下面這個錯誤

execption at 11: ReferenceError: window is not defined

原來是 window 對象惹的禍,這個時候就需要我們偽造 window 對象了,至于怎樣偽造呢,我們可以調(diào)試出錯的地方,看看它使用了什么方法,就直接使用適合 node 運行的相同效果的代碼代替就可以了,經(jīng)過多次調(diào)試,需要我們偽造 window 和 navigator 這兩個對象,下面就是偽造之后的代碼

image

這個時候再運行看看。

image

可以看到成功了,上面的紅色字是一個提示,關(guān)于 Buffer 的,這個我們忽略就行,接下來就可以使用 python 環(huán)境進(jìn)行測試了。

image
image

果然,都出來了,哈哈,注意需要先安裝 PyExecJS 庫,自行安裝,然后在測試的時候記得導(dǎo)入 execjs 即可?,F(xiàn)在這個 fromdata 算是大功告成了,接下來就是登陸驗證下我們搞得這個加密對不對了。

6. 模擬登陸知乎

這個知乎的登陸也是坑滿滿,我也給踩了幾個,這個就直接說坑吧,其他的就不多說了。

我只是用手機(jī)號來登陸的,也可以用郵箱登陸,過程都差不多的。

1. 請求登陸的網(wǎng)址的請求頭需要帶上這幾個

image

不帶 content-type 的話,會給你返回這個錯誤

Missing argument grant_type

不帶 x-zse-83 的話,會給你返回這個錯誤

請求參數(shù)異常,請升級客戶端后重試

至于 agent-user 那就更不需要說了。

2. 請求順序

知乎這個登陸是首先請求驗證碼地址,看需要不需要填寫驗證碼,如果需要填就再請求一次,而且還需要再再請求一次查看是否輸入驗證碼正確,不正確就重復(fù)上面步驟,當(dāng)不需要填寫驗證碼的時候就可以直接請求登陸網(wǎng)址了。

還有上面的三次請求的驗證碼地址的請求方法都是不一樣的,哪種方法自行調(diào)試即可。

3. 驗證驗證碼

在驗證驗證碼的時候請求頭的 content-type 不要填寫 值為 multipart/form-data,如果填了請求驗證碼的時候會給你返回這個錯誤:

{"error":{"message":"Missing argument input_text","code":400}}

它的意思是說沒有帶上驗證碼驗證,當(dāng)我們?nèi)サ舻倪@個字段的時候,就可以驗證了。

驗證驗證碼的時候請求頭只需要有一個** user-agent **就可以了

4. 請求的所有階段帶上 cookie

知乎這個有個 cookie 值是驗證碼票據(jù),是從第一次請求驗證碼地址來的,就是下面這個

image

如果不帶 cookie請求或者請求順序不一樣都有可能給你返回這個錯誤。

{"error":{"message":"缺少驗證碼票據(jù)","code":120002,"name":"ERR_CAPSION_TICKET_NOT_FOUND"}}

5.

你還想要?沒有了,坑暫時只有這么多,最后給你們看下登陸成功的結(jié)果

image

7. 寫在最后

這個登陸折騰了差不多一周了,實際來說可能是三周,因為從剛開始看不懂 js 代碼,就跑去學(xué)了兩周 js,現(xiàn)在總得來說 js 也可以說上手了,以后或許也會使用 nodejs 搞點爬蟲,挺好玩的。

如果你上面看不懂不要緊,可以先去學(xué)習(xí)下 js,推薦大家去廖雪峰的官網(wǎng)看 JavaScript 教程,寫得蠻不錯的,如果想看視頻學(xué)的可以加我好友,微信 june--98給你發(fā)教程,如果直接發(fā)容易和諧,所以加好友發(fā)方便點。

至于代碼,暫時不公布了,如果你一步一步按照我方法來弄的話估計也可以,前提的有 js 基礎(chǔ)最好,以后會公布的,等我再完善先,因為還需要干別的東西。如果有問題也可以找我,加我微信 june--98 拉你進(jìn)群討論即可。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容