如下內容僅交流學習,請勿用於非法用途html
若是你如今想模擬登錄知乎,會發現 fromdata 是一串加密的字符串node
看了以後是否是很痛苦?你是否是就想使用 selenium 來模擬登錄?不過好像知乎對 selenium 也進行了相應的反爬處理,哈哈。可是我不也想用 selenium,效率太慢了,直接破解 js 纔是我最喜歡挑戰的。好,我如今教你如何用 js 硬擼破解,廢話很少說,直接進入正題。python
加密位置這個相對來講是比較難找的,須要本身對那些混淆過的 js 進行一遍又一遍的搜尋,有時候你看到頭皮發麻也不必定找獲得,再加上這個加密參數是一堆字符串,連個鍵都沒有,搜索的條件都沒有。這怎麼辦呢?咱們能夠去百度或者谷歌看看前人是怎麼搞的。web
你直接搜索知乎模擬登錄的話,會發現之前的知乎的 fromdata 是鍵值形式的,有如下鍵值對算法
順便也能夠看看以前的破解思路,看到了上面的 signature 是經過加密來的,猜想知乎應該也是對以前的鍵值加密的 fromdata 進行加密的,在控制檯搜搜 signature 看看有沒有線索api
提示:按下 ctrl + shift + f 可出現搜索框
一搜,果真有,看了看,signature 的加密過程和之前的仍是同樣的,證實個人猜測正確了,說明是經過以前的 fromdata 的鍵值對進行加密成的一堆字符串,如今就看看 signature 是如何加密的。瀏覽器
若是你對加密有點了解的話,還容易知道經過上面代碼知道,很容易知道是經過 hmac 加密,哈希算法是 sha1,密鑰爲 d1b964811afb40118a12068ff74a12f4,加密數據有四個,爲 clientId、grantType、timestamp 和 source,這些值均可以在上面經過調試出來的,就很少說了,以下微信
在知道 signature 是如何加密的以後,咱們還須要找出完整的 fromdata 先,不過在上面的調試中,你會發現也有幾個 fromdata 值,可是不全。cookie
這時候若是咱們得繼續搜索 signature 的話,找了一成天你都會發現不到什麼線索,這時候咱們能夠經過登錄的 url 進行突破,看看 url 是哪一個路徑,而後一段搜。webstorm
其登錄url是 https://www.zhihu.com/api/v3/...。那咱們能夠直接搜 sign_in 試試。搜了發現和上面的 signature 是在同一個 js 文件上的,感受應該有戲。
這個和登錄地址徹底匹配,應該就是這個了,能夠進行調試一波
這不出來了,通過屢次調試,發現大多數值都是固定的,只有 signature 和 timestamp 不是,其餘的就是帳號密碼之類的,還有個驗證碼 captcha 以及它的類型 lang,signature 上面的已經找出來了,timestamp 很明顯就是時間戳,其餘的就很少說了。
如今的 fromdata 已經所有找出來了,咱們離加密字符串又近了一步,若是你直接用這個表單進行模擬登錄,會給你返回下面錯誤
Missing argument grant_type
可見咱們還得找出這個 fromdata 的加密方法。
若是你是第一次找這個,估計你得不斷地翻 js,也不必定能找獲得,或者你能夠根據下面這個調用函數過程來找
會發現不少,不過你懂套路的話都知道加密通常都用到 encrypt 名字之類的,能夠直接根據這個名字搜
一搜果真有這個,經過查看你很容易就找到這個
這個一經過調試,你能夠看到,咱們的加密字符串出來了,是否是很激動,我當時找到了這個的時候激動不得了。
這個是加密的字符串
這個就是咱們須要找的
歷盡千辛萬苦,終於找出了廬山真面目,激動不?先不要激動先,這只是加密的位置,後面的纔是最難的!
知道位置後,咱們能夠直接把這個加密的 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 環境來進行嘗試如下。
你能夠拿上面的 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 算是大功告成了,接下來就是登錄驗證下咱們搞得這個加密對不對了。
這個知乎的登錄也是坑滿滿,我也給踩了幾個,這個就直接說坑吧,其餘的就很少說了。
我只是用手機號來登錄的,也能夠用郵箱登錄,過程都差很少的。
不帶 content-type 的話,會給你返回這個錯誤
Missing argument grant_type
不帶 x-zse-83 的話,會給你返回這個錯誤
請求參數異常,請升級客戶端後重試
至於 agent-user 那就更不須要說了。
知乎這個登錄是首先請求驗證碼地址,看須要不須要填寫驗證碼,若是須要填就再請求一次,並且還須要再再請求一次查看是否輸入驗證碼正確,不正確就重複上面步驟,當不須要填寫驗證碼的時候就能夠直接請求登錄網址了。
還有上面的三次請求的驗證碼地址的請求方法都是不同的,哪一種方法自行調試便可。
在驗證驗證碼的時候請求頭的 content-type 不要填寫 值爲 multipart/form-data,若是填了請求驗證碼的時候會給你返回這個錯誤:
{"error":{"message":"Missing argument input_text","code":400}}
它的意思是說沒有帶上驗證碼驗證,當咱們去掉的這個字段的時候,就能夠驗證了。
驗證驗證碼的時候請求頭只須要有一個 user-agent 就能夠了
知乎這個有個 cookie 值是驗證碼票據,是從第一次請求驗證碼地址來的,就是下面這個
若是不帶 cookie請求或者請求順序不同都有可能給你返回這個錯誤。
{"error":{"message":"缺乏驗證碼票據","code":120002,"name":"ERR_CAPSION_TICKET_NOT_FOUND"}}
你還想要?沒有了,坑暫時只有這麼多,最後給大家看下登錄成功的結果
這個登錄折騰了差很少一週了,實際來講多是三週,由於從剛開始看不懂 js 代碼,就跑去學了兩週 js,如今總得來講 js 也能夠說上手了,之後或許也會使用 nodejs 搞點爬蟲,挺好玩的。
至於代碼,暫時不公佈了,若是你一步一步按照我方法來弄的話估計也能夠,前提的有 js 基礎最好,之後會公佈的,等我再完善先,由於還須要幹別的東西。若是有問題也能夠找我,加我微信 june--98 拉你進羣討論便可。
折騰這個,掉了很多頭髮,但據說分享點贊是生髮之道,因此大家懂的!