案例
url: aHR0cHM6Ly93d3cuaXNodW1laS5jb20vdHJpYWwvY2FwdGNoYS5odG1s
一。获取图片
可以发现 接口里面得bg
和fg
分别是验证码图片背景图 和滑块图
domains
里面则是域名 拼接下url 这样我们就能拿到图片了
里面的k l rid
则是后续验证所需要的参数
接下来看看接口参数
callback
很明显是‘sm_’ + Date().now()
就是一个时间戳
captchaUuid搜索一下能看到
用ast
稍微解下混淆
可以看出 大致是这个样子
然后再看看最后return
的这个函数
作用就是把两个参数拼接起来
然后再看看参数 很明显是把当前的时间转化成字符串 然后再拼接上一个随机字符串
'20230920144758ByAH2EMkxRkH6WZ6ip' = '20230920144758' + 'ByAH2EMkxRkH6WZ6ip'
这样我们直接写出生成captchaUuid
的方法
function getCaptchaUuid() {
var _0xe1cb10 = ''
, _0x5514c3 = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
, _0x63a9bf = 48;
for (var _0x171d30 = 0; _0x171d30 < 18; _0x171d30++) {
_0xe1cb10 += _0x5514c3['charAt'](Math['floor'](Math['random']() * _0x63a9bf));
}
return getCurrentTimeString() + _0xe1cb10;
}
function getCurrentTimeString() {
var now = new Date();
var year = now.getFullYear();
var month = ('0' + (now.getMonth() + 1)).slice(-2);
var day = ('0' + now.getDate()).slice(-2);
var hour = ('0' + now.getHours()).slice(-2);
var minute = ('0' + now.getMinutes()).slice(-2);
var second = ('0' + now.getSeconds()).slice(-2);
var currentTimeString = year + month + day + hour + minute + second;
return currentTimeString;
}
然后organization
是一个固定值
其他的参数也是一些固定值 类似于版本信息等
二。轨迹
拿到验证码图片和滑块之后
这里我使用的是ddddocr
def distance(fg, bg):
with open('slide.png', 'wb') as f:
f.write(requests.get(fg).content)
with open('back.png', 'wb') as f:
f.write(requests.get(bg).content)
det = ddddocr.DdddOcr(det=False, ocr=False, show_ad=False)
with open('slide.png', 'rb') as f:
target_bytes = f.read()
with open('back.png', 'rb') as f:
background_bytes = f.read()
res = det.slide_match(target_bytes, background_bytes, simple_target=True)
res = res.get('target')[0]
return int(res / 2)
识别出来的距离/2就是滑块正确的位置
复制一段真实的轨迹 然后根据识别出的距离进行缩放
def tt(X):
base_track = [[0, -8, 11], [0, -8, 102], [31, 0, 208], [45, 0, 301], [57, 1, 401], [66, 2, 504], [71, 2, 602], [74, 3, 705], [78, 4, 802], [82, 4, 904], [82, 4, 1003]]
scale = X / base_track[-1][0]
r = []
for item in base_track:
x = int(item[0] * scale) + random.randint(0, 5)
y = int(item[1] * scale) + random.randint(-1, 1)
z = item[2] + random.randint(1, 100)
r.append([x,y,z])
return r
三。验证
验证接口的参数看似很多
params = {
"captchaUuid": self.captchaUuid,
"rid": rid,
"hd": "w6ArMUdGI6s=",
"act.os": "web_pc",
"xc": "MPQBHp3MK74=",
"qu": "Q/IW6xhk8TI=",
"jv": "tnws0FUkt6c=",
"us": "zY8brT9SISY=",
"xy": "xIAv2QAUoJA=",
"ma": "Ku1yrQmmWo8=",
"sdkver": "1.1.3",
"ostype": "web",
"protocol": "179",
"ee": result.get('ee'),
"ml": result.get('ml'),
"rversion": "1.0.4",
"rj": "LpMN9yrHH3I=",
"callback": f"sm_{int(time.time()*1000)}",
"jn": "w6ook9DZFNo=",
"organization": self.organization,
"ra": result.get('ra')
}
实际大多是固定值
其中需要生成的有 ee ml ra
rid
是从验证码图片接口获取的
搜索getMouseAction
就能看到大致加密等的一些流程
其中k
和l
是我们获取验证码图片接口时获取的 mousedata
则是轨迹数组,X是缺口距离
补上一些环境之后 调用
就能获取到所有的参数
总结:难度较低,轨迹校验不严,随便搞搞都能过,环境也简单补就行了