【验证码逆向专栏】最新某度旋转验证码 v2 逆向分析
字数 1493 2025-08-10 16:34:31

某度旋转验证码v2逆向分析教学文档

1. 验证码概述

某度旋转验证码v2是一种基于用户交互行为的验证系统,主要包含以下特点:

  • 采用旋转滑块形式
  • 使用AI生成的底图(非旧版风景图)
  • 包含多重加密机制
  • 加入了浏览器指纹验证
  • 验证流程分为多个接口交互

2. 验证码流程分析

2.1 接口交互流程

  1. init接口 - 初始化验证码

    • 请求参数:
      • ver: 固定值"1"
      • _: 13位时间戳
      • refer: 网站URL
      • ak: 固定值(盾ID,不同网站不同)
    • 响应参数:
      • as: 后续加密使用
      • tk: 后续请求使用
  2. style接口 - 获取验证码样式

    • 请求参数:
      • tk: init接口返回
      • _: 时间戳
    • 响应参数:
      • path: 旋转验证码底图URL
      • backstr: 生成fs参数的关键部分
  3. log接口 - 提交验证结果

    • 请求参数:
      • ak: 盾ID
      • tk: init接口返回
      • as: init接口返回
      • fs: 加密参数(需逆向)
      • fuid: 浏览器指纹
  4. urlsubmit接口 - 最终提交

    • 请求参数:
      • ds: log接口返回
      • tk: log接口返回
      • url: 提交的链接地址

2.2 验证结果判断

  • 验证码未转正:响应op值为3
  • 验证码转正:响应op值为1
  • 提交成功:{"over":0, "status":0}
  • 验证码信息有误:{"status":101}
  • 未输入提交链接:{"status":2}
  • 未添加cookies:not allowed

3. 关键参数逆向分析

3.1 fs参数生成流程

fs参数生成分为两个阶段:

第一阶段fs生成

n.fs = (0, f.Li)(JSON.stringify(this.rzData), this.secondHandle)
  • this.rzData: 包含backstr及鼠标轨迹等参数
  • this.secondHandle: 主要包含as参数

关键参数ac_c(旋转比例)计算:

Number((this.distance / (e - 52)).toFixed(2))
  • this.distance: 滑动的距离
  • e: 固定值290(滑动条最大长度)

第二阶段fs生成(最终fs)

n.fs = (0, f.Li)(JSON.stringify({
  common_en: n.fs,  // 第一阶段生成的fs
  backstr: this.cfg.backstr
}), {
  key: this.newKey,
  as: this.cfg.as,
  method: "aes-ecb"
})

3.2 加密密钥生成

密钥生成函数getNewKey(as):

function getNewKey(as) {
  var encryptedStr = as + "appsapi2";
  var r = as.substr(as.length - 1, 1);
  var encryptedValue;
  
  switch(true) {
    case ['A','B','C','D','E','F','G','a','b','c','d','e','f','g'].includes(r):
      encryptedValue = CryptoJS.MD5(encryptedStr).toString();
      break;
    case ['H','I','J','K','L','M','N','h','i','j','k','l','m','n'].includes(r):
      encryptedValue = CryptoJS.SHA1(encryptedStr).toString(CryptoJS.enc.Hex);
      break;
    case ['O','P','Q','R','S','T','o','p','q','r','s','t'].includes(r):
      encryptedValue = CryptoJS.SHA256(encryptedStr).toString(CryptoJS.enc.Hex);
      break;
    case ['U','V','W','X','Y','Z','u','v','w','x','y','z'].includes(r):
      encryptedValue = CryptoJS.SHA512(encryptedStr).toString(CryptoJS.enc.Hex);
      break;
    case ['0','1','2','3','4'].includes(r):
      encryptedValue = CryptoJS.SHA3(encryptedStr, {outputLength: 256}).toString(CryptoJS.enc.Hex);
      break;
    case ['5','6','7','8','9'].includes(r):
      encryptedValue = CryptoJS.SHA3(encryptedStr, {outputLength: 512}).toString(CryptoJS.enc.Hex);
      break;
    default:
      encryptedValue = encryptedStr;
  }
  
  var key = encryptedValue.slice(0, 16);
  return key;
}

