以下內容僅交流學習,請勿用於非法用途
如果你現在想模擬登陸知乎,會發現 fromdata 是一串加密的字串
看了之後是不是很痛苦?你是不是就想使用 selenium 來模擬登陸?不過好像知乎對 selenium 也進行了相應的反爬處理,哈哈。但是我不也想用 selenium,效率太慢了,直接破解 js 才是我最喜歡挑戰的。好,我現在教你如何用 js 硬擼破解,廢話不多說,直接進入正題。
1. 找出signature加密
加密位置這個相對來說是比較難找的,需要自己對那些混淆過的 js 進行一遍又一遍的搜尋,有時候你看到頭皮發麻也不一定找得到,再加上這個加密引數是一堆字串,連個鍵都沒有,搜尋的條件都沒有。這怎麼辦呢?我們可以去百度或者谷歌看看前人是怎麼搞的。
你直接搜尋知乎模擬登陸的話,會發現以前的知乎的 fromdata 是鍵值形式的,有以下鍵值對
順便也可以看看之前的破解思路,看到了上面的 signature 是通過加密來的,猜測知乎應該也是對之前的鍵值加密的 fromdata 進行加密的,在控制檯搜搜 signature 看看有沒有線索
提示:按下 ctrl + shift + f 可出現搜尋框
一搜,果然有,看了看,signature 的加密過程和以前的還是一樣的,證明我的猜想正確了,說明是通過之前的 fromdata 的鍵值對進行加密成的一堆字串,現在就看看 signature 是如何加密的。
如果你對加密有點了解的話,還容易知道通過上面程式碼知道,很容易知道是通過 hmac 加密,雜湊演算法是 sha1,金鑰為 d1b964811afb40118a12068ff74a12f4,加密資料有四個,為 clientId、grantType、timestamp 和 source,這些值都可以在上面通過除錯出來的,就不多說了,如下
2. 找出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 的加密方法。
3. 找出 fromdata 加密位置
如果你是第一次找這個,估計你得不斷地翻 js,也不一定能找得到,或者你可以根據下面這個呼叫函式過程來找
會發現很多,不過你懂套路的話都知道加密一般都用到 encrypt 名字之類的,可以直接根據這個名字搜
一搜果然有這個,通過檢視你很容易就找到這個
這個一通過除錯,你可以看到,我們的加密字串出來了,是不是很激動,我當時找到了這個的時候激動不得了。
這個是加密的字串
這個就是我們需要找的
歷盡千辛萬苦,終於找出了廬山真面目,激動不?先不要激動先,這只是加密的位置,後面的才是最難的!
4. 找出 fromdata 加密的所有方法
知道位置後,我們可以直接把這個加密的 js 方法都扣出來,放在一個 html 檔案內執行就好。
在上面找出位置之後,很容易就可以看到這個完整的一個的加密方法
按這個半括號向上找,你就可以找到一個完整的加密方法,這個就是整個 fromdata 的加密方法,挺容易找的,如果覺得不方便找的,可以先將這個 js 檔案裡面的程式碼複製下來,然後到 Sublime Text 軟體上找,這個可以摺疊,也比較容易找,找出來是這樣子
格式化之後有 400 多行,而且全是混淆,難看得一批。
為了看看這個正確不正確,我們可以把函式裡面的內容直接拿出來,就是去掉最外層的函式,然後呼叫下面的函式 Q,把我們的 fromdata 傳進去
最後將上面的 JavaScript 給弄成一個 html 檔案,放在 script 標籤內即可
格式就和上面一樣,然後直接用瀏覽器上開啟這個 html 檔案,你會看到這個
這個就是我們一直努力在找的 fromdata 加密字串。
弄完這個之後,我們繼續使用 python 來操作了,因為這個 加密的方法格式化之後有 400 多行,實在太多,也全都是混淆,如果想用 python 來實現的話也不是不可能,就是成本太大了,需要的時間太多了,我們還不如直接使用 python 的 execjs 來執行 JavaScript 程式碼直接獲得就可以了,這個簡單方便。
(我們除了使用 execjs 來執行,還可以使用 selenium 執行這個html 檔案也是可以的,但是我並不想用 selenium 這個工具,還是喜歡折騰,所以忽略了,想用的可以試試。)
但是這裡又會有一個問題,我們用瀏覽器開啟的是為它提供了一個瀏覽器的執行環境,我們在 python 使用的 execjs 提供的是 node 環境,兩個環境的不一樣,就會產生不同的效果,下面我們可以選擇使用 webstorm 編輯器來提供 nodejs 環境來進行嘗試以下。
5. 在 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 算是大功告成了,接下來就是登陸驗證下我們搞得這個加密對不對了。
6. 模擬登陸知乎
這個知乎的登陸也是坑滿滿,我也給踩了幾個,這個就直接說坑吧,其他的就不多說了。
我只是用手機號來登陸的,也可以用郵箱登陸,過程都差不多的。
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.
你還想要?沒有了,坑暫時只有這麼多,最後給你們看下登陸成功的結果
7. 寫在最後
這個登陸折騰了差不多一週了,實際來說可能是三週,因為從剛開始看不懂 js 程式碼,就跑去學了兩週 js,現在總得來說 js 也可以說上手了,以後或許也會使用 nodejs 搞點爬蟲,挺好玩的。
至於程式碼,暫時不公佈了,如果你一步一步按照我方法來弄的話估計也可以,前提的有 js 基礎最好,以後會公佈的,等我再完善先,因為還需要幹別的東西。如果有問題也可以找我,加我微信 june--98 拉你進群討論即可。
折騰這個,掉了不少頭髮,但聽說分享點贊是生髮之道,所以你們懂的!