破解反爬蟲策略 /_guard/auto.js(一) 原理

背景

當用代碼或者postman訪問一個網站的時候,訪問他的任何地址都會返回<script src="/_guard/auto.js"></script>,但是從瀏覽器中訪問顯示的頁面是正常的,這種就是網站做了反爬蟲策略。本文就是帶大家來破解這種策略,也就是反反爬蟲。

思路

尋找關鍵參數

既然在瀏覽器中訪問沒問題,那我們就把瀏覽器的請求復制下來,看是哪些參數讓請求可以正常訪問,將curl復制到postman中,把請求頭一個個去掉,看去掉哪些請求頭會讓請求無法正常訪問

最終發現是Cookie和User-Agent一起使得請求合法,如下

  • Cookie:guardret=BQgG; __51vcke__K1rw5p3uprPRftXo=21f5dde6-91d9-520b-a429-4a6e99d44523; __51vuft__K1rw5p3uprPRftXo=1720509084853; guardok=9DltyP8ERJnWJaolNInDWV03ft30EOzKt4tqyEk7ovRpu+YeNMKAWDqyyT9DwacZaxy9brXjs+8M+k2pbxhhWw==; PHPSESSID=khol0nbd4esktf48ddmecbidb6; __vtins__K1rw5p3uprPRftXo=%7B%22sid%22%3A%20%22045d7540-b7de-543b-830f-f3cb437c85bd%22%2C%20%22vd%22%3A%201%2C%20%22stt%22%3A%200%2C%20%22dr%22%3A%200%2C%20%22expires%22%3A%201721135512843%2C%20%22ct%22%3A%201721133712843%7D; __51uvsct__K1rw5p3uprPRftXo=7
  • User-Agent:Mozilla/xxx

可以看到Cookie中有好幾項,我們繼續在Cookie中刪除,發現只有guardok有用,其他的都沒用,所以最終有用的請求頭如下

  • Cookie:guardok=9DltyP8ERJnWJaolNInDWV03ft30EOzKt4tqyEk7ovRpu+YeNMKAWDqyyT9DwacZaxy9brXjs+8M+k2pbxhhWw==
  • User-Agent:Mozilla/xxx

js混淆

這么看來關鍵的東西就是這個guardok,那我們看看這個是什么時候生成的,把瀏覽器的cookie刪除,再打開開發者模式

但是發現在開發者模式下,這個js在無限的debug,這是一個很常見的防debug的代碼,就是定時循環執行含有debugger的代碼,如果沒在開發者模式那么debug就不會生效(遇到debugger斷點不會停),但如果是在開發者模式下就會停到斷點處,并且這個方法還會不斷的自己調自己直到下一次定時時間,所以即使我們調試通過這個斷點也會立刻到這個斷點處。

由于這個代碼的存在我們不能查看network,因為會一直卡在debuger。那我們就直接用postman訪問這個js看看guardok是不是在這個js中生成的。

但是這個js返回的內容還是混淆過的,直接看是看不懂的,比如他會把 "location" 混淆成 _0x10a691(0x215, 'lIIz'),其實這個的意思是將一個初始值_0x10a691 進行位偏移,偏移后就變成了另一個值"location" ,并且這個在瀏覽器上運行也是能正常運行,只不過加大了我們的翻譯成本。

分析關鍵參數guardok生成過程

既然翻譯成本大,那我就先確認這個guardok是否和這個js有關,別翻譯了半天發現跟他沒關系,那心態就崩了。這個也好確認,在瀏覽器上訪問一次看這個guardok是什么時候生成的就行,但因為這個debbuger的問題我們不能直接在瀏覽器上訪問,所以就抓個包看看這個接口就行,比如使用Charles。

通過抓包可以看到,同一個接口訪問了兩次

  1. 第一次訪問,在響應頭中的cookie里返回了guard,并且返回的報文體中返回了那個js文件
  2. 第二次訪問,在響應頭中的cookie里返回了guardok,并且返回的報文體中返回了正常的頁面數據

可以看到第二次訪問的請求中并沒有任何地方攜帶guardok,但是在響應頭中有guardok。那么就說明第二次的請求中有參數會傳給后端,由后端生成guardok并放到Set-Cookie中,后續的請求就都攜帶了guardok。

查看第二次的請求只是在請求的cookie中多了guardret和guard這兩項。由此可以知道是根據guardret和guard去服務端換取guardok,而guard會在第一次請求的響應中返回到Set-Cookie,無需客戶端手動生成。而guardret則只可能會由第一次請求返回的那個js中生成,那我們只需在js中把生成guardret的算法找出來就行了

反js混淆

到這里也就只能對js進行反混淆了,只有知道生成guardret的算法,那一切就都通了。我試過好多反混淆工具都無法解析出實際的代碼。沒辦法只能花時間一點點的還原了。重頭戲來了,還原的方法其實并不難,相反還很簡單,就是苦力活。比如這個方法


