爬虫逆向之易盾文字点选分析
本文章中所有内容仅供学习交流使用,不用于其他任何目的。否则由此产生的一切后果均与作者无关!
目录
1.cb值
2.验证码识别
3.验证接口分析
4.m值
参数分析
轨迹生成分析(生成轨迹函数)
轨迹加密处理
5.P值
6.ext值
总结
目标网站:图片点选验证码_图片验证码_验证码接口_在线体验_网易易盾
1.cb值
图片验证码接口。有三个值是需要提取的
文字,图片链接,token
效验加密参数只有cb值
找加密参数,直接启动器断住,刷新图片断住,然后跟栈
跟栈,很轻松就找到了
全扣,直接补环境
window = global
window.addEventListener = function (args) {// console.log('window的addEventListener获取的参数:', args)
}document = {body: {},createElement: function (args) {// console.log('document的createElement获取的参数:', args)if (args == 'div') {return {addEventListener: function (args) {// console.log('document的addEventListener获取的参数:', args)},getAttribute: function (args) {// console.log('document的addEventListener的getAttribute获取的参数:', args)},}}},addEventListener: function (args) {// console.log('document的addEventListener获取的参数:', args)},getElementById: function (args) {// console.log('document的addEventListener获取的参数:', args)},
}
setTimeout = function () {
}
setInterval = function () {
}navigator = {userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36'
}location = {"ancestorOrigins": {},"href": "https://dun.163.com/trial/picture-click","origin": "https://dun.163.com","protocol": "https:","host": "dun.163.com","hostname": "dun.163.com","port": "","pathname": "/trial/picture-click","search": "","hash": ""
}
进入函数内部,直接导出函数
整理一下
params = {"referer": "https://dun.163.com/trial/picture-click","zoneId": "CN31","id": "07e2387ab53a4d6f930b8d9a9be71bdf","https": "true","type": "3","version": "2.28.5","dpr": "1","dev": "1","cb": js.call('get_cb'),"ipv6": "false","runEnv": "10","group": "","scene": "","lang": "zh-CN","sdkVersion": "","loadVersion": "2.5.3","iv": "4","user": "","width": "320","audio": "false","sizeType": "10","smsVersion": "v3","callback": "__JSONP_jg0aa6s_2"
}
response = requests.get(url, headers=headers, params=params)
json_str = re.search("__JSONP_jg0aa6s_2\((.*?)\)", response.text).group(1)
json_obj = json.loads(json_str)
print(json_obj)
id = json_obj['data']['token']
front = json_obj['data']['front']
img_url = json_obj["data"]['bg'][0]
顺利出值
2.验证码识别
这里用的是云码打码平台:aHR0cHM6Ly93d3cuamZieW0uY29tL3ByaWNlLmh0bWw=
参考官方文档封装一下
def click_img(img, front):img_content = requests.get(img).contentwith open('img1.jpg', 'wb') as f:f.write(img_content)url = "http://api.jfbym.com/api/YmServer/customApi"data = {## 关于参数,一般来说有3个;不同类型id可能有不同的参数个数和参数名,找客服获取"token": "你的token","extra": ",".join(front),"type": "300010","image": base64.b64encode(img_content).decode(),}_headers = {"Content-Type": "application/json"}response = requests.request("POST", url, headers=_headers, json=data)return response.json()['data']['data']
成功识别
3.验证接口分析
跟cb值一样跟栈找加密位置
三个参数需要分析
m,p,ext
4.m值
参数分析
把m值单独拎出来
缺什么,补什么
切记,以网页为主,有同名的函数
然后在自己的环境导出
下面缺一个对象,在对象和函数之间优先导出对象
最后整理,差一个_0x119ab0值
数组,每一位都加密。先给结论,对每一个轨迹坐标进行加密
直接搜索traceData
最好是在push打断点
有时会混淆,注意
当你点选第一个位置,一移动就断住
传参第一个值,很明显是验证码接口返回的token值。
接下来另一个参数是长这样子的
先给结论,一个x坐标,一个y坐标,一个时间,一个固定的零。
打上日志断点,验证一下
轨迹生成就出来了
所以结果出来了,需要一个轨迹和一个token,token已经有了,验证码接口返回的token值。
轨迹生成分析(生成轨迹函数)
观察一次成功的轨迹,一次生成一百多个坐标,一次生成七十多次坐标
其实不难看出,当坐标变少时,时间相隔就会变大,初始时间10到100以上不等
而且到这个点,时间间隔暴增,这其实是一个点击点,模拟你点击的时候停顿
给出开源的模拟轨迹代码,可以自己调一下
def get_gj(xy):# xy = xy.split('|')# xy_list = [i.split(',') for i in xy]xy_list = [[int(num1), int(num2)] for num1, num2 in xy]# print(xy_list)tr = []zb = []for i in range(len(xy_list) - 1):s, e = xy_list[i], xy_list[i + 1]if not tr:tr.append([*s, 13])zb.append([*s, 13])np = random.randint(30, 40) # 点到点之间生成多少个坐标点bt = random.randint(15, 20) # 时间差值for j in range(np):p = (j + 1) / (np + 1) # 获取进度比例x = int(s[0] + (e[0] - s[0]) * p)y = int(s[1] + (e[1] - s[1]) * p)tr.append([x, y, tr[-1][2] + bt])tr.append([*e, tr[-1][2] + bt]) # 确保我们的轨迹到重点zb.append(tr[-1]) # 确保我们的轨迹到重点return tr, zb
tr是轨迹,zb是坐标
xy = click_json['data']['data'].split('|')
xy_list = [i.split(',') for i in xy]
arr = get_gj(xy_list)
print(arr[1])
print(arr[0])
轨迹模拟结果
轨迹加密处理
由之前得出,轨迹加密一共传入两个值,token和每一个轨迹坐标
现在自己环境设假值,
这一段整理为
_0x12d10c = window.encrypt(token, [tr_list[i][0], tr_list[i][1], tr_list[i][2], 0] + '')
加密方法直接导出
最后封装
function get_traceData(track, token) {traceData = []for (i = 0; i < track.length; i++) {_0x12d10c = window.encrypt(token, [track[i][0], track[i][1], track[i][2], 0] + '')traceData.push(_0x12d10c)}return traceData
}
输出轨迹
轨迹出来了,上传轨迹进行二次加密,
function get_m(token,track) {_0x119ab0 = get_traceData(track,token)m = window._0x3ebd00(window._0x4facd8 ["sample"](_0x119ab0, 50)["join"](':'))return m
}
m值处理结果出来了
5.P值
其实p值传参就是三个点击坐标加时间戳,进行轨迹加密,然后跟m值一样
直接就在这个值里面
看单词也知道是点击栈
对于的div属性也就是页面的属性标签
三个点
也就猜出就是三个点坐标
换种搜索方式
pointsStack在哪里生成,搜索pointsStack,看push,结果没搜索到
由这里进入解密函数
可以在解密函数的返回值插桩
最后也成功找到混淆参数,一点击就断住,加密方式跟轨迹一样,只不过传参是坐标
function get_p(token,track_point) {_0x119ab0 = get_traceData(track,token)m = window._0x3ebd00(_0x119ab0["join"](':'))return m
}
最终m值也顺利得出
6.ext值
这个值比较简单,传入轨迹长度加3,和token值即可,函数都是已经导出来了
function get_ext(token,len)
{return window._0x3ebd00(window.encrypt(token, 3+ ',' +len))}
总结
封装
function get_data(token,track,track_point) {// a = get_traceData(tr_list, token)// b = get_traceData(point_list, token)l = track.lengthreturn JSON['stringify']({'d': '','m': get_m(token,track),'p': get_p(token,track_point),'ext': get_ext(token,l)})}console.log(get_data(token,track,track_point))
顺利出结果
一共需要python请求环境一共需要换入三个参数,
第一次验证码接口返回token
模拟生成的坐标轨迹,可以在生成轨迹的地方日志断点,观察轨迹怎么生成
ocr识别的坐标
。。。。。。。。。。
加密的参数可以跟栈找,没有异步,轨迹或坐标可以看push关键词
在混淆环境下,关键词搜索可以在解密函数返回参数插桩。
报这个错误,说明你加密方式搞错了或者传参错了
报这个错误,说明轨迹不够逼真
这是成功的返回的
测试成功率:
基本成功率两成上下,可以去调一下轨迹生成函数,模拟更逼真轨迹以便更高概率通过。