某红书旋转滑块验证码分析与协议算法实现(高通过率)

devtools/2024/11/15 2:02:13/

文章目录

  • 1. 写在前面
  • 2. 接口分析
  • 3. 验证轨迹
  • 4. 算法还原

【🏠作者主页】:吴秋霖
【💼作者介绍】:擅长爬虫与JS加密逆向分析!Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Python与爬虫领域研究与开发工作!
【🌟作者推荐】:对爬虫领域以及JS逆向分析感兴趣的朋友可以关注《爬虫JS逆向实战》《深耕爬虫领域》
未来作者会持续更新所用到、学到、看到的技术知识!包括但不限于:各类验证码突防、爬虫APP与JS逆向分析、RPA自动化、分布式爬虫、Python领域等相关文章

作者声明:文章仅供学习交流与参考!严禁用于任何商业与非法用途!否则由此产生的一切后果均与作者无关!如有侵权,请联系作者本人进行删除!

1. 写在前面

  作者在使用红薯的时候,经常会选择通过手机验证的方式去登录。但是,天公不作美!我甚至有时候第一次登录,就给我弹出一个验证码…有风控固然是好的,但是略微的影响到了用户的交互体验,一般用户只能选择是手动拖动滑块进行验证…

在这里插入图片描述

但是!作为一名科技行业的程序员。肯定是不会屈服的,于是带着对技术的好奇心在想过这个旋转的验证码,是否可以自动化呢?当然自动化没有挑战!作者选择通过协议+算法的方式去通过这个验证码

2. 接口分析

这里我们浅拉一下旋转的滑块,然后监测register这个接口的发包,如下所示:

在这里插入图片描述

这几个参数中verifyUuid是重要的,它在每一次生成弹出验证码的时候,给出的一个新且唯一的验证ID,在后续的验证接口同样需要携带!获取方式如下所示:

在这里插入图片描述

在输入手机号点击发送短信验证码的时候,假设失败被风控了。短信接口会正常给到你成功的响应,如下所示:

{"code":0,"success":true,"msg":"成功","data":{}}

但是如果你光通过接口去检验,是不知道出验证的。得看请求状态,失败出现验证码则是471,这个时候再去头部分析,拿到验证码UID

通过register的接口,获取到验证码提交所需要的ridcaptchaInfo字段信息

请求同样是需要头部带X-s、X-s-common参数的

第二个我们需要分析的接口则是check,这个是提交验证检测的。如下所示:

在这里插入图片描述

可以看到提交的参数中captchaInfo是最重要的,通过字段信息能够看到提交的鼠标轨迹相关的一些东西,而且看这样子应该还是加密的!另外的rid、uid在前面环节都能够获取到,checkCount参数则是验证次数,通不过就会自增

3. 验证轨迹

接下来如果没有解决头部X系列的两个参数加密,建议先去研究这个两个参数,再来研究滑块!当然如果你不知道怎么还原可以去看作者以前的文章!现在开始还原captchaInfo这个参数

JS调试发现轨迹验证参数的值采用了DES加密,可以拿浏览器内的加密轨迹来解密看看,如下所示:

在这里插入图片描述

轨迹分析后开始实现算法,如下所示:

function generate_Track(slideDistance) {var trackList = [];var x = 0;while (x < slideDistance) {x += 2;var y = -(Math.floor(x / 10));var z = 2 * (x - 1) + Math.floor(Math.random() * 7) + 1;trackList.push([x, y, z]);}return JSON.stringify(trackList);
}
function get_mousetrack(distance,time){var mousetrack1=get_trace(distance,time);var mousetrack2=generate_Track(distance);return DES_Encrypt(mousetrack2,"PYrm8rMk")
}
function get_trace(distance,time) {distance = Math.floor(distance);var trace = [];var sy = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0];var st = [15, 16, 17, 18, 15, 16, 17, 18, 15, 16, 17, 18, 15, 16, 17, 18, 15, 16, 17, 18, 15, 16, 17, 18, 15, 16, 17,18, 15, 16, 17, 18, 15, 16, 17, 18, 15, 16, 17, 18, 14, 16, 17, 18, 16, 17, 18, 19, 20, 17];if (distance < 95) {var sx = [1, 2, 1, 2, 1, 2, 1, 1, 2, 1];}else{var sx = [1, 2, 1, 2, 1, 2, 2, 2, 3, 4];}var zt = RandomNum(10, 100);var zx = 0,zy = 0;var random_x = RandomNum(9, 14);var n = 0, x = 0, y = 0, t = 0;while (true){n += 1;if (n < 5){x = 1;}else{x = RandomChoice(sx)}if (distance > 125 && random_x === n){x = RandomNum(14, 18)}y = RandomChoice(sy);t = RandomChoice(st);zx += x;zy += y;zt += t;trace.push([zx, zy, zt]);if (distance - zx < 6){break;}}var value = distance - zx;for (var i = 0; i < value; i++){t = RandomChoice(st);if (value === i + 1){t = RandomNum(42, 56)}if (value === i + 2){t = RandomNum(32, 38)}if (value === i + 3){t = RandomNum(30, 36)}x = 1;zx += x;zt += t;trace.push([zx, zy, zt]);}let csz=RandomNum(1, 10)let elementToInsert0 = [0, 0, csz];let elementToInsert1 = [0, 0, csz+2];trace.unshift(elementToInsert1);trace.unshift(elementToInsert0);return JSON.stringify(trace);
}

