某企查-某度旋转验证码V2算法分析
声明:本案例中所有内容仅供个人学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!
1.流程分析
所有接口都会用到cookie,msg为请求头Referer的值这里必须设置,1-4需要设置,不然第五步会报错
{'code': 1, 'msg': 'url is invalid', 'data': {'f': {'feedback': 'wappass.baidu.com/static/acti...
scss
1.某企查翻页触发验证码,会返回msg,ak 后续会用到
2./cap/init 验证码初始化 tk(style接口用到),as(log接口生成newkey会用到),ds(log接口用到)
3./cap/style 获取图片验证码接口 path为验证码图片,backstrs(后续生成fs参数用用到、首次滑动c接口不需要refresh参数,失败再次滑动需传refresh值为backstrs)
4./cap/log 验证接口 fuid和fs为关键参数,ak、as、tk为上面接口返回,响应返回as、ds、tk,op为1为成功,3为失败
5./cap/c 认证接口 携带log接口返回的 tk、ds以及refer也就是一开始的msg,成功响应返回一个url
6.访问/cap/c响应的内容的url,这个地址与msg相关联,请求返回的url会设置cookie-> __jdg_yd(某企查的是这个,其他项目就不知道了)
2.参数fuid生成
直接搜索fuid可以找到,这个fingerprint.js 文件主要是收集一些指纹相关,可以写死,也可以找一些canvas指纹进行随机,将收集的指纹转为json字符串进入U函数进行加密

进入U之后可以看到秘钥直接写出来了,我们只需要看一下是不是标准的AES
可以看到与标准算法一致,那么这个参数就解决了

3.参数fs生成
入口搜n.fs就可以找到,但是不能直接下段,这个绑定了鼠标事件,要不然无法断到我们旋转后再断的时机,我们需要先搜索ac_c,这个也就是旋转角度,在这里下断点,断住之后再放行断到n.fs这个才是真正发包加密的地方,t.data也就是旋转角度 / 360

n.fs成功断住,发现n.fs经过了两次生成,第一次将this.rzData进行加密,第二次将第一次生成的在进行一次加密而且两次加密的入口都是u.Li函数,先看下this.rzData是什么,比较关键的的ac_c旋转角度 backstr为style接口返回 ,以及两个mv,common的mv只是记录,写不写都行,captchalist的mv为轨迹校验,每次只有3-5个也不怎么校验,随机一下就可以,acc = 旋转角度 / 360 距离 = acc * 290 290为总长,根据距离伪造mv理论上就没问题。
yaml
{
"common": {
"cl": [],
"mv": [],
"sc": [],
"kb": [],
"sb": [],
"sd": [],
"sm": [],
"cr": {
"screenTop": 0,
"screenLeft": 0,
"clientWidth": 2560,
"clientHeight": 937,
"screenWidth": 2560,
"screenHeight": 1080,
"availWidth": 2560,
"availHeight": 1040,
"outerWidth": 2560,
"outerHeight": 1040,
"scrollWidth": 2560,
"scrollHeight": 2560
},
"simu": 0
},
"backstr": "xxxxxxxx",
"captchalist": {
"spin-0": {
"mv": [],
"ac_c": 0.71,
"p": {
"t": 5,
"an": 780
},
"cr": {
"left": 1135,
"top": 308,
"width": 290,
"height": 280
},
"back": {
"left": 1204,
"top": 352,
"width": 152,
"height": 152
}
}
}
}

进入Li函数根据第二个参数去取key以及所用模式,多次刷新模式是固定的,这里的key生成是通过getNewKey函数传入as参数,也就是init接口返回的,看一下如何生成key的

这里是根据as加一个固定字符串appsapi2相加,r为as的最后一位,然后根据r进入对应分支,对e进行对应方法的sha和md5运算,最后返回前16为作为aes的key,这里的方法经过测试均为标准算法

4.模型识别
这里验证码识别用到了大佬开源的模型,时间比较久了,左为现在干扰的右边为之前的,图片加干扰,所以识别不理想但是勉强能用。
bash
https://github.com/HarderThenHarder/rotate_image_classifier
逻辑比较简单,算法也是标准的,用python实现就好,也是成功拿到了cookie,使用生成的也是成功拿到数据。