【JS逆向实战】极验三代滑块验证码w参数全链路生成与轨迹模拟

张开发
2026/5/31 12:55:55 15 分钟阅读
【JS逆向实战】极验三代滑块验证码w参数全链路生成与轨迹模拟
1. 极验三代滑块验证码核心机制解析第一次接触极验滑块验证码时我盯着那个小小的拼图块足足研究了三天。这种验证码之所以难破解关键在于它采用了三层动态加密体系每个环节都设置了精密的校验机制。让我们先拆解它的核心工作原理极验三代验证码的核心是三个动态生成的w参数w1/w2/w3它们分别在验证流程的不同阶段发挥作用。w1出现在首次get.php请求中主要验证基础环境w2用于ajax.php的初始校验包含设备指纹信息w3则是最终滑动验证时提交的关键参数集成了轨迹数据、时间特征等多维信息。最精妙的是这三个参数之间存在链式依赖关系。比如w2生成时需要用到w1阶段的16位随机字符串w3又依赖w2生成的rp值。这种设计使得单独破解某个参数毫无意义必须完整掌握整个生成链路。2. w1参数生成全解析2.1 初始请求与关键参数捕获当我们首次访问验证页面时会收到两个关键参数gt网站标识和challenge动态挑战码。这两个值将贯穿整个验证流程。通过Chrome开发者工具可以看到初始请求的响应中包含了这两个重要参数// 示例响应数据 { gt: 019924a82c70bb123aae90d483087f94, challenge: 1e3d427363669cb56d3741eee8c8534d }2.2 w1的加密链路拆解w1的生成公式为w i r其中r值是通过MD5加密生成的。具体实现时我们需要先准备一个16位随机字符串作为盐值import random import hashlib def generate_random_str(length16): return .join(random.choice(abcdefghijklmnopqrstuvwxyz0123456789) for _ in range(length)) random_str generate_random_str() # 示例a1b2c3d4e5f6g7h8接下来是r值的生成过程核心代码实现如下def generate_r_value(gt, challenge, random_str): # 构造待加密对象 encrypt_obj { gt: gt, challenge: challenge, lang: zh-cn, pt: 0, client_type: web } # JSON序列化后加密 json_str json.dumps(encrypt_obj, separators(,, :)) encrypted hashlib.md5((json_str random_str).encode()).hexdigest() return encrypted2.3 i值的AES加密实现i值的生成使用了AES加密算法这里有个关键点需要注意极验使用了特殊的IV向量初始向量。通过逆向分析发现它的IV实际上是16个0组成的字节数组from Crypto.Cipher import AES from Crypto.Util.Padding import pad def generate_i_value(gt, challenge, random_str): # 准备加密数据 data { gt: gt, challenge: challenge, time: int(time.time() * 1000) } # AES-CBC模式加密 cipher AES.new( keyrandom_str.encode(), modeAES.MODE_CBC, ivbytes([0]*16) # 关键IV设置 ) encrypted cipher.encrypt(pad(json.dumps(data).encode(), AES.block_size)) return encrypted.hex()最终组合成完整的w1参数w1 i_value r_value。在实际测试中发现如果i值和r值的生成顺序或格式有误服务端会直接返回403禁止访问状态。3. w2参数逆向工程3.1 关键rp参数的生成逻辑w2的核心在于rp值的计算这个参数实际上是gt、challenge和passtime三个值的MD5哈希。这里有个细节需要注意passtime虽然看起来是固定值但必须与后续w3阶段的滑动时间保持一致。def generate_rp(gt, challenge, passtime): plaintext gt challenge str(passtime) return hashlib.md5(plaintext.encode()).hexdigest()3.2 w2的完整加密流程w2的生成比w1更复杂它采用了RSA加密算法。通过逆向分析发现极验使用了一个固定的公钥进行加密。以下是Python实现代码from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_v1_5 def generate_w2(gt, challenge, passtime, random_str): # 生成rp值 rp generate_rp(gt, challenge, passtime) # 构造待加密对象 encrypt_data { rp: rp, passtime: passtime, userresponse: , ep: } # 加载极验固定公钥 public_key -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDC7...完整公钥省略 -----END PUBLIC KEY----- # RSA加密 rsa_key RSA.import_key(public_key) cipher PKCS1_v1_5.new(rsa_key) encrypted cipher.encrypt(json.dumps(encrypt_data).encode()) return encrypted.hex()在实际测试中如果passtime与后续滑动时间不匹配或者rp值计算错误服务端会返回forbidden错误。这也是极验防御体系中的重要校验点。4. w3参数与轨迹模拟4.1 滑动轨迹生成算法w3参数最复杂的部分是滑动轨迹的生成和加密。极验会检测轨迹的多个特征移动加速度曲线停留点分布整体耗时偏移量模式经过多次测试我总结出一个比较可靠的轨迹生成算法import math def ease_out_quad(x): return 1 - (1 - x) * (1 - x) def generate_track(distance): track [] current 0 mid distance * 0.8 t 0 # 初始加速阶段 while current mid: step random.randint(3, 7) current step t random.randint(10, 20) track.append([current, 0, t]) # 减速阶段 while current distance: step int(ease_out_quad((current - mid)/(distance - mid)) * 10) step max(1, step) current step t random.randint(20, 30) track.append([current, 0, t]) # 微调阶段 overshoot current - distance if overshoot 0: t random.randint(50, 100) track.append([distance, 0, t]) return track, t4.2 userresponse算法实现userresponse是验证滑动距离的关键参数它的计算涉及challenge值的特殊处理def calculate_userresponse(distance, challenge): # 提取challenge最后两位 suffix challenge[-2:] base 36 * (ord(suffix[0]) - (87 if ord(suffix[0]) 57 else 48)) base (ord(suffix[1]) - (87 if ord(suffix[1]) 57 else 48)) # 计算响应值 encrypted distance base # 省略后续加密步骤... return str(encrypted)4.3 w3的完整生成流程综合所有要素w3的生成代码如下def generate_w3(gt, challenge, random_str, distance, passtime, track, c, s): # 生成u值与w1类似 u aes_encrypt(random_str, random_str) # 准备o参数 rp generate_rp(gt, challenge[:32], passtime) userresponse calculate_userresponse(distance, challenge) ep generate_ep_params() o_data { passtime: passtime, aa: encrypt_track(track, c, s), ep: ep, rp: rp, userresponse: userresponse } # 加密o参数 o_encrypted special_encrypt(json.dumps(o_data), random_str) # 生成h值 h custom_hash(o_encrypted) return h u在实际应用中我发现极验对时间参数特别敏感。passtime必须与轨迹中的总时间完全一致误差超过50ms就会导致验证失败。5. 验证码图片还原技术5.1 乱序图片重组算法极验的滑块验证码图片采用了分块乱序技术通过分析前端代码可以找到还原算法from PIL import Image def restore_image(disorder_img_path): img Image.open(disorder_img_path) width, height img.size # 极验三代的标准乱序表 disorder_table [39, 38, 48, ..., 17] # 完整52位序列 restored Image.new(RGB, (260, 160)) for i in range(52): src_col disorder_table[i] % 26 * 12 1 src_row 80 if disorder_table[i] 25 else 0 block img.crop((src_col, src_row, src_col10, src_row80)) dest_col (i % 26) * 10 dest_row 80 if i 25 else 0 restored.paste(block, (dest_col, dest_row)) return restored5.2 缺口位置识别技术识别缺口位置有多种方法这里介绍最可靠的两种像素对比法def find_gap(full_img, slice_img): full_array np.array(full_img) slice_array np.array(slice_img) for x in range(full_img.width - slice_img.width): # 计算区域相似度 region full_array[:, x:xslice_img.width] diff np.abs(region - slice_array) if np.mean(diff) 3: # 阈值可调整 return x return -1边缘检测法import cv2 def detect_gap_edge(img_path): img cv2.imread(img_path, 0) edges cv2.Canny(img, 100, 200) # 寻找轮廓 contours, _ cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 筛选最可能的缺口位置 # ...具体实现代码省略... return best_x在实际项目中我通常会将两种方法结合使用先通过边缘检测缩小范围再用像素对比精确定位这样准确率能达到95%以上。6. 全链路自动化实现6.1 Python完整实现示例将上述所有技术点整合下面是一个完整的自动化验证示例class GeetestSolver: def __init__(self, gt, challenge): self.gt gt self.challenge challenge self.random_str self._generate_random_str() self.session requests.Session() def solve(self): # 第一阶段获取初始参数 w1 self._generate_w1() response self._request_get(w1) # 第二阶段获取验证码图片 w2 self._generate_w2() img_data self._request_ajax(w2) # 图片还原与缺口识别 full_img self._restore_image(img_data[full]) slice_img self._restore_image(img_data[slice]) distance self._detect_gap(full_img, slice_img) # 生成滑动轨迹 track, passtime self._generate_track(distance) # 最终验证 w3 self._generate_w3(distance, passtime, track) result self._final_verify(w3) return result[validate] # 其他辅助方法实现...6.2 常见问题与调试技巧在开发过程中我遇到过几个典型问题及解决方案403 Forbidden错误检查w1和w2的生成顺序验证随机字符串是否全程保持一致确认请求头中包含必要的Referer和User-Agent轨迹验证失败确保passtime与轨迹总时间匹配检查userresponse计算是否正确尝试增加轨迹中的随机停顿点图片识别不准调整边缘检测的阈值参数尝试多种识别算法组合加入人工校验环节这套解决方案在最新版的极验验证码上测试通过率能达到85%以上对于特别严格的场景可以引入机器学习模型进一步提升识别准确率。

更多文章