立即加星标
每月看好文
趣味模块
一、前言介绍
滑块验证码(Slider Captcha),又称拼图验证码或滑动验证码,是一种常见的验证机制,旨在防止机器人和恶意攻击者对网站进行自动化操作。与传统验证码不同,滑块验证码需要用户通过将一个滑块拖动到正确的位置来完成验证。
通常,滑块验证码由两部分组成:一个背景图像和一个滑块。在验证过程中,用户需要按照提示将滑块拖动到正确的位置。为了防止针对验证码的攻击,滑块验证码会使用多种技术来检测用户的行为模式并确定是否存在异常行为,例如反复尝试拖动滑块或使用自动化脚本进行操作。
某美验证码的应用非常广泛,像某书、某街就是使用了某美滑块来进行风控的,当爬虫没有使用代理ip、ip质量比较差或者单个代理ip使用次数过多的时候,就会出现滑块验证码,严重的时候还会出现无限滑块的情况。总之,滑块验证码是一种常见的验证机制,因其易于使用和安全性高而被广泛应用于各种网站和应用程序中。
二、网站分析
1、抓包分析,打开我们本次分析的网站,拖动滑块到任意位置。然后查看请求流程如下:
2、标红的框主要是滑块生成接口和滑块请求的验证接口以及滑块图片。我们先查看下register滑块图片生成接口,截图如下:
说明:因为register接口有两个,此刻我们需要确认fverify验证码校验接口使用的是哪一个register接口?这里我们先留个疑问。
3、紧接着我们查看下fverify验证码校验接口,截图如下所示:
4、因为滑块没有通过,触发了REJECT机制。紧接着我们分析下fverify的payload参数结构体,截图如下:
说明:查看fverify请求结构体,我们确认rid和第一次register请求接口response中的rid一致,我们可以确定本次验证请求和register第一个接口相关联。
5、接下来,我们将滑块滑动通过校验,查看下验证成功的response结果,截图如下:
总结:我们只需要对fverify接口的payload参数体进行算法还原,然后验证接口返回为PASS即可完成滑块逆向分析。那么接下来,让我们进入参数逆向环节吧。
三、参数逆向
1、 我们多次触发fverify接口请求,观察参数变动,最终确定以下参数会变动:
2、接下来,对上面五个参数进行初判断:
-
callback sm_拼接毫秒级时间戳。
-
rid 此参数通过register接口返回。
-
ee 以往经验感觉是轨迹加密值。
-
ra 加密值,不是坐标就是时间。
-
ml 加密值,不是坐标就是时间。
总结:我们可以忽略callback、rid参数,只需要逆向分析ee、ra、ml即可完成对滑块算法的还原,接下来我们开始堆栈分析进行断点调试吧。
3、我们通过fverify接口的堆栈定位js文件,由于网站使用了定时函数,断点断在发请求出的话堆栈不好跟踪,所以可以选择在setTimeout函数前的每个堆栈都下一个断点,观察下加密参数最早在哪边出现的。截图如下:
4、打好断点后,再次滑动代码,我们可以发现在"_0x9baf4e"位置,已经有加密参数生成,截图如下:
5、那么全局搜索一下这个变量,看下是在哪里进行赋值的。接着搜索定位到了变量赋值的地方,是通过调用this['getMouseAction']()生成的加密对象。我们继续跟进,看看这个函数是如何进行加密的。
6、继续断点跟进后,由下图可知,加密参数的生成位置出来了,截图如下:
7、跟进ml参数断点,此刻我们可以确定ml、ee、ra参数使用的是DES加密算法,截图如下:
8、分析下加密代码,加密函数主要就是使用了对称加密算法des来进行加密,同时也能清晰的观察到传入的参数和密钥,简化出来的目标参数生成逻辑伪代码如下:
总结:参数分析流程到这里就结束了,接下来我们进入算法还原环节。分别对DES加密算法还原、滑块距离计算、滑块轨迹模拟进行还原吧。
四、算法还原
1、在Console中拿到ml参数的横向滑动距离102/300,以及DES的密钥key:2a29ac9a,编写算法如下:
import base64
from Crypto.Cipher import DES
from Crypto.Util.Padding import pad
def des_encrypt(key, text):
"""使用DES算法对文本进行加密"""
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)
运行代码后,我们查看pycharm中,结果输出如下:
科普:通过上图,我们发现des加密算法不是常规的des加密。des默认块填充为DES.block_size=8(字节),如果需要填充5个字节,那么填充的内容将是 b'x05x05x05x05x05',其中 x05 表示字节的十六进制值为5,解密时会检测并移除这种填充。而我们查看JS中des加密逻辑,发现此处填充的内容为x00,于是我们修改代码如下图所示:
我们再次运行代码后,可以看到python还原的值和js中加密的值结果一致,截图如下:
2、参数加密算法搞定后,紧接着我们来搞定滑块x坐标距离,我们使用OpenCV来识别图片,计算滑动距离。编辑完整代码如下:
3、在得到x坐标滑动距离后,我们进行轨迹模拟,经过反复的修正轨迹,最终确定代码如下:
import random
def generate_tracks(distance):
"""生成轨迹"""
tracks = []
initial_velocity = 0
time_interval = 1
current_distance = 0
target_midpoint = distance * 3 / 4
exceed_threshold = 20
initial_height = 1
0, initial_height])
while current_distance < (distance + exceed_threshold):
if current_distance < target_midpoint / 2:
acceleration = 15
elif current_distance < target_midpoint:
acceleration = 20
else:
acceleration = -30
acceleration /= 2
initial_velocity = initial_velocity
displacement = 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_change
depth = 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_change
depth += 100 + random.randint(0, 10)
(distance + exceed_threshold))), height, depth])
return tracks
4、以上三步流程搞定后,我们编辑增加ml、ee、ra参数流程生成代码如下:
5、加密算法还原、滑块距离识别、滑块轨迹模拟完成后,我们结合完整流程发送20次接口请求,验证效果截图如下:
总结:滑动成功率还是挺高的,18/20=90%;如果想要追求更高的通过率的话,可以进一步优化下图像识别和轨迹模拟这两方面。
五、思路总结
回顾整个分析流程,本次重点主要概括为以下几点:
-
DES魔改算法还原实现 -
滑块缺口位置坐标定位 -
滑块数组轨迹模拟生成 -
混淆代码中确定加密位置
原文始发于微信公众号(逆向与爬虫的故事):某美滑块验证码别乱捅!一不小心就反爬了。
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论