注:本篇博客仅供学习使用,请勿用做其他商业用途,如有侵权,请联系我
首先进入极验官网按下F12进入开发者模式进行抓包,抓到第一个包请求参数如下,
查看响应参数可以发现,返回了需要的图片的url,网页查看,图片底图没有像极验三代一样被打乱,所以不需要还原
多刷新几次,其中变化的请求参数有,challenge和callback,但是callback很明显是时间戳,所以只剩下了challenge,全局搜索challenge。challenge其实就是由uuid生成,将其扣下直接运行即可。但是第一次请求将其直接写死也是可以的,后面需要的会由上一个请求返回
带着参数请求
session=requests.session()
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.43',
}
millis = int(round(time.time() * 1000))
params = {
'callback': 'geetest_'+str(millis),
'captcha_id': '24f56dc13c40dc4a02fd0318567caef5',
'client_type': 'web',
'risk_type': 'slide',
'pt': '1',
'lang': 'zho',
}
response = session.get('https://gcaptcha4.geetest.com/load', params=params, headers=headers).text
print(response)
使用正则将返回的url提取出来,请求该url,下载图片,后续会用上 。
bg=re.search('\"bg\":\"(.*)\.png"',response).group(1)#提取url
png1="https://static.geetest.com/"+str(bg)+'.png'
responsepng1=session.get(url=png1,headers=headers)
image=Image.open(BytesIO(responsepng1.content))
fileName=str(uuid.uuid4())+'.'+image.format.lower()
with open('D:/js/'+"jyqk.png",'wb') as f:
f.write(responsepng1.content)
qk=re.search('\"slice\":\"(.*?)\.png',response).group(1)#提取url
png2="https://static.geetest.com/"+str(qk)+'.png'
responsepng2=session.get(url=png2,headers=headers)
image1=Image.open(BytesIO(responsepng2.content))
fileName1=str(uuid.uuid4())+'.'+image.format.lower()
with open('D:/js/'+"jyhk.png",'wb') as f:
f.write(responsepng2.content)
验证滑块请求,请求携带参数,只有w需要逆向,其他的参数为固定值或者上个请求返回。
1.1 w加密
由于w太广泛,使用直接搜索不太合适,所以选择调用堆栈
跟栈进入,发现r很像我们需要的w参数,但是变量名被混淆。
将被混淆的变量名进行还原,发现就是w参数(http://www.msxindl.com/tools/unicode16.asp)
往上看 ,可以看见w参数的加密位置
代码被混淆了不好看,可以在控制台输出一下。
其实该函数就是对e进行了一下序列化,所以不用扣,直接用js代码实现即可
进入第一个大函数
前面都是各种验证,只有在最后return了一下
控制台输出发现就是我们需要的w参数。
w参数需要对c进行加密然后拼接u,网上看可以看见c,u,s的位置,e为传入的参数,先不管或者写死。
1.1.1 s参数:
进入生成s参数的函数
函数里面调用了函数,继续进
看见了math,其实s就是随机的十六为数,可以自己用python实现,也可以使用原本的js
1.1.2 u参数:
进来后发现是这个函数,使用控制台输出发现是定义在c函数原型上的一个函数,所以肯定会报c函数没有定义,遇到这种情况最好将整个大函数全部扣出来后跟着原本写的js正常调用。
将整个函数扣下来,直接调用
1.1.3 c参数:
进入c参数,将混淆的名字解出来后为encrypt,也是扣整体(js逆向能够扣整体就扣,不然后面一个函数调用一个函数,扣不完),然后正常调用
1.1.4 w加密
进入加密c的函数,直接扣就行,用js运行时可能会出现xxx未定义,缺什么补什么,继续往下扣就行
1.2 找e参数
对于e参数,需要我们细心看的就是打上箭头的,setleft为滑块的距离,passtime为滑动时间,可以直接写死,pow_msg中间的时间是由上个请求返回的,也可以自己写。其后面三个分别为定值,返回的lot_number和十六位随机数,pow_sign为pow_msg加密而来
极验所有变量名都进行了混淆,将pow_sign混淆后在搜索
l为pow_msg,进入加密函数
看着比较少,直接扣局部,后面缺什么补什么,不会补很多。
将userresponse混淆后搜索
一共十个结果,如果不确定可以全部打上断点后调试。
a为滑动距离,另一个为固定值。极验4代没有校验轨迹,所以可以不用写轨迹,只需计算滑块距离即可
使用ddddocr计算出滑块的距离
slide = ddddocr.DdddOcr(det=False, ocr=False)
with open('D:/js/jyhk.png', 'rb') as f:
target_bytes = f.read()
with open('D:/js/jyqk.png', 'rb') as f:
background_bytes = f.read()
res = slide.slide_match(target_bytes, background_bytes, simple_target=True)
left=res['target'][0]
print(left)
#取出后续需要用上的参数
lot_number=re.search('lot_number\":\"(.*?)\"',response).group(1)
current_dateTime = datetime.now()
current_dateTime=str(current_dateTime).replace(" ","T")
current_dateTime=current_dateTime+"+08:00"
powMsg="1|0|md5|"+current_dateTime+"|24f56dc13c40dc4a02fd0318567caef5|"+lot_number+"||"
token=re.search('process_token\":\"(.*?)\"',response).group(1)
payload=re.search('payload\":\"(.*?)\"',response).group(1)
#调用js,获取加密后的w,带上w进行请求
excjiami=execjs.compile(open("极验4滑块.js", 'r', encoding="utf-8").read()).call("result2", left, lot_number, powMsg)
params_all = {
'callback': 'geetest_'+str(int(round(time.time() * 1000))),
'captcha_id': '24f56dc13c40dc4a02fd0318567caef5',
'client_type': 'web',
'lot_number': lot_number,
'risk_type': 'slide',
'payload': payload,
'process_token':token,
'payload_protocol': '1',
'pt': '1',
'w':excjiami,
}
print(params_all)
response_all = session.get('https://gcaptcha4.geetest.com/verify', params=params_all, headers=headers)
print(response_all.text)
请求结果如图即为成功。
如果返回值不是图片上的,可以去极验官网看看是什么原因https://docs.geetest.com/onelogin/deploy/Returncode