【验证码逆向专栏】数美验证码全家桶逆向分析以及 AST 获取动态参数
字数 2093 2025-08-11 00:08:50

数美验证码全家桶逆向分析与AST动态参数获取教学文档

一、目标概述

本教学文档针对数美验证码全家桶进行逆向分析,包括以下验证码类型:

  • 滑块验证码 (slide)
  • 文字点选验证码 (select)
  • 图标点选验证码 (icon_select)
  • 语序点选验证码 (seq_select)
  • 空间推理验证码 (spatial_select)
  • 无感验证码 (auto_slide)

二、验证码接口分析

1. 验证码体验地址

  • 官网体验地址:aHR0cHM6Ly93d3cuaXNodW1laS5jb20vdHJpYWwvY2FwdGNoYS5odG1s
  • 官方隐藏地址(包含无感验证):aHR0cHM6Ly9jYXN0YXRpYy5mZW5na29uZ2Nsb3VkLmNuL3ByL3YxLjAuNC9kZW1vLmh0bWw=
  • 某红书验证页面:aHR0cHM6Ly93d3cueGlhb2hvbmdzaHUuY29tL3dlYi1sb2dpbi9jYXB0Y2hh

2. 核心接口分析

(1) conf接口 - 获取配置

请求参数

参数 含义
organization 数美分配的公司标识,每个网站唯一
appId 应用标识,区分不同应用
callback 回调参数
lang 语言(zh-cn/zh-tw/en)
model 验证码模式
sdkver captcha-sdk.min.js内部写死的版本
channel 推广渠道
captchaUuid 32位随机字符串
rversion captcha-sdk.min.js版本号

返回结果:主要获取captcha-sdk.min.js文件地址

(2) register接口 - 注册验证码

返回数据

  • bg: 背景图片
  • fg: 滑块图片(滑块验证码)
  • order: 提示信息(文字点选、空间推理)
  • k, l, rid: 后续加密使用的关键参数

(3) fverify接口 - 验证接口

请求参数:12个动态生成的加密参数,包括:

  • 类似ep的长参数(包含轨迹加密)
  • 其他11个动态参数

返回结果

  • code: 状态码(1100成功,1901 QPS超限,1902 参数不合法,1903 服务失败,9101 无权限操作)
  • riskLevel: 处置建议(PASS正常,REJECT违规)

三、核心逆向分析

