如何搞定知乎模擬登陸的加密難題?

如何搞定知乎模擬登陸的加密難題?

作者 | sergiojune

聲明:以下內容僅交流學習,請勿用於非法用途。

如果你現在想模擬登陸知乎,會發現 fromdata 是一串加密的字符串:

如何搞定知乎模擬登陸的加密難題?

看了之後是不是很痛苦?你是不是就想使用 selenium 來模擬登陸?不過好像知乎對 selenium 也進行了相應的反爬處理,哈哈。但是我不也想用 selenium,效率太慢了,直接破解 js 才是我最喜歡挑戰的。

好,我現在教你如何用 js 硬擼破解。廢話不多說,直接進入正題。

找出signature加密

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

你直接搜索知乎模擬登陸的話,會發現以前的知乎的 fromdata 是鍵值形式的,有以下鍵值對:

如何搞定知乎模擬登陸的加密難題?

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

如何搞定知乎模擬登陸的加密難題?

提示:按下 ctrl + shift + f 可出現搜索框

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

如何搞定知乎模擬登陸的加密難題?

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

如何搞定知乎模擬登陸的加密難題?

找出fromdata的完整鍵值對

在知道 signature 是如何加密的之後,我們還需要找出完整的 fromdata 先,不過在上面的調試中,你會發現也有幾個 fromdata 值,但是不全。

如何搞定知乎模擬登陸的加密難題?

這時候如果我們得繼續搜索 signature 的話,找了一整天你都會發現不到什麼線索,這時候我們可以通過登陸的 url 進行突破,看看 url 是哪個路徑,然後一頓搜。

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

如何搞定知乎模擬登陸的加密難題?

這個和登陸地址完全匹配,應該就是這個了,可以進行調試一波:

如何搞定知乎模擬登陸的加密難題?

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

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

Missing argument grant_type

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

找出 fromdata 加密位置

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

如何搞定知乎模擬登陸的加密難題?

會發現很多,不過你懂套路的話都知道加密一般都用到 encrypt 名字之類的,可以直接根據這個名字搜:

如何搞定知乎模擬登陸的加密難題?

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

如何搞定知乎模擬登陸的加密難題?

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

如何搞定知乎模擬登陸的加密難題?

這個是加密的字符串

如何搞定知乎模擬登陸的加密難題?

這個就是我們需要找的

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

找出 fromdata 加密的所有方法

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

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

如何搞定知乎模擬登陸的加密難題?

按這個半括號向上找,你就可以找到一個完整的加密方法,這個就是整個 fromdata 的加密方法。挺容易找的,如果覺得不方便找的,可以先將這個 js 文件裡面的代碼複製下來,然後到 Sublime Text 軟件上找,這個可以摺疊,也比較容易找,找出來是這樣子:

如何搞定知乎模擬登陸的加密難題?

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

為了看看這個正確不正確,我們可以把函數里面的內容直接拿出來,就是去掉最外層的函數,然後調用下面的函數 Q,把我們的 fromdata 傳進去:

如何搞定知乎模擬登陸的加密難題?

最後將上面的 JavaScript 給弄成一個 html 文件,放在>

如何搞定知乎模擬登陸的加密難題?

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

如何搞定知乎模擬登陸的加密難題?

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

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

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

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

在 node 環境調試加密代碼

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

TypeError: __g._encrypt is not a function
如何搞定知乎模擬登陸的加密難題?

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

要調試我們先要找到代碼運行的開端,可以很容易找到:

如何搞定知乎模擬登陸的加密難題?

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

如何搞定知乎模擬登陸的加密難題?

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

ReferenceError: atob is not defined
如何搞定知乎模擬登陸的加密難題?

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

如何搞定知乎模擬登陸的加密難題?

運行之後,還是報這個錯誤:

TypeError: __g._encrypt is not a function

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

如何搞定知乎模擬登陸的加密難題?

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

execption at 11: ReferenceError: window is not defined

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

如何搞定知乎模擬登陸的加密難題?

這個時候再運行看看:

如何搞定知乎模擬登陸的加密難題?

可以看到成功了,上面的紅色字是一個提示,關於 Buffer 的,這個我們忽略就行,接下來就可以使用 Python 環境進行測試了。

如何搞定知乎模擬登陸的加密難題?

如何搞定知乎模擬登陸的加密難題?

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

模擬登陸知乎

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

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

1. 網址的請求頭

請求登陸的網址的請求頭需要帶上這幾個:

如何搞定知乎模擬登陸的加密難題?

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

Missing argument grant_type

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

請求參數異常,請升級客戶端後重試

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

2. 請求順序

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

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

3. 驗證驗證碼

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

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

它的意思是說沒有帶上驗證碼驗證,當我們去掉的這個字段的時候,就可以驗證了。

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

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

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

如何搞定知乎模擬登陸的加密難題?

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

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

5.XXX

你還想要?沒有了,坑暫時只有這麼多,最後給你們看下登陸成功的結果:

如何搞定知乎模擬登陸的加密難題?

寫在最後

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

如果你上面看不懂不要緊,可以先去學習下 js,推薦大家去廖雪峰的官網看 JavaScript 教程,寫得蠻不錯的。

至於代碼,暫時不公佈了,如果你一步一步按照我方法來弄的話估計也可以,前提的有 js 基礎最好。

折騰這個,掉了不少頭髮,但聽說轉發是生髮之道,所以你們懂的!


分享到:


相關文章: