某美滑塊驗(yàn)證碼別亂捅!一不小心就反爬了.
“
閱讀本文大概需要 7 分鐘。
大家好,我是 TheWeiJun!經(jīng)過一段時(shí)間的等待,我終于回來了。在這段間隙里,我毫無保留地投入精力,為大家精心打造了一篇關(guān)于某美驗(yàn)證碼逆向分析的文章。如果你希望第一時(shí)間閱讀我的最新內(nèi)容,請(qǐng)務(wù)必關(guān)注我的公眾號(hào)!盡管在這篇內(nèi)容更新后,因個(gè)人安排的需要,我將稍作休息幾個(gè)月。然而我堅(jiān)信,這篇文章會(huì)讓你欲罷不能。廢話不多說,讓我們一同探索吧!
特別聲明: 本公眾號(hào)文章只作為學(xué)術(shù)研究,不作為其他不法用途;如有侵權(quán)請(qǐng)聯(lián)系作者刪除。
立即加星標(biāo)
每月看好文
趣味模塊
小江, 一位出色的IT工程師,常常被頻繁的 IP 請(qǐng)求所困擾,滑塊驗(yàn)證碼像難纏的門神一樣擋在他前進(jìn)的路上。然而,他不甘心被困擾,于是決心尋找解決之道。通過還原算法、模擬軌跡、識(shí)別滑塊距離,他逐漸揭開了滑塊驗(yàn)證碼的神秘面紗。經(jīng)過不懈的努力,他終于成功破解了滑塊的詭計(jì),讓這個(gè)煩人的問題不再是他的困擾。小江的故事鼓舞著許多人,教導(dǎo)我們無論面對(duì)多大的挑戰(zhàn),只要用心探索,就能找到通向勝利的路徑。 (GPT 故事情節(jié)虛構(gòu)) 小江 公眾號(hào)如下:
一、前言介紹
滑塊驗(yàn)證碼(Slider Captcha),又稱拼圖驗(yàn)證碼或滑動(dòng)驗(yàn)證碼,是一種常見的驗(yàn)證機(jī)制,旨在防止機(jī)器人和惡意攻擊者對(duì)網(wǎng)站進(jìn)行自動(dòng)化操作。與傳統(tǒng)驗(yàn)證碼不同,滑塊驗(yàn)證碼需要用戶通過將一個(gè)滑塊拖動(dòng)到正確的位置來完成驗(yàn)證。
通常,滑塊驗(yàn)證碼由兩部分組成:一個(gè)背景圖像和一個(gè)滑塊。在驗(yàn)證過程中,用戶需要按照提示將滑塊拖動(dòng)到正確的位置。為了防止針對(duì)驗(yàn)證碼的攻擊,滑塊驗(yàn)證碼會(huì)使用多種技術(shù)來檢測(cè)用戶的行為模式并確定是否存在異常行為,例如反復(fù)嘗試拖動(dòng)滑塊或使用自動(dòng)化腳本進(jìn)行操作。
某美驗(yàn)證碼的應(yīng)用非常廣泛,像某書、某街就是使用了某美滑塊來進(jìn)行風(fēng)控的,當(dāng)爬蟲沒有使用代理 ip、ip 質(zhì)量比較差或者單個(gè)代理ip使用次數(shù)過多的時(shí)候,就會(huì)出現(xiàn)滑塊驗(yàn)證碼,嚴(yán)重的時(shí)候還會(huì)出現(xiàn)無限滑塊的情況。總之,滑塊驗(yàn)證碼是一種常見的驗(yàn)證機(jī)制,因其易于使用和安全性高而被廣泛應(yīng)用于各種網(wǎng)站和應(yīng)用程序中。
二、網(wǎng)站分析
1、抓包分析,打開我們本次分析的網(wǎng)站,拖動(dòng)滑塊到任意位置。然后查看請(qǐng)求流程如下:


2、標(biāo)紅的 框主要是 滑塊生成接口和滑塊請(qǐng)求的驗(yàn)證接口以及滑塊圖片。 我們先查看下 register 滑塊圖片生成接口, 截圖如下:
說明: 因?yàn)?register 接口有兩個(gè),此刻我們需要確認(rèn) fverify 驗(yàn)證碼校驗(yàn)接口使用的是哪一個(gè) register 接口?這里我們先留個(gè)疑問。
3、緊接著我們查看下 fverify 驗(yàn)證碼校驗(yàn)接口,截圖如下所示:

4、因?yàn)榛瑝K沒有通過,觸發(fā)了 REJECT 機(jī)制。緊接著我們分析下 fverify 的 payload 參數(shù)結(jié)構(gòu)體,截圖如下:

說明: 查看 fverify 請(qǐng)求結(jié)構(gòu)體,我們確認(rèn) rid 和第一次 register 請(qǐng)求接口 response 中的 rid 一致,我們可以確定本次驗(yàn)證請(qǐng)求和 register 第一個(gè)接口相關(guān)聯(lián)。
5、接下來,我們將滑塊滑動(dòng)通過校驗(yàn),查看下驗(yàn)證成功的 response 結(jié)果,截圖如下:

總結(jié): 我們只需要對(duì) fverify 接口的 payload 參數(shù)體進(jìn)行算法還原,然后驗(yàn)證接口返回為 PASS 即可完成滑塊逆向分析。那么接下來,讓我們進(jìn)入?yún)?shù)逆向環(huán)節(jié)吧。
三、參數(shù)逆向
1、 我們多次觸發(fā) fverify 接口請(qǐng)求,觀察參數(shù)變動(dòng),最終確定以下參數(shù)會(huì)變動(dòng):

2、接下來,對(duì)上面五個(gè)參數(shù)進(jìn)行初判斷:
-
callback sm_ 拼接毫秒級(jí)時(shí)間戳。
-
rid 此參數(shù)通過 register 接口返回。
-
ee 以往經(jīng)驗(yàn)感覺是軌跡加密值。
-
ra 加密值,不是坐標(biāo)就是時(shí)間。
-
ml 加密值,不是坐標(biāo)就是時(shí)間。
總結(jié): 我們可以忽略 callback、rid 參數(shù),只需要逆向分析 ee、ra、ml 即可完成對(duì)滑塊算法的還原,接下來我們開始堆棧分析進(jìn)行斷點(diǎn)調(diào)試吧。
3、我們通過 fverify 接口的堆棧定位 js 文件,由于網(wǎng)站使用了定時(shí)函數(shù),斷點(diǎn)斷在發(fā)請(qǐng)求出的話堆棧不好跟蹤,所以可以選擇在 setTimeout 函數(shù)前的每個(gè)堆棧都下一個(gè)斷點(diǎn),觀察下加密參數(shù)最早在哪邊出現(xiàn)的。截圖如下:

4、打好斷點(diǎn)后,再次滑動(dòng)代碼,我們可以發(fā)現(xiàn)在"_0x9baf4e"位置,已經(jīng)有加密參數(shù)生成,截圖如下:

5、那么全局搜索一下這個(gè)變量,看下是在哪里進(jìn)行賦值的。接著搜索定位到了變量賦值的地方,是通過調(diào)用 this['getMouseAction']() 生成的加密對(duì)象。我們繼續(xù)跟進(jìn),看看這個(gè)函數(shù)是如何進(jìn)行加密的。

6、繼續(xù)斷點(diǎn)跟進(jìn)后,由下圖可知,加密參數(shù)的生成位置出來了,截圖如下:

7、跟進(jìn)ml參數(shù)斷點(diǎn),此刻我們可以確定 ml、ee、ra 參數(shù)使用的是 DES 加密算法,截圖如下:

8、分析下加密代碼,加密函數(shù)主要就是使用了對(duì)稱加密算法 des 來進(jìn)行加密,同時(shí)也能清晰的觀察到傳入的參數(shù)和密鑰,簡(jiǎn)化出來的目標(biāo)參數(shù)生成邏輯偽代碼如下:

總結(jié): 參數(shù)分析流程到這里就結(jié)束了,接下來我們進(jìn)入算法還原環(huán)節(jié)。分別對(duì) DES 加密算法還原、滑塊距離計(jì)算、滑塊軌跡模擬進(jìn)行還原吧。
四、算法還原
1、在 Console 中拿到 ml 參數(shù)的橫向滑動(dòng)距離 102/300,以及DES 的密鑰 key:2a29ac9a,編寫算法如下:
import base64from Crypto.Cipher import DESfrom Crypto.Util.Padding import pad
def des_encrypt(key, text):"""使用DES算法對(duì)文本進(jìn)行加密"""key = key.encode('utf-8')text = text.encode('utf-8')cipher = DES.new(key, DES.MODE_ECB)padded_text = pad(text, DES.block_size)encrypted_bytes = cipher.encrypt(padded_text)encrypted_base64 = base64.b64encode(encrypted_bytes).decode('utf-8')return encrypted_base64
if __name__ == '__main__':key = '2a29ac9a'text = str(102/300)ori_encrypt = "mJRZFPayX/Y="print(text, des_encrypt(key, text), ori_encrypt)
運(yùn)行代碼后,我們查看 pycharm 中,結(jié)果輸出如下:

科普: 通過上圖,我們發(fā)現(xiàn) des 加密算法不是常規(guī)的 des 加密。des 默認(rèn)塊填充為 DES.block_size=8(字節(jié)),如果需要填充 5 個(gè)字節(jié),那么填充的內(nèi)容將是 b'\x05\x05\x05\x05\x05',其中 \x05 表示字節(jié)的十六進(jìn)制值為 5,解密時(shí)會(huì)檢測(cè)并移除這種填充。而我們查看 JS 中 des 加密邏輯,發(fā)現(xiàn)此處填充的內(nèi)容為 x00,于是我們修改代碼如下圖所示:

我們?cè)俅芜\(yùn)行代碼后,可以看到 python 還原的值和 js 中加密的值結(jié)果一致,截圖如下:

2、參數(shù)加密算法搞定后,緊接著我們來搞定滑塊 x 坐標(biāo)距離,我們使用 OpenCV 來識(shí)別圖片,計(jì)算滑動(dòng)距離。編輯完整代碼如下:

3、在得到 x 坐標(biāo)滑動(dòng)距離后,我們進(jìn)行軌跡模擬,經(jīng)過反復(fù)的修正軌跡,最終確定代碼如下:
import random
def generate_tracks(distance):"""生成軌跡"""tracks = []
initial_velocity = 0time_interval = 1current_distance = 0target_midpoint = distance * 3 / 4exceed_threshold = 20initial_height = 1
0, initial_height])
while current_distance < (distance + exceed_threshold):if current_distance < target_midpoint / 2:acceleration = 15elif current_distance < target_midpoint:acceleration = 20else:acceleration = -30acceleration /= 2
initial_velocity = initial_velocitydisplacement = initial_velocity * time_interval + 0.5 * acceleration * (time_interval * time_interval)current_distance += int(displacement)initial_velocity += acceleration * time_interval
height_change = random.randint(-5, 5)height = tracks[-1][1] + height_changedepth = tracks[-1][2] + 100 + random.randint(0, 10)
(distance + exceed_threshold))), height, depth])
while exceed_threshold > 0:exceed_threshold -= random.randint(0, 5)height_change = random.randint(-5, 5)height += height_changedepth += 100 + random.randint(0, 10)(distance + exceed_threshold))), height, depth])
return tracks
4、以上三步流程搞定后,我們編輯增加 ml、ee、ra 參數(shù)流程生成代碼如下:

5、加密算法還原、滑塊距離識(shí)別、滑塊軌跡模擬完成后,我們結(jié)合完整流程發(fā)送 20 次接口請(qǐng)求,驗(yàn)證效果截圖如下:

總結(jié): 滑動(dòng)成功率還是挺高的,18/20=90%;如果想要追求更高的通過率的話,可以進(jìn)一步優(yōu)化下圖像識(shí)別和軌跡模擬這兩方面。
五、思路總結(jié)
回顧整個(gè)分析流程,本次重點(diǎn)主要概括為以下幾點(diǎn):
- DES 魔改算法還原實(shí)現(xiàn)
- 滑塊缺口位置坐標(biāo)定位
- 滑塊數(shù)組軌跡模擬生成
- 混淆代碼中確定加密位置
本篇分享到這里就結(jié)束了,歡迎大家關(guān)注下期文章,我們不見不散??????

END

作者簡(jiǎn)介
我是TheWeiJun,有著執(zhí)著的追求,信奉終身成長(zhǎng),不定義自己,熱愛技術(shù)但不拘泥于技術(shù),愛好分享,喜歡讀書和樂于結(jié)交朋友,歡迎掃我微信與我交朋友?? 分享日常學(xué)習(xí)中關(guān)于爬蟲及逆向分析的一些思路,文中若有錯(cuò)誤的地方,歡迎大家多多交流指正??

點(diǎn)分享

點(diǎn)收藏

點(diǎn)點(diǎn)贊

點(diǎn)在看