1. JS混淆与反混淆

  • 核心逻辑在captcha-sdk.min.js中,采用类似OB混淆
  • 可使用v_jstools工具进行解混淆
  • 重要提示:替换JS时需注意:
    • 解决跨域问题(设置响应头Access-Control-Allow-Origin
    • JS不能格式化(有格式化检测),需保持压缩为一行

2. captchaUuid生成算法

function generateTimeFormat() {
    var e = new Date()
    , t = function(n) {
        return +n < 10 ? "0" + n : n.toString();
    };
    return ((e.getFullYear().toString() + t(e.getMonth() + 1)) + t(e.getDate()) + t(e.getHours()) + t(e.getMinutes())) + t(e.getSeconds());
}

function getCaptchaUuid() {
    var c = "";
    var o = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678";
    var s = o.length;
    for (var a = 0; a < 18; a++) {
        c += o.charAt(Math.floor(Math.random() * s));
    }
    return generateTimeFormat() + c;
}

3. 12个加密参数生成逻辑

  • 通过getEncryptContent方法生成4个加密参数
  • 通过getMouseAction方法生成另外8个参数

(1) getEncryptContent加密方法

  • 标准DES加密算法
  • 模式:ECB
  • 填充:ZeroPadding
  • 不需要IV

加密实现

var CryptoJS = require("crypto-js")

function DESEncrypt(key, word) {
    var key_ = CryptoJS.enc.Utf8.parse(key);
    var srcs = CryptoJS.enc.Utf8.parse(word);
    var encrypted = CryptoJS.DES.encrypt(srcs, key_, {
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.ZeroPadding
    });
    return encrypted.toString();
}

function DESDecrypt(key, word) {
    var key_ = CryptoJS.enc.Utf8.parse(key);
    var decrypt = CryptoJS.DES.decrypt(word, key_, {
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.ZeroPadding
    });
    return decrypt.toString(CryptoJS.enc.Utf8);
}

(2) 格式化检测

  • isJsFormat函数检测JS是否被格式化
  • 若检测到格式化,会导致DES Key错误,验证失败

4. 不同类型验证码的数据结构

(1) 滑块验证码(slide)

var baseData = {}
baseData.mouseData = track  // 滑动轨迹 [[x,y,t],...]
baseData.startTime = 0
baseData.endTime = track[track.length - 1][2] + randomNum(100, 500)
baseData.mouseEndX = distance  // 滑动距离
baseData.trueWidth = 300
baseData.trueHeight = 150
baseData.selectData = []
baseData.blockWidth = 40

滑块轨迹生成算法(Python示例)

def get_sm_track(distance):
    track_length = random.randint(4, 10)
    track = [[0, -2, 0]]
    m = distance % track_length
    e = int(distance / track_length)
    for i in range(track_length):
        x = (i + 1) * e + m + random.randint(20, 40)
        y = -2 + (random.randint(-1, 10))
        t = (i + 1) * 100 + random.randint(-3, 5)
        if i == track_length - 1:
            x = distance
            track.append([x, y, t])
        else:
            track.append([x, y, t])
    return track

(2) 点选类验证码

var baseData = {}
var time_ = new Date().getTime()
coordinate.forEach(function(co) {
    co[0] = co[0] / 300
    co[1] = co[1] / 150
    co[2] = time_
    time_ += randomNum(100, 500)
})
baseData.mouseData = coordinate
baseData.startTime = time_ - randomNum(800, 20000)
baseData.endTime = coordinate[coordinate.length - 1][2]
baseData.mouseEndX = 0
baseData.trueWidth = 300
baseData.trueHeight = 150
baseData.selectData = coordinate
baseData.blockWidth = undefined

(3) 无感验证码(auto_slide)

var baseData = {}
baseData.mouseData = [[0, 0, 0]]
baseData.startTime = 0
baseData.endTime = randomNum(100, 500)
baseData.mouseEndX = 260
baseData.trueWidth = 300
baseData.trueHeight = 150
baseData.selectData = []
baseData.blockWidth = 40

四、AST获取动态参数

1. 版本号规则

  • v1.0.4-171v1.0.4为大版本,171为小版本
  • 小版本不定期更新,版本号递增
  • 可通过document.lastModified查看JS更新时间

2. 兼容版本

以下版本已验证可正常提取动态参数:

  • v1.0.4-148 ~ v1.0.4-171
  • v1.0.3-147 ~ v1.0.3-171
  • v1.0.1-147 ~ v1.0.1-171

3. AST提取要点

  • 提取结果是有序、未去重的
  • 按索引顺序获取参数即可
  • 仅提取动态参数,不还原所有混淆

五、注意事项

  1. DES Key:会定期变化,需动态获取
  2. 参数名称:12个加密参数的名称也会随版本变化
  3. 格式化检测:替换JS时需保持压缩格式
  4. 跨域问题:使用Fiddler替换时需设置Access-Control-Allow-Origin
  5. 版本更新:定期检查JS版本变化,更新AST解析逻辑

六、总结

本教学文档详细分析了数美验证码全家桶的逆向过程,包括:

  1. 接口请求流程与参数分析
  2. 核心加密算法与参数生成逻辑
  3. 不同类型验证码的数据结构差异
  4. 使用AST动态获取参数的方法
  5. 实际逆向过程中的注意事项

通过掌握这些关键点,可以有效应对数美验证码的逆向需求,实现自动化验证。

数美验证码全家桶逆向分析与AST动态参数获取教学文档 一、目标概述 本教学文档针对数美验证码全家桶进行逆向分析,包括以下验证码类型: 滑块验证码 (slide) 文字点选验证码 (select) 图标点选验证码 (icon_ select) 语序点选验证码 (seq_ select) 空间推理验证码 (spatial_ select) 无感验证码 (auto_ slide) 二、验证码接口分析 1. 验证码体验地址 官网体验地址: aHR0cHM6Ly93d3cuaXNodW1laS5jb20vdHJpYWwvY2FwdGNoYS5odG1s 官方隐藏地址(包含无感验证): aHR0cHM6Ly9jYXN0YXRpYy5mZW5na29uZ2Nsb3VkLmNuL3ByL3YxLjAuNC9kZW1vLmh0bWw= 某红书验证页面: aHR0cHM6Ly93d3cueGlhb2hvbmdzaHUuY29tL3dlYi1sb2dpbi9jYXB0Y2hh 2. 核心接口分析 (1) conf接口 - 获取配置 请求参数 : | 参数 | 含义 | |------|------| | organization | 数美分配的公司标识,每个网站唯一 | | appId | 应用标识,区分不同应用 | | callback | 回调参数 | | lang | 语言(zh-cn/zh-tw/en) | | model | 验证码模式 | | sdkver | captcha-sdk.min.js内部写死的版本 | | channel | 推广渠道 | | captchaUuid | 32位随机字符串 | | rversion | captcha-sdk.min.js版本号 | 返回结果 :主要获取 captcha-sdk.min.js 文件地址 (2) register接口 - 注册验证码 返回数据 : bg : 背景图片 fg : 滑块图片(滑块验证码) order : 提示信息(文字点选、空间推理) k , l , rid : 后续加密使用的关键参数 (3) fverify接口 - 验证接口 请求参数 :12个动态生成的加密参数,包括: 类似 ep 的长参数(包含轨迹加密) 其他11个动态参数 返回结果 : code : 状态码(1100成功,1901 QPS超限,1902 参数不合法,1903 服务失败,9101 无权限操作) riskLevel : 处置建议(PASS正常,REJECT违规) 三、核心逆向分析 1. JS混淆与反混淆 核心逻辑在 captcha-sdk.min.js 中,采用类似OB混淆 可使用 v_jstools 工具进行解混淆 重要提示 :替换JS时需注意: 解决跨域问题(设置响应头 Access-Control-Allow-Origin ) JS不能格式化(有格式化检测),需保持压缩为一行 2. captchaUuid生成算法 3. 12个加密参数生成逻辑 通过 getEncryptContent 方法生成4个加密参数 通过 getMouseAction 方法生成另外8个参数 (1) getEncryptContent加密方法 标准DES加密算法 模式:ECB 填充:ZeroPadding 不需要IV 加密实现 : (2) 格式化检测 isJsFormat 函数检测JS是否被格式化 若检测到格式化,会导致DES Key错误,验证失败 4. 不同类型验证码的数据结构 (1) 滑块验证码(slide) 滑块轨迹生成算法(Python示例) : (2) 点选类验证码 (3) 无感验证码(auto_ slide) 四、AST获取动态参数 1. 版本号规则 v1.0.4-171 : v1.0.4 为大版本, 171 为小版本 小版本不定期更新,版本号递增 可通过 document.lastModified 查看JS更新时间 2. 兼容版本 以下版本已验证可正常提取动态参数: v1.0.4-148 ~ v1.0.4-171 v1.0.3-147 ~ v1.0.3-171 v1.0.1-147 ~ v1.0.1-171 3. AST提取要点 提取结果是有序、未去重的 按索引顺序获取参数即可 仅提取动态参数,不还原所有混淆 五、注意事项 DES Key :会定期变化,需动态获取 参数名称 :12个加密参数的名称也会随版本变化 格式化检测 :替换JS时需保持压缩格式 跨域问题 :使用Fiddler替换时需设置 Access-Control-Allow-Origin 版本更新 :定期检查JS版本变化,更新AST解析逻辑 六、总结 本教学文档详细分析了数美验证码全家桶的逆向过程,包括: 接口请求流程与参数分析 核心加密算法与参数生成逻辑 不同类型验证码的数据结构差异 使用AST动态获取参数的方法 实际逆向过程中的注意事项 通过掌握这些关键点,可以有效应对数美验证码的逆向需求,实现自动化验证。