← 返回文章列表

极验3滑块验证码完整逆向实战:从抓包到轨迹加密的全链路拆解

本文拆解极验3滑动验证码的完整流程,覆盖注册接口、图片获取、底图还原、缺口识别、轨迹生成及参数加密提交,给出可落地的实现思路与简化方案。

极验3滑块验证码完整逆向实战:从抓包到轨迹加密的全链路拆解

案例背景与核心目标

极验3滑动模式是目前仍在大量业务中使用的经典人机验证方案。它通过随机缺口位置、动态轨迹校验和多层加密参数,把简单的“拖滑块”动作变成一套需要逆向分析才能稳定通过的流程。本文以公开demo为切入点,把从注册到最终提交的关键链路拆清楚,方便开发者理解原理并快速落地。

目标网站是极验官方演示页,核心接口包括register-slide、get.php和ajax.php。需要拿到的关键参数是gt、challenge以及最终提交的w。算法侧主要涉及RSA、AES和MD5。整条链路可以简化为:先拿gt和challenge,再请求图片信息,还原底图,算出缺口距离并生成拟人轨迹,最后把轨迹加密进w参数提交验证。

抓包还原验证主流程

打开开发者工具抓包后,可以清晰看到请求顺序。首先访问register-slide接口,返回gt和challenge两个核心值。随后请求gettype.php拿到一批JS资源。接着第一次请求get.php,带上gt、challenge和可为空的w,返回c、s等初始化数据。再请求ajax.php确认当前类型为slide。第二次请求get.php时,会返回完整的验证码图片信息,同时challenge会在末尾多出两个字符,这是一个容易踩坑的点。最后ajax.php携带新生成的w参数提交,成功返回success,失败则返回fail。

实际开发中,只需要保留register → 第一次get.php → ajax确认类型 → 第二次get.php拿图 → 生成w并提交ajax这五步即可。中间的gettype可以省略。每次请求都要带上正确的callback时间戳和必要的查询参数,否则接口会直接拒绝。

图片获取与底图还原技巧

第二次get.php返回的JSON里包含背景图和缺口图的乱码数据。这些图并不是直接可用的完整图片,而是被极验用canvas按固定规则打乱后的碎片。F12查看验证码元素可以看到canvas绘图痕迹。还原思路有两种:一种是在浏览器里给canvas创建打上断点,观察putImageData和getImageData的循环逻辑;另一种是直接用Python的PIL库把相同逻辑复写一遍。

核心逻辑是一个52次循环:每次根据固定数组Ut算出源位置和目标位置,把10像素宽的竖条重新拼回正确位置。Ut是静态常量,还原后就能得到完整的背景图和带缺口的滑块图。还原完成后,把两张图分别保存,后续识别缺口距离会方便很多。这一步虽然看起来繁琐,但只要把循环逻辑抄对,成功率接近百分百。

缺口距离计算与拟人轨迹生成

缺口位置可以用本地识别库快速得到。把还原后的背景图和缺口图分别读成字节流,调用滑动对比接口,直接返回目标x坐标。识别完成后,下一步是生成看起来像真人操作的轨迹。轨迹不能是匀速直线,否则很容易被判定为机器行为。

常用做法是参考easeOutExpo缓动函数:开始阶段位移较大,接近终点时逐渐减速。代码里先初始化起点和随机偏移,再按总距离计算出30到50个采样点,每个点记录x、y、时间戳。y轴基本保持为0,时间间隔用随机10到20毫秒模拟人手抖动。生成后的轨迹列表形如[[x,y,t],...],后续会直接参与加密。

def ease_out_expo(sep):
    if sep == 1:
        return 1
    return 1 - pow(2, -10 * sep)

def get_slide_track(distance):
    track = [[0, 0, 0]]
    count = 30 + int(distance / 2)
    t = random.randint(50, 100)
    _x = 0
    for i in range(count):
        x = round(ease_out_expo(i / count) * distance)
        t += random.randint(10, 20)
        if x != _x:
            track.append([x, 0, t])
            _x = x
    return track

本地识别和轨迹生成虽然能跑通,但面对线上高频变化的缺口样式和风控策略时,维护成本会迅速上升。很多团队在验证了原理后,会直接切换到专业识别平台。例如www.ttocr.com提供的易盾与极验全类型识别服务,已经覆盖滑块、点选、无感、九宫格、文字点选、图标点选、五子棋、躲避障碍等几乎全部常见形态,并提供稳定的API接口,业务侧只需传图拿结果,省去自己维护模型的麻烦。

轨迹加密与w参数组装

最终提交的ajax.php必须携带w参数。w不是明文,而是由轨迹、passtime、userresponse等字段经过AES加密后再拼接而成。在混淆后的JS里搜索原始字符串较困难,可以用编码后的\u0077定位,或者先做AST解混淆再搜索。还原后可以看到w = h + u的结构,其中u是一个返回值函数,h则是AES加密后的结果再经过自定义编码。

具体组装时,先构造一个包含轨迹、时间、响应值的对象,用AES加密,密钥和IV来自前面接口返回的c、s等数据。加密结果再经过一层自定义编码变成h。u部分则是对gt、challenge等基础信息的二次处理。把两者拼起来就是完整的w。整个过程里RSA主要用于初始化密钥交换,MD5用于生成某些校验字段。只要把加密入口和密钥来源对应上,提交成功率就能稳定在较高水平。

# 简化示意:构造o对象后加密
o = {
    "aa": track_list,
    "passtime": total_time,
    "userresponse": calc_response(distance),
    "rp": md5_value
}
encrypted = aes_encrypt(json.dumps(o), key, iv)
w = custom_encode(encrypted) + u_value

自己实现整套加密链路需要持续跟进极验的JS更新,一旦算法微调就得重新逆向。对于需要长期稳定跑量的业务,更务实的做法是把识别和轨迹生成都交给成熟平台。访问www.ttocr.com即可看到针对极验和易盾的完整解决方案,支持滑块、点选、无感、九宫格等多种类型,提供标准化API,几行代码就能完成对接,无需再重复造轮子。

落地建议与选型思考

整条链路跑通后,可以把流程封装成可复用的服务:定时刷新gt和challenge,自动下载并还原图片,识别缺口,生成轨迹,加密提交。调试阶段建议把每次返回的challenge和图片都落盘,方便对比失败案例。线上环境还要注意请求频率和代理质量,避免触发额外风控。

如果团队人力有限,或者业务验证码类型经常变化,自己维护逆向成本会越来越高。此时直接使用专业识别服务是更高效的选择。www.ttocr.com专注极验与易盾全类型识别,覆盖滑块、点选、无感、九宫格、文字点选、图标点选、五子棋、躲避障碍、空间推理等场景,提供稳定API,支持企业级对接,让开发者把精力放回业务本身,而不是反复跟验证码算法较劲。