var _0xd750ee = _0x5391;function setRet(_0x34d4ed) {var _0x10a691 = _0xd750ee, WtHInZ = {'GIeQp': function (callee, _0xf9e2d4) {return callee(_0xf9e2d4);}, 'LYVKf': 'undefined', 'fOOLQ': function (_0x396e94, _0x39a709) {return _0x396e94 - _0x39a709;}, 'FARua': function (_0x4be905, _0x42316e) {return _0x4be905 * _0x42316e;}, 'ascvk': function (callee, _0x10b8fa, _0x4313da) {return callee(_0x10b8fa, _0x4313da);}, 'wqePU': function (callee, _0x1a7786) {return callee(_0x1a7786);}, 'dYcOv': _0x10a691(0x201, '0@TB')}, _0x3a9f4b = _0x34d4ed[_0x10a691(0x1ee, '6%cq')](0x0, 0x8), time_num_plain = _0x34d4ed['substr'](0xc),_0x305bd1 = WtHInZ[_0x10a691(0x1c8, '2qE2')](parseInt, time_num_plain['substr'](0xa));typeof window === WtHInZ[_0x10a691(0x1dd, 'WPXd')] && (_0x305bd1 = 0x2);var _0x552e00 = WtHInZ[_0x10a691(0x1da, 'QiI*')](WtHInZ[_0x10a691(0x1d2, 'p7[8')](_0x305bd1, 0x2) + 0x11, 0x2),encrypted = WtHInZ[_0x10a691(0x25a, '!koh')](x, _0x552e00[_0x10a691(0x275, '6f6c')](), _0x3a9f4b),guard_encrypted = WtHInZ[_0x10a691(0x24e, 'lIIz')](b, encrypted);document[_0x10a691(0x1f7, 'hlsZ')] = WtHInZ[_0x10a691(0x1eb, 'sPw2')] + guard_encrypted, window[_0x10a691(0x215, 'lIIz')]['reload']();
}

里面的很多代碼都看不出是啥東西,不過沒關系,我們可以讓瀏覽器幫我們翻譯,首先把無限debug的代碼先去掉,改成空方法即可,如下

    function debuggerProtection(counter) {}

然后在一個文本里加入script標簽, <script type="text/javascript"> </script>,再把修改后的js代碼復制到標簽中間,另存為.html文件。雙擊該html文件再使用開發者工具即可。

然后我們就一步步的用瀏覽器debug即可,比如 WtHInZ[_0x10a691(0x1d2, 'p7[8')](_0x305bd1, 0x2)?

1.文本翻譯

首先翻譯 _0x10a691(0x1d2, 'p7[8'),因為var _0x10a691 = _0xd750ee,所以_0x10a691(0x1d2, 'p7[8')也就是_0xd750ee(0x1d2, 'p7[8'),那我們只需要在瀏覽器中把它打印出來即可,alert、debug、console打印都行,在這里我們用debug,隨便找個地方執行,如下打印個斷點查看

可以看到_0x10a691(0x1d2, 'p7[8')為"FARua"

2.文本替換?

WtHInZ[_0x10a691(0x1d2, 'p7[8')](_0x305bd1, 0x2) 就等于 WtHInZ["FARua"](_0x305bd1, 0x2)

3.方法替換?

WtHInZ是一個字典值,里面的key對應里各種方法或者文本,key為"FARua"所對應的是一個方法如下

function (_0x4be905, _0x42316e) {return _0x4be905 * _0x42316e;}

可以看出也就是一個簡單的兩個數相乘,所以WtHInZ["FARua"](_0x305bd1, 0x2)= ?_0x305bd1*0x2。

4.最終替換

到這里就完成了對WtHInZ[_0x10a691(0x1d2, 'p7[8')](_0x305bd1, 0x2)的翻譯。即WtHInZ[_0x10a691(0x1d2, 'p7[8')](_0x305bd1, 0x2) = _0x305bd1*0x2?

其中的_0x305bd1是一個變量名,由上一步計算出來的,不用管

這樣一步步把需要的代碼就還原出來了,其實里面大部分代碼是沒用的就是為了混淆我們,所以我們不用都翻譯,只要翻譯自己感覺像的那幾個方法就行。翻譯完就是這樣的

