极验GT4滑块验证协议全链路逆向演示

极验从第三代验证码迭代到第四代后,核心加密逻辑的复杂度有了质的飞跃——尤其是环境指纹采集、行为轨迹拟合等环节。但对于官方公开的演示站,或者能够通过浏览器 Hook 稳定提取关键生成函数的情况,仍然可以构建一套轻量、可复现的全流程自动化方案。

本文将以极验官方 GT4 登录 Demo 为目标,展示如何用 Python + Node.js 搭建一个极简实现,完整走通验证流程。


一、整体验证流程拆解

GT4 简化版的公开验证逻辑可以拆分为 4 个核心步骤

  1. 生成 UUID 格式的 challenge 标识
    这是验证流水线的起点,每次验证需要一个全局唯一的标识符。

  2. 调用 /load 接口拉取验证配置
    拿到 lot_numberpayloadprocess_token 以及静态资源路径 static_path 等关键字段。

  3. 核心逆向:生成加密参数 w
    调用从浏览器中 Hook 或补环境后提取的 JS 函数,计算出 w 参数。这一步是整个流程中最难的部分。

  4. 调用 /verify 接口通过极验服务器验证
    携带着上一步生成的 w 及其它元数据请求验证接口,最终得到业务可用的 seccode

  5. 携带 seccode 完成业务 Demo 登录
    seccode 中的 pass_tokengen_timecaptcha_output 等参数,向后端业务接口发送请求,完成登录。

下面我们直接看代码实现。


二、轻量级实现代码

前置依赖

pip install requests PyExecJS

注意PyExecJS 需要本地已安装 Node.js 并将 node 命令添加到环境变量中。执行时会通过子进程调用 Node 来运行 JavaScript 代码。

