聲明
本文章中所有內(nèi)容僅供學(xué)習(xí)交流,抓包內(nèi)容逻翁、敏感網(wǎng)址饥努、數(shù)據(jù)接口均已做脫敏處理,嚴(yán)禁用于商業(yè)用途和非法用途卢未,否則由此產(chǎn)生的一切后果均與作者無關(guān)肪凛,若有侵權(quán),請聯(lián)系我立即刪除辽社!
本文章未經(jīng)許可禁止轉(zhuǎn)載伟墙,禁止任何修改后二次傳播,擅自使用本文講解的技術(shù)而導(dǎo)致的任何意外滴铅,作者均不負(fù)責(zé)戳葵,若有侵權(quán),請在公眾號【K哥爬蟲】聯(lián)系作者立即刪除汉匙!
逆向目標(biāo)
- 目標(biāo):某驗四代滑塊驗證碼拱烁,w 參數(shù)逆向
- 主頁:
aHR0cHM6Ly9ndDQuZ2VldGVzdC5jb20v
- 加密算法:RSA、AES
通訊流程
驗證碼流程分析
進(jìn)入網(wǎng)頁后噩翠,打開開發(fā)者人員工具進(jìn)行抓包戏自,點(diǎn)擊滑動拼圖驗證,此時還未點(diǎn)擊按鈕開始驗證伤锚,抓到了一個名為 load?captcha_id=xxx
的包擅笔,Query String Parameters
包含了一些參數(shù):
-
captcha_id
:驗證碼 id,固定值屯援,由adaptive-captcha-demo.js
文件生成猛们,后文分析; -
challenge
:動態(tài)變化狞洋,由gtc4.js
文件生成弯淘,后文分析; -
client_type
:表示 web 端吉懊; -
risk_type
:驗證碼類型庐橙,例如滑塊為 slide,無感為 ai借嗽; -
lang
:語言怕午; -
callback
:geetest_ + 時間戳,主要作用是防止緩存淹魄。
響應(yīng)預(yù)覽中返回的關(guān)鍵內(nèi)容如下,相較于三代堡距,底圖未做混淆:
-
bg
:背景圖片地址甲锡; -
captcha_type
:驗證碼類型兆蕉; -
gct_path
:gct4 文件路徑; -
lot_number
:后續(xù)生成 pow_msg缤沦、w 的關(guān)鍵參數(shù)虎韵; -
payload
:后續(xù) verify 請求接口需要的參數(shù); -
datetime
:ISO 8601擴(kuò)展格式的日期缸废,后續(xù)生成 pow_msg 的關(guān)鍵參數(shù)包蓝; -
process_token
:后續(xù) verify 請求接口需要的參數(shù); -
slice
:滑塊圖片地址企量。
點(diǎn)擊按鈕開始驗證测萎,彈出滑塊驗證碼,滑動滑塊届巩,抓包到 verify?captcha_id=xxx
硅瞧,Query String Parameters
同樣包含了一些參數(shù):
-
captcha_id
:與 load 接口請求頭中的 captcha_id 一致; -
client_type
:表示 web 端恕汇; -
lot_number
:load 接口返回的腕唧; -
risk_type
:與 load 接口中的一致,表示驗證碼類型瘾英; -
payload
:load 接口返回的枣接; -
process_token
:load 接口返回的; -
w
:加密參數(shù)缺谴,由軌跡但惶、滑動時間、滑動距離瓣赂、userresponse榆骚、device_id、pow_msg 等參數(shù)加密得到煌集; -
callback
:geetest_ + 時間戳妓肢,主要作用是防止緩存。
響應(yīng)預(yù)覽中返回的內(nèi)容如下苫纤,result 值為 fail 即校驗失敗碉钠,success 為校驗通過,通過后攜帶 seccode 下的參數(shù)進(jìn)行后續(xù)業(yè)務(wù)請求:
逆向分析
captcha_id 參數(shù)
全局搜索 captcha_id
卷拘,跟進(jìn)到 gt4.js 文件中:
進(jìn)去后在第 307 行打上斷點(diǎn)喊废,刷新頁面即會斷住,此時 captcha_id
參數(shù)的值已經(jīng)生成栗弟,同時 challenge 參數(shù)定義在下一行:
向上跟棧到 value污筷,即 adaptive-captcha-demo.js
文件中,會發(fā)現(xiàn)其是個固定值乍赫,實(shí)際上這個值是每個網(wǎng)站不一樣瓣蛀,是管理員在極驗后臺申請得到的:
challenge 參數(shù)
前面提到陆蟆,challenge
參數(shù)定義在 captcha_id
參數(shù)的下一行,在 gt4.js 文件的第 309 行打下斷點(diǎn):
可以看到惋增,challenge 參數(shù)的值由 uuid
函數(shù)生成叠殷,扣出即可。
w 參數(shù)
從 verify?captcha_id=xxx
接口的堆棧處跟棧進(jìn)去:
打下斷點(diǎn)滑動滑塊斷住后诈皿,向上跟棧到 s 處林束,如果做過某驗三代滑塊的話,第 6249 行有個很熟悉的東西稽亏,"\u0077": r
壶冒,"\u0077"
即字母 w 的 Unicode 值,r 即 w 參數(shù)的值:
r 參數(shù)定義在第 6237 行措左,e 也是跟三代類似的參數(shù)依痊,r 是將 i 參數(shù)和轉(zhuǎn)為字符串的 e 參數(shù)加密得到的:
向上跟棧,找到 e 參數(shù)中各部分定義生成的位置怎披,跟到 $_BHIH
中胸嘁,_ 中先生成了四個鍵值對:
passtime
和 track
是熟悉的滑動時間和軌跡,setLeft
為識別出來的缺口距離凉逛,userresponse
定義在 19593 行性宏, a 為 setLeft
參數(shù)的值,t[$_GDFCG(1909)]
為定值 1.0059466666666665:
a / t[$_GDFCG(1909)] + 2
接著跟到 $_BCFj
中状飞,e 定義在第 6201 行毫胜,下面幾行定義了 e 中的 device_id
、lot_number
诬辈、pow_msg
酵使、pow_sign
:
device_id
同一個網(wǎng)站是固定值,lot_number
是 load 響應(yīng)返回的焙糟,控制臺打印一下 pow_msg
口渔、pow_sign
的結(jié)果:
pow_msg
很明顯是由幾部分組成的,pow_sign
經(jīng)過加密穿撮,向上跟棧到 init 中缺脉,分別定義在第 5837 行和第 5838 行,為 d 字典的鍵悦穿,根據(jù)鍵名取值:
d 定義在第 5835 行攻礼,這部分還原一下就很明顯了:
var c = t["toDataURL"]()["replace"]("data:image/png;base64,", "")
, _ = new w["default"]["MD5"]()["hex"](c);
a["options"]["deviceId"] = _;
var h = a["options"]
, l = h["powDetail"]
, p = h["lotNumber"]
, f = h["captchaId"]
, d = v["default"](p, f, l["hashfunc"], l["version"], l["bits"], l["datetime"], "")
跟進(jìn)到 v["default"]
中,函數(shù)定義在第 6945 行栗柒,于 6978 行打下斷點(diǎn):
pow_msg
由 _ + h
得到礁扮,_
定義在第 6960 行:
_ = i + "|" + r + "|" + n + "|" + s + "|" + t + "|" + e + "|" + o + "|";
- i:
l["version"]
- r:
l["bits"]
- n:
l["hashfunc"]
- s:
l["datetime"]
- t:
f, h["captchaId"]
- e:
p, h["lotNumber"]
- o:
""
h 定義在第 6269 行,跟進(jìn)去是 16 位隨機(jī)數(shù)字符串,pow_sign
為 p深员,就是 pow_msg
經(jīng)過 MD5 加密得到的:
至此這四個也分析完了负蠕,還差以下這部分:
em 等定值就不分析了,注意 kqg5:"1557244628"
倦畅,這個參數(shù)值和三代滑塊中一樣,每隔幾個小時會改變绣的,向上跟棧到 $_BCFj
中叠赐,在第 6207 行打下斷點(diǎn),此時 e 中這個值還未生成:
下一行打下斷點(diǎn)屡江,下步斷點(diǎn)芭概,即執(zhí)行完 n[$_CBHIE(791)](e);
后,這個參數(shù)值就生成了惩嘉,證明是 n[$_CBHIE(791)]
方法生成的罢洲,跟進(jìn)去:
跳轉(zhuǎn)到第 5766 行,在第 5779 行打下斷點(diǎn)文黎,此時的 n 中還未生成此參數(shù):
執(zhí)行了 _gct(n)
后即生成:
可見其生成位置在 _gct
方法中惹苗,跟進(jìn)去后到 gct4.js 文件,和三代大差不差:
可以將值導(dǎo)出耸峭,至此 e 就分析完了桩蓉,接著回到第 6238 行,跟進(jìn)到加密函數(shù) d[$_CBHHO(84)]
中劳闹,定義在第 11669 行院究,d[$_DIEHS(177)](c) + u
即 r 參數(shù)的值,c 為一個大數(shù)組本涕,u 明顯也經(jīng)過加密了业汰,所以 r 參數(shù)的值就是數(shù)組 c 加密后再加上 u 得到的:
先跟進(jìn)到 u,其定義在第 11705 行菩颖,解混淆后如下:
u = new l["default"]()["encrypt"](i);
所以 u 是 i 經(jīng)過加密后得到的样漆,i 定義在第 11702 行:
i = (0,d[$_DIEIq(103)])()
跟進(jìn)到 d[$_DIEIq(103)]
中,定義在第 852 行位他,又是熟悉的 16 位隨機(jī)數(shù):
i 是隨機(jī)數(shù)氛濒,跟進(jìn)到加密函數(shù) l[($_DIEHS(84))]
中,在第 12725 行鹅髓,于 12741 行打下斷點(diǎn)舞竿,可以看到這里就是個 RSA 加密,扣代碼或者直接引庫即可:
回到 c 參數(shù)窿冯,c 參數(shù)的值為一個大數(shù)組骗奖,其定義在第 11705 行,解混淆后內(nèi)容如下:
var c = s[a]["symmetrical"]["encrypt"](e, i);
e 之前分析完了,i 為隨機(jī)數(shù)执桌,兩個參數(shù)已經(jīng)分析完了鄙皇,跟進(jìn)到加密方法中,在第 12174 行仰挣,于 12186 行打下斷點(diǎn)伴逸,控制臺打印一下混淆部分內(nèi)容,很熟悉的東西膘壶,這里就是 AES 加密错蝴,iv 為初始向量,加密模式為 CBC颓芭,對各類加密算法不熟悉的顷锰,可以閱讀 K 哥文章 【爬蟲知識】爬蟲常見加密解密算法:
c 參數(shù)最后又被 d[$_DIEHS(177)]
函數(shù)加密,跟進(jìn)后亡问,定義在第 547 行官紫,直接扣下來改改即可: