仅供研究学习使用。
今天带来的是数美滑块验证码的逆向
目标站 --> 传送门
解决此类验证码 首先要解决滑动距离的判定 无论是使用selenium还是使用协议的方式来破解 都绕不开滑动距离的识别
滑动距离可以参考以前我博客上的方式,或者找一找开源的一些算法,正常的opencv就可以搞定。
废话不多说我们直接进入正题。 先抓包分析接口
其实所需要逆向的就两个接口
register 获取图片以及其他加密信息。
verify 验证是否成功。
我们来看看其中有哪些参数以及返回的参数
「captchaUuid」:生成的UUID 32位随机字符串。
capchaUuID 的算法如下:
def getcapcha_uuid():
total_string = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678"
part = "".join([random.choice(total_string) for _ in range(18)])
ctime = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
captcha_uuid = f"{ctime}{part}"
return captcha_uuid
「register接口」
「organization」:每个站点的「captchaUuid」是固定的,可以看成唯一标识ID。
「其他参数」:model 为模式 模式分为:slide 滑块、auto_slide 无感验证、select 文字点选、icon_select 图标点选、seq_select 语序点选、spatial_select 空间推理,我们今天处理的是slider滑块。
「bg」背景图片
「fg」 滑块缺口地址 PS:这里如果是其他验证码 fg会变成order。order是提示信息。了解一下就行。本文不展示了。
「k,l,rid」 接口返回的值 方便verify 参数调用。
「fverify接口」
这里我们看下请求参数
下文红框中的 12个加密值都是JS返回的。不包括之前的 「organization」以及「captchaUuid」。
其中gm为最长的参数。为轨迹加密。
再看看返回值。
根据riskLevel ,pass即通过
逆向分析部分
这里在逆向前需要做个准备。本文不涉及任何解混淆。就是干
这里要注意。数美这个滑块做了格式化检测。
你一旦替换或者格式化了,js 控制台就会卡死 。
这里要注意。只有当你替换完之后重新压缩代码才会成功。
这里直接断点打在下图位置。这个是请求传参。参数已经生成。往上找栈
已经很明显的 12个参数有8个就在这里能用。
看代码分析 后面这一段 有的是_0x27c7fb(0x46e) 这种函数传参(16进制)得到des的key值 也有的是直接就是明文des的key值,所以我们还要得到_0x27c7fb解密的函数。
然后这里getEncryptContent 函数可以自己扣。
也可以自己去python还原。
其实断点打在这里。可以明显看出
第一个值是加密的值。
第二个值是密钥。
ps : 这里有个小坑:gm参数是轨迹。在使用轨迹生成的时候。识别图片得到的距离需要 / 2 。至于为什么 请看下图
至此分析结束。
代码成品运行图:
其中 ‘riskLevel’: ‘REJECT’ 大概率就是轨迹被ban了导致校验不通过,这里可以自行优化轨迹代码,我这里贴一个自用的。
def get_trajectory(self,distance):
ge = []
y = 0
v = 0
t = 1
current = 0
mid = distance * 3 / 4
exceed = 20
z = t
ge.append([0, 0, 1])
while current < (distance + exceed):
if current < mid / 2:
a = 15
elif current < mid:
a = 20
else:
a = -30
a /= 2
v0 = v
s = v0 * t + 0.5 * a * (t * t)
current += int(s)
v = v0 + a * t
y += random.randint(-5, 5)
z += 100 + random.randint(0, 10)
ge.append([min(current, (distance + exceed)), y, z])
while exceed > 0:
exceed -= random.randint(0, 5)
y += random.randint(-5, 5)
z += 100 + random.randint(0, 10)
ge.append([min(current, (distance + exceed)), y, z])
# print(ge)
return ge