3.3 加密函数分析

加密函数encrypt采用AES加密,与旧版区别:

  1. 密钥生成方式不同:
    • 旧版:key = as + "appsapi2"
    • 新版:key = getNewKey(as)(as+"appsapi2"加密后取前16位)
  2. 填充方式不同:
    • 旧版:PKCS7
    • 新版:ZeroPadding

加密模式:ECB(电子码本模式)

4. 浏览器指纹fuid分析

fuid特点:

  • 不同浏览器值不一致
  • 相同浏览器短时间内不变
  • 过一段时间会变化
  • 由user-agent、canvas、plugins等浏览器属性构成

生成位置:fingerprint.js文件

  • F方法:encodeURIComponent()
  • U方法:AES加密(ECB模式,PKCS7填充,固定key)

5. 模拟注意事项

  1. 轨迹模拟

    • 不能直接固定,需模拟构造
    • 校验相对严格
    • 轨迹中有重要参数
  2. 识别模型

    • 底图已改为AI生成(非旧版风景图)
    • 需要重新训练识别模型
  3. 加密实现

    • 需完整实现两阶段fs生成
    • 注意密钥生成规则
    • 使用正确的加密模式和填充方式

6. JavaScript实现示例

const CryptoJS = require('crypto-js');

// 密钥生成函数
function getNewKey(as) {
  var encryptedStr = as + "appsapi2";
  var r = as.substr(as.length - 1, 1);
  var encryptedValue;
  
  switch(true) {
    case ['A','B','C','D','E','F','G','a','b','c','d','e','f','g'].includes(r):
      encryptedValue = CryptoJS.MD5(encryptedStr).toString();
      break;
    case ['H','I','J','K','L','M','N','h','i','j','k','l','m','n'].includes(r):
      encryptedValue = CryptoJS.SHA1(encryptedStr).toString(CryptoJS.enc.Hex);
      break;
    case ['O','P','Q','R','S','T','o','p','q','r','s','t'].includes(r):
      encryptedValue = CryptoJS.SHA256(encryptedStr).toString(CryptoJS.enc.Hex);
      break;
    case ['U','V','W','X','Y','Z','u','v','w','x','y','z'].includes(r):
      encryptedValue = CryptoJS.SHA512(encryptedStr).toString(CryptoJS.enc.Hex);
      break;
    case ['0','1','2','3','4'].includes(r):
      encryptedValue = CryptoJS.SHA3(encryptedStr, {outputLength: 256}).toString(CryptoJS.enc.Hex);
      break;
    case ['5','6','7','8','9'].includes(r):
      encryptedValue = CryptoJS.SHA3(encryptedStr, {outputLength: 512}).toString(CryptoJS.enc.Hex);
      break;
    default:
      encryptedValue = encryptedStr;
  }
  
  return encryptedValue.slice(0, 16);
}

// AES加密函数(ZeroPadding)
function encrypt(key, word, isZeroPadding = true) {
  // 实现ZeroPadding
  if(isZeroPadding) {
    const blockSize = 16;
    const pad = blockSize - (word.length % blockSize);
    word += String.fromCharCode(0).repeat(pad);
  }
  
  const encrypted = CryptoJS.AES.encrypt(
    CryptoJS.enc.Utf8.parse(word),
    CryptoJS.enc.Utf8.parse(key),
    {
      mode: CryptoJS.mode.ECB,
      padding: isZeroPadding ? CryptoJS.pad.ZeroPadding : CryptoJS.pad.Pkcs7
    }
  );
  
  return encrypted.toString();
}

// 生成fs参数
function generateFs(rzData, secondHandle, backstr, as) {
  // 第一阶段fs
  const key1 = getNewKey(as);
  const fs1 = encrypt(key1, JSON.stringify(rzData), true);
  
  // 第二阶段fs(最终fs)
  const payload = {
    common_en: fs1,
    backstr: backstr
  };
  const key2 = getNewKey(as);
  const fsFinal = encrypt(key2, JSON.stringify(payload), true);
  
  return fsFinal;
}

