【验证码逆向专栏】某亭雷池 waf 验证码逆向分析
字数 1171 2025-08-29 22:41:38

某亭雷池WAF验证码逆向分析教学文档

一、目标分析

目标网站:aHR0cHM6Ly95dW5wYW4xLndhbmcv (已脱敏)

验证码类型:无感验证、直滑验证

二、环境检测绕过

1. 控制台检测机制

当打开开发者工具时,页面显示"当前环境正在被调试",这是通过v2/challenge.js文件中的控制台检测实现的。

2. 检测点定位

搜索关键字devtools发现关键检测函数:

  • devtoolsFormatterChecker - 控制台格式检查器
  • _detectLoop - 轮询检测函数,每500ms检查一次控制台状态

3. 绕过方法

方法一:注释或替换检查器

// 将检查器return f.a注释或替换

方法二:重写轮询函数

// 断点定位到_detectLoop调用处
this._detectLoop = function() {}; // 直接置空

方法三:修改launch方法调用

参考项目:https://github.com/AEPKILL/devtools-detector

三、接口分析

1. 请求流程

  1. 首次请求首页,状态码468
  2. 验证成功后,cookie携带sl-challenge-jwt
  3. 成功返回数据,状态码200

2. 关键接口

issue接口

  • client_id:首次请求首页468响应内容中获取

verify接口

  • visitorId:访问者ID(需分析)
  • issue_id:由issue接口返回
  • result:加密参数(需分析)
  • serials:轨迹值(无感/直滑验证的区别点)

四、参数逆向

1. visitorId生成

定位到v2/challenge.js文件,使用fingerprintjs v3库生成设备指纹:

const FingerprintJS = require('@fingerprintjs/fingerprintjs');

FingerprintJS.load().then(fp => {
    fp.get().then(result => {
        console.log(result.visitorId);
    });
});

替代方案:使用fingerprintjs2(对Node.js环境更友好)

const Fingerprint2 = require('fingerprintjs2');

Fingerprint2.get(components => {
    const values = components.map(component => component.value);
    const murmur = Fingerprint2.x64hash128(values.join(''), 31);
    console.log(murmur);
});

2. result参数加密

加密流程分析

  1. 通过XHR断点定位到result生成位置
  2. 发现是通过e(t.data)的返回值
  3. 使用createObjectURL创建临时对象链接

HOOK定位方法

originalCreateObjectURL = URL.createObjectURL;
URL.createObjectURL = function(obj) {
    console.trace("Blob 被创建了", obj);
    debugger;
    return originalCreateObjectURL.call(this, obj);
};

加密实现

  1. 使用v2/calc.wasm文件进行WebAssembly计算
  2. 传入issue接口返回的data值
  3. 通过WASM模块处理后返回result

Node.js复现代码

const fs = require('fs');

function get_result(data){
    wasm = fs.readFileSync('./calc.wasm');
    e = {
        data: {
            "action": "calc",
            "data": {
                "data": data,
                "issue_id": ""
            },
            "wasm": wasm
        }
    }
    var result;
    var flag = false;
    WebAssembly.instantiate(e.data.wasm).then(function(t) {
        result = function(e) {
            return t.instance.exports.reset(),
            e.map(function(e) {
                return t.instance.exports.arg(e)
            }),
            Array(t.instance.exports.calc()).fill(-1).map(function() {
                return t.instance.exports.ret()
            })
        }(e.data.data.data);
        flag = true;
    }).catch(function(e) {
        console.log(e);
    })
    while (!flag) {
        require('deasync').sleep(100);
    }
    return result;
};

console.log(get_result([99, 35, 92, 48, 61, 31, 18, 43, 3, 54, 48, 22, 62, 50]));
// 输出: [ 17, 26, 51, 20 ]

兼容算法

分析发现还有一套JS算法与WASM计算结果一致:

function f(e) {
    for (var t = 1, n = e.reduce(function(e, t) {
        return e + t
    }, 0), r = (6 + e.length + n) % 6 + 6; r--; )
        t *= 6;
    t < 6666 && (t *= e.length),
    t > 0x3f940aa && (t = Math.floor(t / e.length));
    for (var o = 0; o < e.length; o++)
        t += Math.pow(e[o], 3),
        t ^= o,
        t ^= e[o] + o;
    for (var f = []; t > 0; )
        f.unshift(63 & t),
        t >>= 6;
    return f
};

console.log(f([99, 35, 92, 48, 61, 31, 18, 43, 3, 54, 48, 22, 62, 50]));
// 输出: [ 17, 26, 51, 20 ]

五、完整验证流程

  1. 首次请求获取client_id
  2. 生成visitorId
  3. 调用issue接口获取dataissue_id
  4. 使用WASM或JS算法计算result
  5. 构造verify请求参数
  6. 获取sl-challenge-jwt并携带访问

六、注意事项

  1. 本文所有技术仅用于学习交流
  2. 严禁用于商业用途和非法用途
  3. 已对敏感信息进行脱敏处理
  4. 未经许可禁止转载或二次传播

七、参考资源

  1. devtools-detector项目
  2. fingerprintjs官方库
  3. 在线指纹测试
某亭雷池WAF验证码逆向分析教学文档 一、目标分析 目标网站 :aHR0cHM6Ly95dW5wYW4xLndhbmcv (已脱敏) 验证码类型 :无感验证、直滑验证 二、环境检测绕过 1. 控制台检测机制 当打开开发者工具时,页面显示"当前环境正在被调试",这是通过 v2/challenge.js 文件中的控制台检测实现的。 2. 检测点定位 搜索关键字 devtools 发现关键检测函数: devtoolsFormatterChecker - 控制台格式检查器 _detectLoop - 轮询检测函数,每500ms检查一次控制台状态 3. 绕过方法 方法一 :注释或替换检查器 方法二 :重写轮询函数 方法三 :修改launch方法调用 参考项目 :https://github.com/AEPKILL/devtools-detector 三、接口分析 1. 请求流程 首次请求首页,状态码468 验证成功后,cookie携带 sl-challenge-jwt 值 成功返回数据,状态码200 2. 关键接口 issue接口 : client_id :首次请求首页468响应内容中获取 verify接口 : visitorId :访问者ID(需分析) issue_id :由issue接口返回 result :加密参数(需分析) serials :轨迹值(无感/直滑验证的区别点) 四、参数逆向 1. visitorId生成 定位到 v2/challenge.js 文件,使用fingerprintjs v3库生成设备指纹: 替代方案 :使用fingerprintjs2(对Node.js环境更友好) 2. result参数加密 加密流程分析 通过XHR断点定位到result生成位置 发现是通过 e(t.data) 的返回值 使用 createObjectURL 创建临时对象链接 HOOK定位方法 加密实现 使用 v2/calc.wasm 文件进行WebAssembly计算 传入 issue 接口返回的data值 通过WASM模块处理后返回result Node.js复现代码 : 兼容算法 分析发现还有一套JS算法与WASM计算结果一致: 五、完整验证流程 首次请求获取 client_id 生成 visitorId 调用issue接口获取 data 和 issue_id 使用WASM或JS算法计算 result 构造verify请求参数 获取 sl-challenge-jwt 并携带访问 六、注意事项 本文所有技术仅用于学习交流 严禁用于商业用途和非法用途 已对敏感信息进行脱敏处理 未经许可禁止转载或二次传播 七、参考资源 devtools-detector项目 fingerprintjs官方库 在线指纹测试