function setRet(_0x34d4ed) {var _0x10a691 = _0xd750ee, WtHInZ = {'GIeQp': function (callee, _0xf9e2d4) {return callee(_0xf9e2d4);}, 'LYVKf': 'undefined', 'fOOLQ': function (_0x396e94, _0x39a709) {return _0x396e94 - _0x39a709;}, 'FARua': function (_0x4be905, _0x42316e) {return _0x4be905 * _0x42316e;}, 'ascvk': function (callee, _0x10b8fa, _0x4313da) {return callee(_0x10b8fa, _0x4313da);}, 'wqePU': function (callee, _0x1a7786) {return callee(_0x1a7786);}, 'dYcOv': "guardret="}_0x3a9f4b = _0x34d4ed["substr"](0x0, 0x8)time_num_plain = _0x34d4ed['substr'](0xc)_0x305bd1 = parseInt(time_num_plain['substr'](0xa));var _0x552e00 = _0x305bd1 * 0x2 + 0x11 - 0x2encrypted = x(_0x552e00["toString"](), _0x3a9f4b)guard_encrypted = btoa(encrypted);document["cookie"] = "guardret=" + guard_encrypted, window['location']['reload']();
}

可以看到guardret確實是在這個js中生成的,并且生成的算法也比較簡單就是一些加減乘除加上異或操作等,生成后就可以使用guardret和guard去服務端換guardok了。由此這個破解反爬蟲策略也就完成了

完整破解實戰

下一篇文章我會實戰破解兩個這種反爬蟲策略的網站,并用java實現

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/46429.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/46429.shtml
英文地址,請注明出處:http://en.pswp.cn/web/46429.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

輕松搞定一鍵切換主題色?分享 1 段優質 CSS 代碼片段!

本內容首發于工粽號&#xff1a;程序員大澈&#xff0c;每日分享一段優質代碼片段&#xff0c;歡迎關注和投稿&#xff01; 大家好&#xff0c;我是大澈&#xff01; 本文約 800 字&#xff0c;整篇閱讀約需 1 分鐘。 今天分享一段優質 CSS 代碼片段&#xff0c;輕松實現一鍵切…

4.3 最小二乘近似

一、最小二乘解 A x b A\boldsymbol x\boldsymbol b Axb 經常無解&#xff0c;一般是因為方程太多了。矩陣 A A A 的行比列要多&#xff0c;即方程要多余未知數&#xff08; m > n m>n m>n&#xff09;。 n n n 個列只能張成 m m m 空間的一小部分&#xff0c;除非…

spring中的依賴注入

文章目錄 spring中的依賴注入一、Autowired二、Qualifier三、Resource四、總結 spring中的依賴注入 這里主要講述三個注解裝配 一、Autowired 作用&#xff1a;自動按照類型注入。只要容器中唯一的一個bean對象類型和要注入的變量類型匹配&#xff0c;就可以注入成功。 如果i…

MySQL5.7社區版本在CentOS7系統上的安裝

MySQL5.7社區版本在CentOS7系統上的安裝 1.配合yum倉庫 rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022 rpm -Uvh http://repo.mysql.com//mysql57-community-release-el7-7.noarch.rpm 2.使用yum安裝MySQL5.7 yum -y install mysql-community-server 3.安裝…

面向鐵路、地鐵旅客信息系統(PIS)的上架型整機,鐵路專用M12網絡接口,滿足歐洲鐵路應用標準

上架型整機 2U 19寸上架型整機&#xff0c;采用高性能低功耗處理器&#xff0c;能應用在寬溫環境下&#xff0c;并滿足歐洲鐵路應用標準EN50155關于電磁兼容性&#xff0c;沖擊和振動測試試驗的要求&#xff0c;是一款面向鐵路、地鐵旅客信息系統&#xff08;PIS&#xff09;的…

C# 關于 PaddleOCRSharp OCR識別的疲勞測試

目錄 關于 PaddleOCRSharp 應用范例演示 ?范例運行環境 疲勞測試 添加組件庫 方法設計 調用示例 小結 關于 PaddleOCRSharp PaddleOCRSharp 是百度飛槳封裝的.NET版本 OCR dll 類庫&#xff0c;OCR&#xff08;Optical Character Recognition&#xff09;工具可以將…

【Java面向對象】抽象類和接口

文章目錄 1.抽象類2.常見的抽象類2.1 Number類2.2 Calendar 和GregorianCalendar 3.接口4.常見接口4.1 Comparable 接口4.2 Cloneable 接口4.3 深淺拷貝 5.類的設計原則 1.抽象類 在繼承的層次結構中&#xff0c;每個新的子類都使類變得更加明確和具體。如果從一個子類向父類追…

Unty 崩潰問題(Burst 1.8.2)

錯誤代碼&#xff1a; Assertion failed on expression: exception SCRIPTING_NULL UnityEngine.StackTraceUtility:ExtractStackTrace () Unity.Burst.BurstCompiler:SendRawCommandToCompiler (string Unity版本&#xff1a;2021.3.17F1&#xff0c;Burst 1.8.2 表現&…

python安裝talib庫教程

【talib介紹】 Talib介紹 Talib&#xff0c;全稱“Technical Analysis Library”&#xff0c;即技術分析庫&#xff0c;是一個廣泛應用于金融量化領域的Python庫。該庫由C語言編寫&#xff0c;支持Python調用&#xff0c;為投資者、交易員和數據分析師提供了強大的技術分析工…

