ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

极验4滑块协议分析

极验4滑块协议分析 摘要本文以极验4GT4滑块行为验证的官方 demo 为分析对象完整梳理从页面初始化到最终校验的协议流程。文章先介绍 load 初始化接口中 jsonp 回调名、challenge 与 cookie 的生成逻辑再讲解背景图与滑块图的下载、预处理、模板匹配及缺口定位方法最后深入拆解 verify 校验接口中 w 参数与 td 行为数据的生成逻辑涵盖 AES/RSA 加密、PoW 字段处理以及轨迹数据的 gzip 压缩与 Base64 编码流程为理解 GT4 滑块验证的逆向分析提供完整参考。文章大纲本文围绕极验4GT4滑块行为验证的完整协议流程展开从初始化接口到最终校验接口逐步拆解关键参数的生成逻辑。全文结构如下一、介绍 GT4 滑块验证的应用背景、分析目标与学习定位。二、GT4 完整校验流程梳理从 load 初始化到 verify 校验的完整链路。2.1 load 初始化接口分析 jsonp 回调名、challenge 与 cookie 的生成逻辑。2.2 图片处理讲解背景图与滑块图的下载、预处理、模板匹配与缺口定位。2.3 verify 校验接口拆解 w 参数与 td 行为数据的生成逻辑。一.前言极验4的滑块行为验证是目前应用很广的人机验证方案本文以官方demo作为分析站点完整梳理从初始化到最终校验的协议流程定位分析关键参数的生成逻辑仅用于技术学习交流。网址aHR0cHM6Ly9ndDQuZ2VldGVzdC5jb20二.GT4完整校验流程2.1load初始化接口使用Chrome Devtools调试手动触发并进行一次滑动接口返回如下完整流程load页面初始化 -- 返回jsonp -- 加载脚本和样式 -- 下载背景图和滑块图 -- 交互后verify校验其中payload请求参数需要注意有callback和challenge字段其他相对固定。load接口response返回格式不是纯json而是geetest_随机数{}的jsonp格式。核心字段包括lot_number、payload、process_token、payload_protocol、pt、bg、slice、ypos和pow_detail等。lot_number是后续动态字段和td_sign的关联值。需要定位参数生成位置直接搜索关键字段callback找到jsonp回调名的生成位置。进入random()函数里0~9999随机数和当前时间戳直接相加不是字符串拼接。用python类似import random import time def callback_name(now_ms: int | None None) - str: timestamp now_ms if now_ms is not None else int(time.time() * 1000) suffix random.randrange(10000) return fgeetest_{timestamp suffix}再搜challenge定位生成位置直接import uuid challenge str(uuid.uuid4())至于cookie在第一次请求load会返回set-cookie后续请求携带这个cookie即可。2.2图片处理对图片进行处理时先将load请求的response返回的slice和bg拼接成相应的url下载背景图和滑块图。将图片下载到本地后,将背景图读取为灰度图。bg cv2.imread(str(bg_path), cv2.IMREAD_GRAYSCALE)滑块图使用四通道模式读取。piece cv2.imread(str(slice_path), cv2.IMREAD_UNCHANGED)滑块图通常包含B、G、R图像颜色 AAlpha 透明度蒙版Alpha 通道可以区分滑块主体和透明背景因此比单纯比较 RGB 更可靠。验证码背景中的缺口区域通常会增加阴影或低频颜色变化因此先使用高斯模糊提取低频部分再与原图相减bg_hp ( cv2.GaussianBlur(bg, (3, 3), 0).astype(float32) - bg.astype(float32) )滑块图也进行相应处理piece_hp ( cv2.GaussianBlur(piece_gray, (3, 3), 0).astype(float32) - piece_gray.astype(float32) )处理后的结果重点保留边缘、纹理和局部细节削弱大面积颜色渐变造成的影响。滑块边缘通常包含装饰边框、阴影和透明过渡区域。为了减少这些区域对匹配结果的干扰对 Alpha 蒙版进行腐蚀mask cv2.erode( piece[:, :, 3], None, iterations9, )腐蚀后留下的是滑块内部较稳定的纹理区域。之后只使用这部分区域参与模板匹配。使用 OpenCV 的归一化相关系数方法进行模板匹配result cv2.matchTemplate( bg_hp, piece_hp, cv2.TM_CCOEFF_NORMED, maskmask, )result是一个二维矩阵result[y][x] 滑块模板放在背景坐标 (x, y) 时的匹配分数。模板在背景上逐点移动每个位置都会得到一个分数。分数越高表示滑块纹理与该位置越相似。load响应中还会返回ypos。它表示滑块缺口大致所在的垂直位置因此不需要扫描整张背景图。代码将搜索区域限制在ypos - 6 ≤ y ypos 7对应实现lo max(0, int(ypos) - 6) hi min(result.shape[0], int(ypos) 7) band result[lo:hi] _, score, _, local cv2.minMaxLoc(band) location ( local[0], local[1] lo, )最终得到gap_x, gap_y, score这里得到的gap_x还是原始图片坐标不一定等于浏览器滑块控件需要的移动距离。后续会根据客户端缩放比例进行换算set_left int((gap_x - 2) * scale) userresponse set_left / scale 2之后这些字段才会参与明文 JSON 组装和w加密。图片处理阶段只负责回答缺口在原始背景图的什么位置滑动距离、显示缩放和客户端字段则在后续参数组装阶段处理。2.3.verify校验接口2.3.1.w参数生成逻辑verify接口需要还原w和td。首先通过initiator调用堆栈找到对应文件关键词搜索参数process_token,定位到参数的赋值位置。w的值是c找c的生成位置加密函数为i跟入函数内部假设让table _ᖈᕴᖙᕶ.$_Dl() , 最开始state table[6][19] , 与第一个case: table[3][19]判断为true因此进入第一个case其中的if判断的是pt的值第一个case将Config赋值给n然后修改state。第二次循环新的state与第二个case匹配进入第二个case这是主加密分支。首先是一些赋值操作第一个是s跟入函数主要看e()继续跟入e(), 大致是return (65536 * (1 Math[random]()) | 0) [toString](16) [substring](1);生成一个随机数×65536再转成不带0x的十六进制串再去掉首位字符最后是4位十六进制字符s得到的就是16个十六进制字符这个s是后面AES加密的key。继续分析这里有个r函数r的作用就是给当前实例写入$_BJH属性保存传入的数组最后得到的就是个含有数组属性的对象。继续往后看1和2两条分支这个r会通过pt的值来判断分支这里只分析1先看symmetrical跟入函数后查看是标准AES加密再看asymmetric跟入其构造函数是个标准RSA加密这里是初始化 RSA 密钥对象并配置公钥往下通过pt判断先调用asymmetric.encrypt(s)s是前面随机生成的 16 位十六进制字符key返回RSA密文u然后判断u的长度是否为256个十六进制字符也就是128字节直到生成符合要求的RSA 输出。然后调用symmetrical.encrypt(plaintext, s)进行AES加密返回数组c。这里的plaintext是一个 JSON 字符串图片处理后由滑块定位得到的setLeft、passtime、userresponse 等行为参数以及 /load 响应中的lot_number、PoW 字段和其他协议字段共同组成。 PoW 字段pow_sign与pow_msg需要处理load响应中的pow_detail通过找堆栈定位到跟入函数pow_msg: version|bits|hashfunc|datetime|captcha_id|lot_number| device_id|随机16个十六进制字符,device_id这里是“ ”。pow_sign: SHA-256(pow_msg 的 UTF-8 字节).hex()最后将AES加密后的数组c经过下面的函数进行处理后与RSA密文u作拼接就是最后的w参数。2.3.2.td行为数据生成根据堆栈找生成位置定位到这里已经生成了完整的url继续往上找堆栈直到这查看作用域可以看到含有td的对象是在u的闭包。进入u的堆栈到这还不是生成位置但可以看到这个 _ 有td,在附近找 _ 的td是在这里赋值也就是_ᕺᕶᕹᕸ接着往上找_ᕺᕶᕹᕸ在这里生成跟入函数是把第一个参数的new_track属性给了n然后删掉new_track最后返回值是n同时第一个参数对象添加了一个td_sign所以呢new_track的值就是td因此需要找new_track是哪里生成的。函数u的堆栈内查看作用域u的第一个参数携带new_track同时u函数在$_BCEA的闭包作用域断到$_BCEA后发现u的第一个参数已经有new_track值再往上找堆栈。到这里可以看到有个对象的赋值操作有三个值setLeft, passtime,userresponse没有new_trackreturn中的这个函数里这个对象作为了参数传入所以跟入函数这里就是new_track的实际生成位置接收值的是i所以继续跟入i的生成函数跟入后传入参数是一个轨迹对象往后看o()返回的是一个压缩/编码工具对象strToU8字符串转 UTF-8 字节gzipSync对字节进行 gzip 压缩最后的返回值 JSON.stringify(轨迹对象)→ UTF-8 字节→ gzip 压缩→ URL-safe Base64 编码→ 去掉末尾填充 → new_track至于这个函数是一个字节数组编码函数Base64 编码器。最后补齐verify请求携带的参数后:免责声明本文内容仅用于技术学习与交流旨在帮助读者理解 GT4 滑块验证的协议流程与参数生成逻辑。文中涉及的代码、接口分析与逆向思路仅供学习研究使用请勿用于任何违反法律法规、平台服务条款或侵犯他人合法权益的场景。请读者遵守相关法律法规与平台规则合理合法地使用技术知识。
返回列表