Python 主逻辑(main.py

import requests
import time
import execjs
import json
from datetime import datetime, timezone, timedelta

# ---------------------- 1. 初始化 JS 执行环境 ----------------------
# demo.js 是通过浏览器 Hook / 补环境后提取的核心 JS 代码(需自行准备)
with open("demo.js", "r", encoding="utf-8") as f:
    jscode = f.read()
ctx = execjs.compile(jscode)

# ---------------------- 2. 基础配置 ----------------------
CAPTCHA_ID = "99b142aaece96330d0f3ffb565ffb3ef"  # 极验 GT4 Demo 站固定 captcha_id
BASE_HEADERS = {
    "Accept": "*/*",
    "Accept-Language": "zh-CN,zh;q=0.9",
    "Cache-Control": "no-cache",
    "Connection": "keep-alive",
    "Pragma": "no-cache",
    "Referer": "https://gt4.geetest.com/",
    "Sec-Fetch-Dest": "script",
    "Sec-Fetch-Mode": "no-cors",
    "Sec-Fetch-Site": "same-site",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36",
    "sec-ch-ua": "\"Not;A=Brand\";v=\"99\", \"Google Chrome\";v=\"139\", \"Chromium\";v=\"139\"",
    "sec-ch-ua-mobile": "?0",
    "sec-ch-ua-platform": "\"Windows\""
}
# 可选:极验 GT4 Demo 站的临时 Cookie(可省略但响应速度可能稍慢)
BASE_COOKIES = {
    "captcha_v4_user": "011a9cb06bdd4689975694733321d078",
    "sensorsdata2015jssdkcross": "%7B%22distinct_id%22%3A%221984a8102985cf-0b16af714940d38-26011151-2073600-1984a810299111c%22%2C%22first_id%22%3A%22%22%2C%22props%22%3A%7B%7D%2C%22%24device_id%22%3A%221984a8102985cf-0b16af714940d38-26011151-2073600-1984a810299111c%22%7D",
    "Hm_lvt_25b04a5e7a64668b9b88e2711fb5f0c4": "1753596626,1753862889",
    "_uetvid": "635904806ab011f0ba3ed52cdc6e75e1"
}

# ---------------------- 3. 生成 challenge 标识 ----------------------
challenge = ctx.call("uuid")

# ---------------------- 4. 调用 Load 接口拉取验证配置 ----------------------
load_params = {
    "captcha_id": CAPTCHA_ID,
    "challenge": challenge,
    "client_type": "web",
    "lang": "zho",
    "callback": f"geetest_{int(time.time() * 1000)}"
}
load_resp = requests.get(
    url="https://gcaptcha4.geetest.com/load",
    headers=BASE_HEADERS,
    cookies=BASE_COOKIES,
    params=load_params
)
# 去掉 JSONP 外层的回调函数名,提取真正的 JSON 数据
load_data = json.loads(load_resp.text[load_resp.text.find('{'): -1])["data"]

# ---------------------- 5. 核心:生成加密参数 w ----------------------
# GT4 要求带 +08:00 时区的 ISO 格式时间(必须严格带时区)
formatted_time = datetime.now(timezone(timedelta(hours=8))).isoformat()
# 调用提取的 getW 函数(需 demo.js 中暴露该函数)
w = ctx.call(
    "getW",
    load_data["lot_number"],
    CAPTCHA_ID,
    formatted_time,
    load_data["static_path"],
    load_data["payload"],
    load_data["process_token"]
)

# ---------------------- 6. 调用 Verify 接口通过验证 ----------------------
verify_params = {
    "callback": f"geetest_{int(time.time() * 1000)}",
    "captcha_id": CAPTCHA_ID,
    "client_type": "web",
    "lot_number": load_data["lot_number"],
    "payload": load_data["payload"],
    "process_token": load_data["process_token"],
    "payload_protocol": "1",
    "pt": "1",
    "w": w
}
verify_resp = requests.get(
    url="https://gcaptcha4.geetest.com/verify",
    headers=BASE_HEADERS,
    cookies=BASE_COOKIES,
    params=verify_params
)
verify_data = json.loads(verify_resp.text[verify_resp.text.find('{'): -1])["data"]["seccode"]

# ---------------------- 7. 携带 seccode 完成 Demo 业务交互 ----------------------
demo_params = {
    "captcha_id": CAPTCHA_ID,
    "lot_number": load_data["lot_number"],
    "pass_token": verify_data["pass_token"],
    "gen_time": verify_data["gen_time"],
    "captcha_output": verify_data["captcha_output"]
}
demo_resp = requests.get(
    url="https://gt4.geetest.com/demov4/demo/login",
    headers=BASE_HEADERS,
    params=demo_params
)
print("Demo 业务接口响应:", demo_resp.json())

三、关键注意事项

1. 关于 demo.js 的获取

本文只提供 Python 端的调用框架,核心的 demo.js 并不包含在内。你需要通过以下方式自行准备:

  • 浏览器 Hook
    在 Chrome DevTools 中对 XHR/Fetch 或关键 JS 文件设断点,找到处理 /load 接口响应并生成 w 的函数,然后将其导出。常见的目标函数通常会调用类似 __gct$$_X 等混淆名。

  • 自动化浏览器补环境
    使用 Puppeteer 或 Playwright 加载页面,直接调用页面内的完整逻辑。但这种方式引入了完整浏览器依赖,与本文的“轻量级”目标相悖,故不再展开。

无论哪种方式,最终得到的 demo.js 都需要暴露两个函数:
function uuid() – 生成 challenge;
function getW(lot_number, captcha_id, time, static_path, payload, process_token) – 生成加密参数 w

2. 关于带时区的 ISO 时间

GT4 的 getW 函数对时间格式非常敏感,必须使用 +08:00(东八区)时区标记的 ISO 8601 格式,例如 2025-08-01T12:00:00+08:00。若时区信息错误或缺失,极验服务器会直接拒绝此次验证请求。

代码中我们通过 datetime.now(timezone(timedelta(hours=8))) 来精确生成带时区的时间戳。

这里提供的 Cookie 并不是必填项,但携带与 User-Agent 匹配的临时 Cookie 能够减少极验服务器对环境的额外探测,从而提升验证通过的概率与响应速度。在生产环境中,通常需要从真实浏览器浏览过程中提取这些 Cookie。

4. 关于 JSONP 回调的处理

极验的 /load/verify 接口默认返回 JSONP 格式(如 geetest_123456({...})),代码中直接通过字符串截取去掉外层函数调用,再交由 json.loads 解析。如果你希望更健壮,也可以考虑用正则提取,但在 Demo 场景下字符串切片足够使用。


四、总结

本文给出了一套针对极验 GT4 官方演示站的全链路轻量级自动化方案。整条链路的难点集中于 demo.js 的提取与补环境工作,而 Python 侧只是按顺序串联请求、组装参数。

对于真实的线上业务,GT4 通常会叠加复杂的行为轨迹拟合算法、强环境指纹校验以及后端风险分析,本文的简化方案无法直接复用。届时还需要结合轨迹生成算法、更深度的浏览器环境模拟才能稳定通过。

希望这篇演示能帮助你理清 GT4 验证的完整交互逻辑,为更深入的逆向工作铺平道路。