7. 总结

某度旋转验证码v2的主要防护点:

  1. 双重加密的fs参数
  2. 动态的密钥生成算法
  3. 严格的轨迹验证
  4. 浏览器指纹检测
  5. 多阶段的验证流程

逆向关键点:

  1. 完整跟踪两阶段fs生成过程
  2. 正确实现密钥生成算法
  3. 模拟真实的用户交互轨迹
  4. 处理浏览器指纹参数
  5. 注意加密细节(模式、填充方式等)
某度旋转验证码v2逆向分析教学文档 1. 验证码概述 某度旋转验证码v2是一种基于用户交互行为的验证系统,主要包含以下特点: 采用旋转滑块形式 使用AI生成的底图(非旧版风景图) 包含多重加密机制 加入了浏览器指纹验证 验证流程分为多个接口交互 2. 验证码流程分析 2.1 接口交互流程 init接口 - 初始化验证码 请求参数: ver : 固定值"1" _ : 13位时间戳 refer : 网站URL ak : 固定值(盾ID,不同网站不同) 响应参数: as : 后续加密使用 tk : 后续请求使用 style接口 - 获取验证码样式 请求参数: tk : init接口返回 _ : 时间戳 响应参数: path : 旋转验证码底图URL backstr : 生成fs参数的关键部分 log接口 - 提交验证结果 请求参数: ak : 盾ID tk : init接口返回 as : init接口返回 fs : 加密参数(需逆向) fuid : 浏览器指纹 urlsubmit接口 - 最终提交 请求参数: ds : log接口返回 tk : log接口返回 url : 提交的链接地址 2.2 验证结果判断 验证码未转正:响应 op 值为3 验证码转正:响应 op 值为1 提交成功: {"over":0, "status":0} 验证码信息有误: {"status":101} 未输入提交链接: {"status":2} 未添加cookies: not allowed 3. 关键参数逆向分析 3.1 fs参数生成流程 fs参数生成分为两个阶段: 第一阶段fs生成 this.rzData : 包含backstr及鼠标轨迹等参数 this.secondHandle : 主要包含as参数 关键参数 ac_c (旋转比例)计算: this.distance : 滑动的距离 e : 固定值290(滑动条最大长度) 第二阶段fs生成(最终fs) 3.2 加密密钥生成 密钥生成函数 getNewKey(as) : 3.3 加密函数分析 加密函数 encrypt 采用AES加密,与旧版区别: 密钥生成方式不同: 旧版: key = as + "appsapi2" 新版: key = getNewKey(as) (as+"appsapi2"加密后取前16位) 填充方式不同: 旧版:PKCS7 新版:ZeroPadding 加密模式:ECB(电子码本模式) 4. 浏览器指纹fuid分析 fuid特点: 不同浏览器值不一致 相同浏览器短时间内不变 过一段时间会变化 由user-agent、canvas、plugins等浏览器属性构成 生成位置: fingerprint.js 文件 F 方法: encodeURIComponent() U 方法:AES加密(ECB模式,PKCS7填充,固定key) 5. 模拟注意事项 轨迹模拟 : 不能直接固定,需模拟构造 校验相对严格 轨迹中有重要参数 识别模型 : 底图已改为AI生成(非旧版风景图) 需要重新训练识别模型 加密实现 : 需完整实现两阶段fs生成 注意密钥生成规则 使用正确的加密模式和填充方式 6. JavaScript实现示例 7. 总结 某度旋转验证码v2的主要防护点: 双重加密的fs参数 动态的密钥生成算法 严格的轨迹验证 浏览器指纹检测 多阶段的验证流程 逆向关键点: 完整跟踪两阶段fs生成过程 正确实现密钥生成算法 模拟真实的用户交互轨迹 处理浏览器指纹参数 注意加密细节(模式、填充方式等)