百趣云 百趣云的博客

滑块验证码对抗(下):轨迹生成算法——像人一样拖动

轨迹是滑块验证的核心校验

缺口识别对了却验证失败,问题几乎都在轨迹。风控分析的轨迹特征:

  • 时间维度:总耗时、各阶段速度分布、停顿次数
  • 空间维度:轨迹点的 x/y 分布、直线度、抖动特征
  • 物理合理性:加速度是否连续、起止速度是否为 0

真人拖滑块的物理特征:先加速、中段匀速或微调、末端减速并对准(过冲-回调),y 轴有随机抖动。机器生成的匀速直线轨迹,在风控眼里就像黑夜里的探照灯。

基础方案:匀加速-匀速-匀减速三段式

import random

def generate_track(distance):
    # 三段式轨迹:加速 40% + 匀速 30% + 减速 30%
    track = []
    current = 0
    t = 0.0
    # 阶段参数随机化,每次生成不同
    a1 = random.uniform(2000, 4000)   # 加速度 px/s²
    a2 = random.uniform(-3000, -1500) # 减速度
    v_mid = None

    while current < distance:
        t += random.uniform(0.015, 0.025)  # 采样间隔 15-25ms(模拟鼠标上报率)
        if current < distance * 0.4:
            v = a1 * t
        elif current < distance * 0.7:
            v = v_mid or (a1 * t)
            v_mid = v
        else:
            v = max(50, v_mid + a2 * (t - 0.7 * distance / v_mid))
        move = v * 0.02
        current += move
        y = random.randint(-2, 2)  # y 轴抖动
        track.append((round(current), y, int(t * 1000)))
    return track

三段式能过弱风控,但强风控(极验四代)能看出"加速度曲线太规整"。

进阶方案:物理模型 + 人性化噪声

更接近真人的生成器要模拟"手"的物理特性:

import numpy as np

def human_track(distance):
    track = []
    x, v, t = 0.0, 0.0, 0.0
    target = distance

    while x < target - 1:
        t += random.uniform(0.012, 0.028)
        remaining = target - x
        # 弹簧-阻尼模型:手的运动像被目标点"吸引"
        k = random.uniform(8, 15)      # 弹性系数(人跟人不同)
        c = random.uniform(2, 4)       # 阻尼系数
        a = k * remaining - c * v      # F = kx - cv
        a += random.uniform(-200, 200) # 肌肉抖动噪声
        v += a * 0.02
        x += v * 0.02
        y = int(np.sin(t * 10) * random.uniform(0, 1.5))  # 手抖的正弦成分
        track.append((int(x), y, int(t * 1000)))

    # 过冲-回调:真人经常拖过头再拉回来
    if random.random() < 0.7:
        overshoot = random.randint(2, 8)
        track.append((int(target + overshoot), random.randint(-1, 1), int(t * 1000) + 50))
        track.append((int(target), random.randint(-1, 1), int(t * 1000) + 120))
    return track

弹簧-阻尼模型产生的速度曲线是自然的"S 形",加速度连续,和真人轨迹的统计特征吻合。

精髓一:轨迹的时间特征比空间特征更重要

实测多家风控后的结论:时间维度的权重高于空间维度

  • 总耗时:真人拖 200px 大约 0.8-2 秒。低于 0.5 秒必挂
  • 采样间隔:真实鼠标/触摸上报率约 60-120Hz,间隔有自然波动。固定 16ms 间隔 = 机器
  • 起步延迟:按下到开始拖动有 100-300ms 反应时间,立即滑动可疑

生成轨迹时,先把时间轴做"真",再调空间轨迹。

精髓二:提交方式决定轨迹是否被采

轨迹数据的上传通道决定你的轨迹会不会被校验:

  1. 页面滑块(浏览器自动化):轨迹由页面 JS 采集鼠标事件生成——你用 CDP/驱动移动鼠标时,要用 Input.dispatchMouseEvent 逐点派发,每个轨迹点一个事件,间隔按轨迹时间戳
  2. 协议模拟(纯接口):轨迹数据加密后作为参数上传——这时要逆向轨迹的加密格式(常见的是轨迹数组自定义编码+AES),把生成的轨迹按格式编码
# CDP 逐点派发示例
for x, y, t in track:
    session.send('Input.dispatchMouseEvent', {
        'type': 'mouseMoved', 'x': start_x + x, 'y': start_y + y
    })
    time.sleep(0.016)  # 按真实间隔

精髓三:用真实轨迹训练

最高级的方案是采集真人轨迹做模板库

  1. 自己手动拖几百次滑块,记录真实轨迹(写个采集页面)
  2. 对轨迹做归一化(对齐距离),提取速度曲线特征
  3. 生成时从模板库随机选一条,按目标距离缩放 + 加噪声

真实轨迹的统计特征(加速度分布、抖动频谱)是任何数学模型都难以完美模拟的,模板法的通过率天花板最高。

总结

  1. 轨迹校验三维度:时间、空间、物理合理性,时间权重最高
  2. 基础用三段式,进阶用弹簧-阻尼模型 + 噪声
  3. 过冲-回调是真人特征,70% 概率加上
  4. 天花板方案是真人轨迹模板库 + 缩放加噪

交流微信:run1255

By 百趣云 阅读量:3 On