4. 算法还原

首先需要封装register接口的协议请求,核心请求提交封参如下所示:

json_data = {"secretId": "000","verifyType": "102","verifyUuid": v_id,"verifyBiz": "471","sourceSite": "","captchaVersion": "1.1.0"
}
jmurl='url=/api/redcaptcha/v2/captcha/register'+json.dumps(json_data).replace(" ","")a1=ck['a1']
xts = self.ctx.call('get_x_s',jmurl,a1)
xtscommon = self.ctx.call('get_x_s_common',xts,a1)
self.headers['x-s'] = xts['X-s']
self.headers['x-s-common']=xtscommon
self.headers['x-t']=str(xts['X-t'])data=json.dumps(json_data,separators=(',',':'))
response = requests.post(url, headers=self.headers, cookies=ck, data=data)

check验证接口的提交核心封参请求如下所示:

chainfo={"mouseEnd":self.ctx.call('DES_Encrypt',mouseend,"WquqhEkd"),"time":self.ctx.call('DES_Encrypt',time,"vPMvCY4K"),"track":self.ctx.call('get_mousetrack',mouseend,time),"width":self.ctx.call('DES_Encrypt',width,"WquqhEkd")}json_data={"rid":rid,"verifyType":"102","verifyBiz":"471","verifyUuid":v_id,"sourceSite":"","captchaVersion":"1.1.0","checkCount":str(check_count),"captchaInfo":json.dumps(chainfo)}

当然,请求完成后的过程中我们还需要对旋转图片角度的分析与图像处理(包括裁剪)!主要就是通过对两个图像进行分析处理来找出最佳的角度。使得合并后的图像在梯度上的差异最小,这里我们采用了CV2,通过核心Py。源码如下所示:

def perform_angle_analysis(self,query_image_path, background_image_path):def calculate_gradient_difference(image, cx, cy, circle_radius):circle_inner_mask = np.zeros_like(image, dtype=np.uint8)cv2.circle(circle_inner_mask, (cx, cy), circle_radius, 255, -1)circle_outer_mask = np.zeros_like(image, dtype=np.uint8)cv2.circle(circle_outer_mask, (cx, cy), circle_radius + 30, 255, -1)inner_pixels = cv2.bitwise_and(image, circle_inner_mask)outer_pixels = cv2.bitwise_and(image, circle_outer_mask)inner_sobel_x = cv2.Sobel(inner_pixels, cv2.CV_64F, 1, 0)inner_sobel_y = cv2.Sobel(inner_pixels, cv2.CV_64F, 0, 1)inner_gradient_magnitude = cv2.magnitude(inner_sobel_x, inner_sobel_y)outer_sobel_x = cv2.Sobel(outer_pixels, cv2.CV_64F, 1, 0)outer_sobel_y = cv2.Sobel(outer_pixels, cv2.CV_64F, 0, 1)outer_gradient_magnitude = cv2.magnitude(outer_sobel_x, outer_sobel_y)gradient_diff = np.sum(outer_gradient_magnitude) - np.sum(inner_gradient_magnitude)return gradient_diffdef merge_images(query_result, bg_image, radius, angle):query_height, query_width = query_result.shape[:2]rotation_matrix = cv2.getRotationMatrix2D((query_width / 2, query_height / 2), angle, 1)rotated_result = cv2.warpAffine(query_result, rotation_matrix, (query_width, query_height))center = (bg_image.shape[1] // 2, bg_image.shape[0] // 2)cv2.circle(bg_image, center, radius, (0, 0, 0), -1)bg_height, bg_width = bg_image.shape[:2]circle_height, circle_width = rotated_result.shape[:2]x = (bg_width - circle_width) // 2y = (bg_height - circle_height) // 2overlay = np.zeros_like(bg_image)overlay[y:y + circle_height, x:x + circle_width] = rotated_resultresult = cv2.bitwise_or(bg_image, overlay)return resultdef split_circular_region(image, radius):height, width, _ = image.shapecenter = (width // 2, height // 2)mask = np.zeros_like(image)cv2.circle(mask, center, radius, (255, 255, 255), -1)result = cv2.bitwise_and(image, mask)return resultdef enlarge_image(image, scale_factor):circle_height, circle_width = image.shape[:2]new_height = int(circle_height * scale_factor)new_width = int(circle_width * scale_factor)result = cv2.resize(image, (new_width, new_height), interpolation=cv2.INTER_LINEAR)return resultquery_image = cv2.imread(query_image_path)bg_image = cv2.imread(background_image_path)query_result = split_circular_region(query_image, 89)query_result = enlarge_image(query_result, 1.1)min_difference = float('inf')min_angle = 0for angle in range(0, 360, 5):result = merge_images(query_result, bg_image, 89, angle)gradient_difference = calculate_gradient_difference(result, bg_image.shape[1] // 2, bg_image.shape[0] // 2, 70)if gradient_difference < min_difference:min_difference = gradient_differencemin_angle = angleresult = merge_images(query_result, bg_image, 89, min_angle)cv2.imwrite('./jpg/result.png', result)return min_angle

在这里插入图片描述

最后完成所有的编码后,把滑块验证部署成一个API服务,这样的话更加方便调用,如下:

在这里插入图片描述

本地直接通过检测471验证码,拿到uid、cookie调用纯协议滑块验证服务,效果如下:

在这里插入图片描述


http://www.ppmy.cn/devtools/45935.html

相关文章

Love-Yi情侣网站3.0存在SQL注入漏洞

目录 1. 前言 2. 网站简介 3. 寻找特征点 3.1 第一次尝试 3.2 第二次尝试 4.资产搜索 5.漏洞复现 5.1 寻找漏洞点 5.2 进行进一步测试 5.2.1 手动测试 1.寻找字段 2.寻找回显位 3.查询当前用户 5.2.2 sqlmap去跑 6.总结 1. 前言 朋友说自己建了一个情侣网站,看到…

python替换“${}“占位符为变量,实现读取配置文件

文章目录 背景1、定义正则表达式2、替换变量占位符3、实现功能 背景 使用python编写小工具&#xff0c;有一个配置文件&#xff0c;希望实现类似shell命令的&#xff0c;定义变量并且使用${}或者$来引用。如果有好的建议欢迎讨论。 配置文件示例内容如下: D:\project\test\pr…

【Java面试】九、微服务篇SpringCloud(上)

文章目录 1、SpringCloud五大组件2、服务注册和发现2.1 Eurake2.2 Eurake和Nacos的区别 3、Ribbon负载均衡3.1 策略3.2 自定义负载均衡策略 4、服务雪崩与熔断降级4.1 服务雪崩4.2 服务降级4.3 服务熔断 5、微服务监控6、面试 1、SpringCloud五大组件 通常情况下&#xff1a; …

Windows API 速查

Windows API 函数大全 (推荐)&#xff1a;https://blog.csdn.net/xiao_yi_xiao/article/details/121604742Windows API 在线参考手册&#xff1a;http://www.office-cn.net/t/api/index.html?web.htmWindows 开发文档 (官方)&#xff1a;https://learn.microsoft.com/zh-cn/wi…

内网渗透-隧道搭建ssp隧道代理工具frp内网穿透

内网渗透-隧道搭建&ssp隧道代理工具&frp内网穿透 目录 内网渗透-隧道搭建&ssp隧道代理工具&frp内网穿透spp隧道代理工具spp工作原理图cs上线主机spp代理通信服务端配置客户端配置CS配置设置CS生成木马的监听器配置CS监听上线的监听器生成木马 spp隧道搭建服务端…

【C++】6-6 你好,输出的格式控制(对齐)

6-6 你好&#xff0c;输出的格式控制&#xff08;对齐&#xff09; 分数 10 全屏浏览 切换布局 作者 向训文 单位 惠州学院 完善程序&#xff1a;按示例格式输出所有分数&#xff0c;分数保留2位小数&#xff0c;分数左对齐输出在两根竖线之间 裁判测试程序样例&#xff1…

#php的pecl工具#

pecl&#xff08;php拓展社区库&#xff0c;pear拓展版本&#xff09;是一个官方的php扩展仓库&#xff0c;提供了众多优秀的php扩展供开发人员使用,作用主要是给php安装php扩展 1:安装PECL 首先&#xff0c;需要确保已安装PHP和PECL。PECL通常随着PHP一起安装&#xff0c;但…

【Qt知识】Qt窗口坐标系

Qt的窗口坐标体系遵循标准的计算机图形坐标系统规则 Qt窗口坐标体系特点 坐标原点&#xff1a;窗口坐标体系的原点位于窗口的左上角&#xff0c;即坐标(0, 0)位置。 轴方向&#xff1a; X轴&#xff1a;向右为正方向&#xff0c;随着X坐标值的增加&#xff0c;元素在窗口中从…