某红书旋转滑块验证码分析与协议算法实现(高通过率)
文章目录
- 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的接口,获取到验证码提交所需要的rid跟captchaInfo字段信息
请求同样是需要头部带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调用纯协议滑块验证服务,效果如下:
相关文章:

某红书旋转滑块验证码分析与协议算法实现(高通过率)
文章目录 1. 写在前面2. 接口分析3. 验证轨迹4. 算法还原 【🏠作者主页】:吴秋霖 【💼作者介绍】:擅长爬虫与JS加密逆向分析!Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致…...

Gin的快速入门和搭建
文章目录 Go的工程工程架构技术选型 Gin入门 Go的工程 基于Go生态,构建一个支持内容管理,内容加工、内容分发的内容库系统。 内容管理:增删改查内容加工:例如内容审核、推荐等内容分发:将内容可以推到不同的业务线 …...

react-native运行程序 出现 Application XXX is waiting for the debugger
1.重启adb: adb kill-server、 adb start-server. 2、确定USB调试模式是否开启,如果已经开启了,关闭了重新打开一下 3.选择调试模式并关闭等待调试程序...

什么文档加密软件好用?迅软DSE加密软件你不会还不知道吧?
一、什么文档加密软件好用? 其中有迅软DSE文档加密软件等。 迅软DSE加密软件:让企业的创意成果、招投标文件、生产工艺、流程配方、研发成果、公司计划、员工信息等核心数据更安全。 多方面加密模式,有效防止数据泄密 透明无感知加密&…...

【kubernetes】关于k8s集群的污点、容忍、驱逐以及k8s集群故障排查思路
目录 一、污点(Taint) 1.1污点介绍 1.2污点的组成格式 1.3当前 taint effect 支持如下三个选项: 1.4污点的增删改查 1.4.1验证污点的作用——NoExecute 1.4.2验证污点的作用——NoSchedule 1.4.3 验证污点的作用——PreferNoSchedule 1.5污点的配置与管理…...

linux进程加载和启动过程分析
我们的源代码通过预处理,编译,汇编,链接后形成可执行文件,那么当我们在终端敲下指令$ ./a.out argv1 argv2 后,操作系统是怎么将我们的可执行文件加载并运行的呢? 首先知道,计算机的操作系统的启动程序是写死在硬件上的,每次计算机上电时,都将自动加载启动程序,之后…...

WLAN组网模型探究
目录 一、WLAN基本概念二、WLAN组网方式三、WLAN转发模型 随着信息技术的飞速发展,无线局域网(WLAN)已逐渐成为企业网络架构中不可或缺的一部分。不同的企业组织因其业务特性、规模大小及安全需求的不同,对WLAN的要求也各有侧重。…...

操作系统基础知识
一. 进程 进程是正在运行中的程序,是动态的 进程是资源分配的最小单位 进程的基本特征:动态性,并发性,独立性,异步性 二. 线程 线程在执行过程中的每一个任务就是一个线程 进程是由一个或多个线程组成࿰…...

Kompas AI:智能生活的开启者
引言 在现代社会,**人工智能(AI)**已经深刻地影响了我们的生活和工作。无论是智能家居、自动驾驶,还是医疗诊断,AI的应用无处不在。而在众多AI平台中,Kompas AI 作为一个先进的对话式AI平台,通过…...

Java——二进制原码、反码和补码
一、简要介绍 原码、反码和补码只是三种二进制不同的表示形式,每个二进制数都有这三个形式。 1、原码 原码是将一个数的符号位和数值位分别表示的方法。 最高位为符号位,0表示正,1表示负,其余位表示数值的绝对值。 例如&…...

git使用流程
1.下载git 搜索下载 2.注册github账号(打开爬墙工具) 创建一个仓库 3.配置邮箱和密码 4.所以找一个文件夹 鼠标右键 选择 open Git Bash here(当前文件夹下打开命令行) 输入命令 配置用户名和邮箱 5.将建的仓库克隆下来 …...

C++设计模式|结构型 代理模式
1.什么是代理模式? 代理模式Proxy Pattern是一种结构型设计模式,用于控制对其他对象的访问。 在代理模式中,允许一个对象(代理)充当另一个对象(真实对象)的接口,以控制对这个对象的…...

C语言 带头双向循环链表的基本操作
带头双向循环链表的基本操作 结构体定义初始化创建新节点头插头删尾插尾删查找在指定位置之后插入删除指定位置的值打印 结构体定义 typedef int DataType; typedef struct LinkNode {DataType data;struct LinkNode* prev;struct LinkNode* next; }LNode;初始化 有两种初始化…...
MATLAB中扩展卡尔曼滤波误差估计的关键点
在MATLAB中,对于扩展卡尔曼滤波(EKF)的误差估计,主要涉及对系统状态估计的准确性和精度的评估。EKF是一种适用于非线性系统的状态估计方法,它通过递归的方式,结合系统的动态模型和观测模型,来预…...
SpringBoot温习
1.1 Spring Boot Spring Boot是一个开源的Java框架,由Pivotal团队(现在是VMware的一部分)开发,它是Spring框架的一个模块,旨在简化Spring应用程序的初始搭建以及开发过程。 Spring Boot的核心目标是让开发者尽可能…...

Spring Cloud:构建高可用分布式系统的利器
摘要:本文将介绍Spring Cloud,一个基于Spring Boot的开源微服务架构工具集。我们将探讨Spring Cloud的核心组件、特性以及如何使用Spring Cloud构建高可用、分布式系统。通过本文,读者将了解到Spring Cloud在实现微服务架构中的应用和优势。 …...

IT技术 | 电脑蓝屏修复记录DRIVER_IRQL_NOT_LESS_OR_EQUAL
我的台式机是iMac 2015年的,硬盘是机械的,时间久了运行越来越慢。后来对苹果系统失去了兴趣,想换回windows,且想换固态硬盘,就使用winToGo 搞了双系统,在USB外接移动固态硬盘上安装了win10系统。 最近&…...

windows 下编译 TessRact+leptonica 识别图片文字
目录 1、下载 2. 编译基础依赖库 1.1 zlib 1.2 jpegsr9f 1.3 lpng1643 1.4 libgif 3. 编译tifflib 4. 配置nasm到系统环境中 5. 编译 libjpeg-turbo 6 编译leptonica 7. 编译tesseract 8. 测试验证 1、下载 下载tesseract5.3.2 下载leptonica1.83.1 下载l…...
如何把docker里的内容拷贝出来
如何把docker里的内容拷贝出来 要从Docker容器中复制文件或目录出来,可以使用docker cp命令。以下是基本的命令格式和示例: 命令格式: docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH示例: 假设你有一个名为my_container的…...

OpenAI开始训练新的前沿模型——但GPT-5至少在90天内不会推出
ChatGPT 制造商 OpenAI 今早宣布,已开始训练其新的“前沿模型”,并成立了一个新的安全委员会,由现任董事会成员 Bret Taylor(OpenAI 董事会主席兼客户服务初创公司 Sierra AI 联合创始人、前谷歌地图负责人和前 Facebook 首席技术…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...

C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...

基于SpringBoot在线拍卖系统的设计和实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...