某片滑块网址如下:
aHR0cHM6Ly93d3cueXVucGlhbi5jb20vcHJvZHVjdC9jYXB0Y2hh
网址通过base64解密后获得
这里我们以嵌入式滑块为例,大部分滑块基本都是两个接口,一个获取验证码,一个校验验证码,我们打开network,模拟抓包后锁定两个请求
我们将两个接口参数解析之后发现get请求有四个,如下
校验验证码则多一个token
我们先跟栈分析get请求
可以发现,整个链接参数都在这里生成,跟参发现,cb为一个随机数,i和k由加密e数据而来,e则包含了浏览器的一些指纹信息,captchaId为一个固定参数,因此,只要分析cb,i,k参数即可
接下来,跟到cb参数中,将方法扣下来就行
然后先查看e中部分指纹的由来,这里最方便的就是全局搜索一下fingerprint关键词
发现指纹也是由浏览器环境信息生成而来,这里可以扣下整个生成的方法,也可以固定,扣下来大概是这样
然后我们回到i和k生成的地方
发现i是aes加密,i的秘钥和初始化向量也是一个16位的随机数,而k是rsa加密,其中k的公钥也能找到
这里,我们尝试使用js来还原这两种加密,使用crypto和jsencrypt库,简单还原后如下
// aes加密函数
function encrypt(plaintext, key, iv) {
const keyBuffer = Buffer.from(key, 'utf8');
const ivBuffer = Buffer.from(iv, 'utf8');
const cipher = crypto.createCipheriv('aes-128-cbc', keyBuffer, ivBuffer);
let encrypted = cipher.update(plaintext, 'utf8', 'base64');
encrypted += cipher.final('base64');
return encrypted;
}
// rsa加密函数
function encryptRSA(N){
let s = new jsencrypt();
s.setPublicKey('MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDnOWe/gs033L/2/xR3oi6SLAMPBY5VledUqqH6dbCNOdrGX4xW+1x6NUfvmwpHRBA2C7xWDDvOIldTl0rMtERTDy9homrVqEcW6/TY+dSVFL3e2Yg2sVaehHv7FhmATkgfC2FcXt8Wvm99QpKRSrGKpcFYJwOj2F8hJh+rTG0IPQIDAQAB')
const encryptedData = s.encrypt(N)
return encryptedData
}
接着,我们组装成python代码,成功得到请求
get请求就分析完成了,接下来分析verify请求,继续跟栈,发现加密的请求入口是一样的,那么我们只需要找到token参数和还原加密轨迹就行
仔细观察get请求返回的餐户数,token其实在get请求中
然后查看堆栈参数,发现这里的e稍有不同
最关键的就是多了两个参数,distanceX和points,初步分析,distanceX是一个归一化向量,points是坐标轨迹,我们继续往前跟栈分析
找到传参位置,distanceX就是r,r的生成,就是由得到的大背景图的宽度和缺口图的宽度和偏移量进行计算的,经过多测测试,大背景图宽度不变,缺口图宽度可能有一些变化,但是大体上基本不变,所以,这里可以将这两个参数固定住
注意: 小图宽度经试验后,有时是59,有时是60,变化不大,可以固定,因为最后校验的偏移值,实际上在后端校验中,都会有几个像素的浮动值,因为不能保证每次都能移到缺口正中间位置
this.imgWidth = 304;
this.alertImgTagwidth = 59;
distanceX= (this.imgWidth - this.alertImgTagwidth) * (this.offsetX / (this.imgWidth - 42)) / 304;
接下来滑块轨迹,可以继续跟栈,去扣生成的代码,也可以自己模拟生成,这里经过多次断点分析后,发现第一个参数是x的移动距离,第二个参数是y的移动距离,而第三个参数是时间戳的变化,所以,大致模拟过程如下
function reducePoints(offsetX){
points = [[800 , 1979, 5]]
var min = 10;
var max = 30;
for ( var i = 1; i<21;i ++){
x = 800 + (offsetX / 20) * i
randomInt = Math.floor(Math.random() * (41)) + min;
point = [x , points[i - 1][1] + 1, points[i - 1][2] + randomInt]
points.push(point)
}
return points
}
这里初始x,y,时间戳都可以固定,我这里循环了20次,最后一共生成21个点
注意:经本人实验后,生成的轨迹点数太少不会通过,具体多少个没有实验,生成21个基本上没有问题
最后将代码拼凑整合一下,如下
然后,使用python请求发包,这里需要注意个点,从get请求拿到的大图,和网页中的图像大小是不一致的,所以轨迹需要做一个计算,轨迹的计算很简单,偏移量 / 大图宽度 * 网页图宽度 即可
最后成功