第一次请求获取 gt 和 challenge 参数,后面会用到。
第四次请求返回值,可以看见返回的值比较多也许加密时会用到,用记事本记录下来。(推荐Notepad++)
拖动滑块就能看到请求参数只有W是加密的,找到加密位置即可。
极验3代的滑块图片是乱序的需要还原,轨迹也需要生成,暂时留个坑有时间再更新。
寻找加密的方式多种多样看个人喜好,这里从请求发包开始寻找(主要是方便),点击第四次请求的堆栈选项,然后再点击第一个选项,进入js代码。
跳转js后点击{}代码格式化,chrome会出现黄色的提示,在提示行打上断点,然后按F10单步执行。
js跳到这里时,可以看见比较多的明文值(如果你的浏览器不显示可以按Ctrl键),这也是判断加密函数的关键因素,将可疑的值在控制台打印出来,可以看到w,client_type,再对比上面拖动滑块的请求参数,基本可以断定这里就是加密位置。
h和u生成的位置,都打上断点,然后进行单步调试,首先看u是如何生产的。
t = undefined
this[$_CBEEc(742)](t) //是随机数
new X()[$_CBEEc(342)] // 加密函数
生成一个16位的随机数,然后将随机数传入new X()[$_CBEEc(342)]进行加密,最后得到256位的字符串。
这里有一个小细节:随机数在后面的请求过程中有2处地方会用到,由于作者使用函数生成,导致2处的随机数不一样,最终请求不成功,经过2天的排查和大佬的指点才找到问题所在,所以随机数取固定值即可。
解密l参数前,需要知道o对象是如何生产的,这也是该案例的核心点。
{
"lang": "zh-cn",
"userresponse": "5777757775777783",
"passtime": 834,
"imgload": 75,
"aa": "F(!!Csssssssussstxsssssusts@tstzssztssssusssBsstssssszssssssssxssssM(!!($)).*,,)*,)),)))))**(*)*)*)*v)),)))))))))))))**(*)*))*)),)**)*,F",
"ep": {
"v": "7.8.6",
"$_BHR": false,
"me": true,
"tm": {
"a": 1656134048892,
"b": 1656134048977,
"c": 1656134049003,
"d": 0,
"e": 0,
"f": 1656134048893,
"g": 1656134048899,
"h": 1656134048900,
"i": 1656134048900,
"j": 1656134048911,
"k": 1656134048903,
"l": 1656134048911,
"m": 1656134048969,
"n": 1656134048976,
"o": 1656134049009,
"p": 1656134049118,
"q": 1656134049118,
"r": 1656134049118,
"s": 1656134051244,
"t": 1656134051245,
"u": 1656134051245
},
"td": -1
},
"x04r": "1585951055",
"rp": "95d1bddba7c049c7d4fb558e08dce1c5"
}
可以看到o对象里面有众多参数
aa 轨迹加密
ep x04r imgload lang 可固定
userresponse 滑动距离 + challenge 加密结果
passtime 拖动时间
rp challenge + gt + passtime 加密结果
这里有3个参数,还记得之前用记事本保存的返回值吗,这里用到c和s两个值,第一个值也是最重要的轨迹值,通过加密后最终得到相应的值,关于轨迹的生成可以参考大佬的代码
def __ease_out_expo(sep):
'''
轨迹相关操作
'''
if sep == 1:
return 1
else:
return 1 - pow(2, -10 * sep)
def get_slide_track(distance):
"""
根据滑动距离生成滑动轨迹
:param distance: 需要滑动的距离
:return: 滑动轨迹: [[x,y,t], ...]
x: 已滑动的横向距离
y: 已滑动的纵向距离, 除起点外, 均为0
t: 滑动过程消耗的时间, 单位: 毫秒
"""
if not isinstance(distance, int) or distance < 0:
raise ValueError(f"distance类型必须是大于等于0的整数: distance: {distance}, type: {type(distance)}")
# 初始化轨迹列表
slide_track = [
[random.randint(-50, -10), random.randint(-50, -10), 0],
[0, 0, 0],
]
# 共记录count次滑块位置信息
count = 30 + int(distance / 2)
# 初始化滑动时间
t = random.randint(50, 100)
# 记录上一次滑动的距离
_x = 0
_y = 0
for i in range(count):
# 已滑动的横向距离
x = round(__ease_out_expo(i / count) * distance)
# 滑动过程消耗的时间
t += random.randint(10, 20)
if x == _x:
continue
slide_track.append([x, _y, t])
_x = x
slide_track.append(slide_track[-1])
return slide_track
print(get_slide_track(80))
[[-27, -11, 0], [0, 0, 0], [8, 0, 75], [14, 0, 93], [21, 0, 105], [26, 0, 125], [31, 0, 143], [36, 0, 156], [40, 0, 168], [44, 0, 178], [47, 0, 188], [50, 0, 202], [53, 0, 216], [56, 0, 232], [58, 0, 243], [60, 0, 256], [62, 0, 269], [64, 0, 287], [65, 0, 305], [67, 0, 320], [68, 0, 336], [69, 0, 352], [70, 0, 372], [71, 0, 383], [72, 0, 402], [73, 0, 417], [74, 0, 455], [75, 0, 488], [76, 0, 519], [77, 0, 548], [78, 0, 587], [79, 0, 676], [80, 0, 834], [80, 0, 834]]
传入滑动距离后就能生成轨迹,o对象的passtime值就是取的最后一个值。
至此o对象的参数已经全部组成,然后在进行加密,会得到一个数组
数组再次加密后就得到值u ,h, l三个值全部拿到,大功告成!