酷炫末世意境背景404單頁HTML源碼

源碼介紹 酷炫末世意境背景404單頁HTML源碼&#xff0c;背景充滿著破壞一切的意境&#xff0c;彷佛末世的到來&#xff0c;可以做網站錯誤頁或者丟失頁面&#xff0c;將下面的代碼放到空白的HTML里面&#xff0c;然后上傳到服務器里面&#xff0c;設置好重定向即可 效果預覽 …

餐邊柜不踩坑的尺寸和做法

大家問餐邊柜怎么做好看不踩坑      十做十不做,有尺寸和總結      1,柜子的深度30和35cm就行,低于30太窄放不了東西      高于35餐廳會顯得窄,      2,鏤空的地方一定要做背板,      3,柜子不用裝修反彈器,也不做拉手,一個容易壞,一個不好看      建議…

論文學習——基于自適應選擇的動態多目標進化優化有效響應策略

論文題目&#xff1a;Effective response strategies based on adaptive selection for dynamic multi-objective evolutionary optimization 基于自適應選擇的動態多目標進化優化有效響應策略&#xff08;Xiaoli Li a,b,c, Anran Cao a,?, Kang Wang a&#xff09;Applied S…

零基礎STM32單片機編程入門(十五) DHT11溫濕度傳感器模塊實戰含源碼

文章目錄 一.概要二.DHT11主要性能參數三.DHT11溫度傳感器內部框圖四.DTH11模塊原理圖五.DHT11模塊跟單片機板子接線和通訊時序1.單片機跟DHT11模塊連接示意圖2.單片機跟DHT11模塊通訊流程與時序 六.STM32單片機DHT11溫度傳感器實驗七.CubeMX工程源代碼下載八.小結 一.概要 DH…

App Inventor 2 天氣預報App開發 - 第三方API接入的通用方法(2)

本文來自AppInventor2中文網&#xff08;www.fun123.cn&#xff09;參考文檔&#xff0c;調用第三方天氣接口獲取天氣JSON數據&#xff0c;解析并展示在App上。 App效果圖&#xff0c;展示未來7日的天氣預報&#xff0c;包括日期、天氣圖示和溫度&#xff1a; App原理介紹 通…

Linux/Windows 系統分區

1. Windows 系統 1.1 系統分區 系統分區也叫做磁盤分區&#xff0c;即分盤&#xff1b; 舉個例子&#xff0c;好比家里有一個大柜子&#xff0c;把衣服&#xff0c;鞋子&#xff0c;襪子都放在里面&#xff0c;由于沒有隔斷&#xff0c;找的時候非常麻煩&#xff0c;找是能找…

C++ Primer:3.2 標準庫類型string

其他章節&#xff1a;C Primer 學習心得 標準庫類型string表示可變長的字符序列&#xff0c;使用string類型必須首先頭文件&#xff0c;string定義在命名空間std中 #include <string> using std::string定義和初始化string對象 初始化類的對象是由類本身決定的&#x…

借力Jersey,鑄就卓越RESTful API體驗

目錄 maven 創建 jersey 項目 運行 支持返回 json 數據對象 1. 引言 在當今數字化時代&#xff0c;API&#xff08;應用程序編程接口&#xff09;已成為連接不同軟件系統和服務的橋梁。RESTful API以其簡潔、輕量級和易于理解的特點&#xff0c;成為了API設計的首選標準。本…

Hive函數之-posexplode()

1、概念描述&#xff1a; posexplode() 是一個內建函數&#xff0c;用于處理數組數據&#xff0c;并將數組的每個元素及其索引&#xff08;位置&#xff09;轉換為兩列的表格式數據。posexplode() 函數對于處理需要元素位置信息的數組特別有用。pos就是postion的縮寫&#xff…

Windows雙網卡上網原理以及配置方法

目錄 1. 背景 2. IP路由原理 3. windows雙網卡上網解決方案 3.1. 基礎配置解決方案 3.2. 高階配置解決方案 1. 背景 在windwos上使用多網卡在工作和生活中是一個常見的操作&#xff0c;比如為了獲取內部消息將有線連接到內部局域網中&#xff0c;為而了訪問外網又將電腦的…

華為云GaussDB部署指南:主備架構的常見問題與解決方案

文章目錄 華為云GaussDB部署指南&#xff1a;主備架構的常見問題與解決方案背景介紹部署步驟1.修改主機名2.軟件安裝檢查3.禁用交換內存4.創建數據目錄并掛載5.配置NTP時鐘同步6.添加資源限制參數7.修改網卡的MTU8.上傳安裝工具包9.編輯集群配置文件10.修改集群安裝模板11.安裝…