推广 热搜: 采购方式  滤芯  带式称重给煤机  甲带  气动隔膜泵  减速机型号  无级变速机  链式给煤机  履带  减速机 

阿里v2验证码算法逆向分析报告

   日期:2026-02-12 10:52:04     来源:网络整理    作者:本站编辑    评论:0    
阿里v2验证码算法逆向分析报告

阿里V2验证码 逆向分析报告

阅读须知

本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!擅自使用本文讲解的技术而导致的任何意外,作者均不负责,若有侵权,请在公众号联系作者立即删除

一、概述

阿里V2验证码 是一套基于设备指纹 + 行为分析的风控验证系统。本报告详细分析了其前端验证流程、加密机制和数据结构。


二、核心组件

2.1 加载的脚本

脚本
作用
AliyunCaptcha.js
主入口,初始化验证码
sg.xxx.js
动态安全脚本,设备指纹收集
feilin.xxx.js
FeiLin 指纹收集库

2.2 关键全局对象

window.AliyunCaptchaConfig// 配置 (region, prefix)window.__ALIYUN_CRYPT// 加密库 (AES, MD5, SHA1, HMAC等)window.__ALIYUN_CAPTCHA_UTILS// 工具函数window.FEILIN// 指纹收集window.captcha// 验证码实例

三、完整请求流程

3.1 初始化阶段 (页面加载)

┌──────────────────────────────────────────────────────────────────┐│ 1. Log1 请求                                                      ││    URL: cloudauth-device-dualstack.cn-shanghai.aliyuncs.com      ││    Action: Log1                                                   ││    Data: 初始设备指纹 (加密)                                       ││    响应: DeviceConfig (含加密密钥)                                 │├──────────────────────────────────────────────────────────────────┤│ 2. InitCaptchaV3 请求                                             ││    URL: {prefix}.captcha-open.aliyuncs.com                       ││    Action: InitCaptchaV3                                          ││    参数: SceneId, Language, Mode, DeviceData                      ││    响应: CertifyId, CaptchaType, DeviceConfig, StaticPath         │├──────────────────────────────────────────────────────────────────┤│ 3. UploadLog 请求                                                 ││    Action: UploadLog                                              ││    上传初始化日志                                                  │├──────────────────────────────────────────────────────────────────┤│ 4. Log2 请求                                                      ││    Action: Log2                                                   ││    Data: 详细设备指纹 (加密)                                       │└──────────────────────────────────────────────────────────────────┘

3.2 验证阶段 (用户交互)

┌──────────────────────────────────────────────────────────────────┐│ 1. 用户点击登录按钮                                               ││    → 弹出滑块验证码                                               ││    → 开始收集鼠标移动轨迹                                          │├──────────────────────────────────────────────────────────────────┤│ 2. 用户完成滑动                                                   ││    → 停止轨迹收集                                                 ││    → AES加密轨迹数据                                              ││    → AES加密环境数据                                              ││    → 生成 deviceToken                                             │├──────────────────────────────────────────────────────────────────┤│ 3. Log3 请求                                                      ││    URL: cloudauth-device-dualstack.cn-shanghai.aliyuncs.com      ││    Action: Log3                                                   ││    Data: 完整设备指纹 + 行为数据 (加密)                            │├──────────────────────────────────────────────────────────────────┤│ 4. VerifyCaptchaV3 请求                                           ││    URL: {prefix}.captcha-open.aliyuncs.com                       ││    Action: VerifyCaptchaV3                                        ││    参数: SceneId, CertifyId, CaptchaVerifyParam                   ││    响应: securityToken, VerifyCode, VerifyResult                  │└──────────────────────────────────────────────────────────────────┘

四、加密机制

4.1 AES 加密参数

基本参数:

  • • 算法: AES-128-CBC
  • • IV: 012***DEF (固定值, Hex: 303***546)
  • • Padding: Pkcs7

密钥列表:

密钥
来源
用途
c17***2e2
SDK内置
Log1 初始化数据加密
45f***397
SDK内置
deviceToken 部分数据加密
FqJ***pwb
SDK内置
deviceToken sessionId 加密
a69***919
服务器动态下发
环境数据、鼠标轨迹加密
a54***aa0
服务器动态下发
Log2/Log3 Data 字段加密

4.2 密钥解密体系

主解密密钥:

ACCESS_SEC = "FqJ***pwb"IV = "012***DEF"算法 = AES-128-CBC

SDK内置密钥解密表:

加密配置
加密值 (Base64)
解密后
用途
WEB_AES_SECRET_KEY.FLAG
k+1RW0***6Gas=c17***2e2
Log1 初始化数据加密
WEB_AES_SECRET_KEY.REQ
8KmHIQs***xss0=45f***397
deviceToken 部分数据加密
WEB_AES_SECRET_KEY.RES
9NhnQQ***CgrM=87f***da7
服务器响应解密
WEB_AES_SECRET_KEY.UPLOAD
+fR9tYzlKFr***bJiMfA=a54***aa0
Log2/Log3 Data 字段加密
WEB_AES_SECRET_KEY.PREID
xLLw/***3ds42B0=75a***802
预初始化数据加密
ACCESS_KEY.ID
tBwmiXX***mDCbo=LTAI***w72p
Device API AccessKeyId
ACCESS_KEY.SECRET
9U6Kg***MVBg=fpOK***IRcX
Device API AccessKeySecret
SALT
NLAoq***zA==daye,raolewoba!
盐值
SESSION_ID_SALT
X1y5Vstb***a0A==8449449787
SessionID 盐值

解密流程:

from Crypto.Cipher import AESimport base64defdecrypt_config(encrypted_b64):    key = b'FqJ***pwb'    iv = b'012***DEF'    cipher = AES.new(key, AES.MODE_CBC, iv)    data = base64.b64decode(encrypted_b64)    decrypted = cipher.decrypt(data)# 去除 PKCS7 填充    padding_len = decrypted[-1]return decrypted[:-padding_len].decode('utf-8')

4.3 DeviceConfig 解密

解密密钥WEB_AES_SECRET_KEY.RES = 87f***da7

解密后格式 (# 分隔):

Base64(key)#Base64(switch)#sessionId#version#plugin1#plugin2#plugin3#timestamp#ip

示例:

解密后: YTY5OGQ1NmU4ZjIyMzkxOQ==#MQ==#ab0***ae1-h-...#1.3.3/feilin077...####1768709118474#113.83.154.89字段解析:- key: Base64解码后 = a69***919 (后续 AES 加密密钥)- switch: 1- sessionId: ab0***ae1-h-timestamp-fingerprint- version: SDK版本- timestamp: 时间戳- ip: 客户端 IP

4.3 请求签名

签名算法: HMAC-SHA1 (Base64编码输出)

签名字符串构建:

HTTPMethod + "&" + urlencode("/") + "&" + urlencode(sortedParams)

sortedParams 构建规则:

  1. 1. 将所有请求参数 (除 Signature 外) 按参数名 ASCII 升序排列
  2. 2. 将每个参数的 key=value 进行 URL 编码
  3. 3. 用 & 连接所有参数

4.4 API 密钥

API
AccessKeyId
AccessKeySecret
Captcha API
LTAI***xmvTdYSKfs***F9r89koz
Device API
LTAI5***GQw72pfpOKzILEa***gIRcX

Captcha API ({prefix}.captcha-open.aliyuncs.com):

  • • 用于: InitCaptchaV3, UploadLog, VerifyCaptchaV3

Device API (cloudauth-device-dualstack.cn-shanghai.aliyuncs.com):

  • • 用于: Log1, Log2, Log3

重要: 签名时密钥末尾需要加 &,即 AccessKeySecret + "&"


五、数据结构

5.1 CaptchaVerifyParam

{"sceneId":"1wpbfo15","certifyId":"2xUrMCZFaL","deviceToken":"V0VCI2FiMDM0ZWMw...Base64...","data":"JRMnX3A3XiIh...AES加密的轨迹数据..."}

5.2 deviceToken 结构

Base64解码后格式:WEB#[sessionID]#[AES加密的设备数据]#[版本号]#[MD5校验]示例:WEB#ab0***ae1-h-1768707464440-8e6***052#OsKhPZ+K63...#163#ad1***12c字段说明:- WEB: 客户端类型标识- sessionID: appKey-h-timestamp-fingerprint- 加密数据: AES加密的设备指纹- 版本号: 数据版本- MD5校验: 数据完整性校验

5.3 鼠标轨迹数据 (data 字段解密后)

{"mousemove":[{"x":131,"y":596,"t":82},{"x":149,"y":534,"t":133},{"x":179,"y":494,"t":163},    ...]}
字段
类型
说明
x
int
鼠标X坐标
y
int
鼠标Y坐标
t
int
相对时间戳(ms)

5.4 环境数据格式 (99个字段,#分隔)

W.10050#####Win32#Chrome#143.0.0.0#...#fingerprint#...#Windows#10#...#IP#...#screen#...

关键字段索引:

索引
字段
示例值
0
版本
W.10050
5
平台
Win32
6
浏览器
Chrome
7
浏览器版本
143.0.0.0
20
字体数量
61
32
设备指纹MD5
862***472
36
操作系统
Windows
37
系统版本
10
42
IP地址
113.83.154.89
47
屏幕分辨率
1440*3440
67
场景名称
saf-captcha
77
CertifyId
2xUrMCZFaL
88
检测标志
Base64编码的检测结果

5.5 检测标志解码

Base64: MCMwIzAjMCMwIzAjMCMwIzAjMSMwIzAjMCMwIzAjMCMwIzAjMCMwIzEjMCMxMTExMTExMDExMTExMTExMTExMTExMTExMQ==解码后: 0#0#0#0#0#0#0#0#0#1#0#0#0#0#0#0#0#0#0#0#1#0#11111110111111111111111111每个标志位表示一种环境检测结果 (0=正常, 1=异常)

六、验证响应

6.1 成功响应

{"RequestId":"7D44D70E-97A5-409A-879C-B103CE10A56A","Message":"success","HttpStatusCode":200,"Code":"Success","Success":true,"Result":{"securityToken":"6oOo7e72nA61uVLiZVKiLfBvot4lJ8pCirs9CNqYOlcDrTP1+FXxhlBexe0GIX8N...","VerifyCode":"T001","VerifyResult":true,"certifyId":"2xUrMCZFaL"}}

6.2 success 回调数据

{"certifyId":"2xUrMCZFaL","sceneId":"1wpbfo15","isSign":true,"securityToken":"6oOo7e72nA61uVLiZVKiLfBvot4lJ8pCirs9CNqYOlcDrTP1..."}

七、请求参数生成

7.1 Log1 Data 生成

Step 1: 加密初始化信息  明文: "W.10001.c#saf-captcha##captcha-front#coooqf#cn"  格式: version#appName#sceneId#mode#prefix#region  密钥: FLAG (c17***2e2)Step 2: 组装并加密  明文: "appKey#W#Step1密文#W20220202#CLOUD#"  密钥: REQ (45f***397)

7.2 InitCaptchaV3 DeviceData 生成

与 Log1 相同格式,但 sceneId 有值,mode 为 "captcha-normal"

7.3 SessionId 生成

格式: appKey-h-timestamp-fingerprint示例: ab0***ae1-h-1768709118471-93f***625fingerprint: UUID v4 (去除连字符)Python: uuid.uuid4().hex

7.4 Log2/Log3 Data 生成

外层 (用 UPLOAD 密钥 a54***aa0 加密):  appKey#W#encEnvData#W20220202#CLOUD#num1#num2#base64Database64Data 解码后:  sessionId#encryptedEnvData#field3#field4#field5#field6encryptedEnvData (用动态密钥加密):  54字段环境数据,#分隔

7.5 deviceToken 生成

Base64编码前格式:  WEB#sessionId#encryptedData#version#md5Checksum示例:  WEB#ab034ec...#2qqVQzPgNt/58kND...#209#40d***ca2

7.6 环境数据字段 (54个)

索引
字段
示例
0
版本
W.10050
4
渲染引擎
Blink
5
平台
Win32
6
浏览器
Chrome
7
浏览器版本
143.0.0.0
9
MIME类型
[application/pdf,text/pdf]
12
WebGL厂商
Google Inc. (NVIDIA)
13
WebGL渲染器
ANGLE...
19
Canvas指纹MD5
b8c***7c9
20
字体数量
61
22
CPU核心数
8
32
设备指纹MD5
862***472
36
操作系统
Windows
37
系统版本
10
40
语言
zh-CN
41
时区
Asia/Shanghai
42
IP
113.83.154.89
47
屏幕分辨率
1440*3440

八、VerifyCaptchaV3 data 字段完整分析 (✅ 已解决)

8.1 data 字段生成流程

data 字段使用 VM 虚拟机加密,不是标准 AES。完整流程如下:

步骤1: 生成 TrackList(鼠标轨迹数据)        │        ▼步骤2: encryptTrackData(TrackListJSON) → trackId (32位hex)        │  使用 VM 函数: j(0, [], F, G, {r:1}, [json, "0000"])        ▼步骤3: 构建 trackData = {TrackList, TrackStartTime, VerifyTime, arg}        │        ▼步骤4: originalData = trackId + JSON.stringify(trackData)        │        ▼步骤5: compressed = pako.deflate(originalData)        │        ▼步骤6: o0 = Base64.encode(compressed)        │        ▼步骤7: data = vmEncrypt(o0, encryptKey)        │  使用 VM 函数: j(0, [], L, D, {r:1}, [o0, key])        ▼最终: data 字段 (Base64编码, ~1580字符)

8.2 TrackList 结构

const trackList = {"mc""x,y,time, ,flag|...",  // 鼠标点击 (mouseclick)"tc""",                      // 触摸点击 (touchclick)"mu""x,y,time, ,flag|...",  // 鼠标释放 (mouseup)"te""",                      // 触摸结束 (touchend)"mp""x,y,time,flag|...",    // 鼠标移动 (mousemove) - 主要轨迹"tmv""",                     // 触摸移动 (touchmove)"mm""x,y,time,flag|...",    // 鼠标滑动阶段轨迹"ks""",                      // 键盘事件"fi""time,type,flag|...",   // 焦点事件"startTime"1768715528000,    // 轨迹开始时间戳"si""1960,3440,1083,..."// 屏幕信息}

8.3 trackId 生成

const trackListForId = {"TrackList": trackList,"TrackStartTime": trackStartTime,"VerifyTime": verifyTime};// VM 函数 j 使用 F/G 字节码生成 32 位 hex 字符串const trackId = j(0, [], F, G, {r:1}, [JSON.stringify(trackListForId), "0000"]);// 返回示例: "a1b***f01"

8.4 VM 字节码位置 (sg.js)

数组
位置
大小
用途
V
209061
~500
主加密常量表
L
209556
~15000
vmEncrypt 字节码
F
204961
~3000
trackId 生成字节码
G
-
~280
trackId 常量表
D
-
~125
vmEncrypt 常量表

8.5 VM 加密密钥

const vmEncryptKey = '3e6***913';  // 固定 16 字符密钥

8.6 VM 操作码 (部分)

操作码
功能
说明
0
属性访问
h[l]
5
递归调用
调用 VM 自身
6
字符串拼接
h + l
8
取模
h % l
16
条件跳转
if false jump
45
前缀递增
++x
48
位运算
左移/右移
49
位与
h & l
55
返回
return
56
位或
h | l

8.7 Canvas 指纹 MD5 生成逻辑

环境数据第 19 字段,示例值:b8c***7c9

生成流程:

// 1. 创建 Canvas (240x60)var canvas = document.createElement('canvas');canvas.width = 240;canvas.height = 60;var ctx = canvas.getContext('2d');// 2. 绘制文本1 - Times New Romanctx.font = '14.6667px "Times New Roman"';ctx.fillStyle = '#006699';ctx.fillText('Cwm fjordbank gly ?'215);// 3. 绘制文本2 - Arial 半透明ctx.font = '24px Arial';ctx.fillStyle = 'rgba(102, 204, 0, 0.2)';ctx.fillText('Cwm fjordbank gly ?'445);// 4. 绘制矩形ctx.fillStyle = '#ff6600';ctx.fillRect(10016220);// 5. 获取 dataURL 并计算 MD5var dataUrl = canvas.toDataURL();var canvasMd5 = MD5(dataUrl);  // 实际输入是 RGB 颜色数组 JSON

实际输入:系统 CSS 颜色值数组的 JSON(约 799 字符)

["rgb(0, 0, 0)","rgb(0, 0, 0)","rgb(0, 102, 204)",...]

8.8 设备指纹 MD5 生成逻辑

环境数据第 32 字段,示例值:862***472

生成流程:

// 1. 创建 WebGL Canvas (122x110)var canvas = document.createElement('canvas');canvas.width = 122;canvas.height = 110;var gl = canvas.getContext('webgl');// 2. 绘制 WebGL 图形并检测 winding 规则var winding = ctx.isPointInPath(66'evenodd') === false;// 3. 获取 Canvas 图像数据var geometry = canvas.toDataURL();// 4. 构建 JSON 对象并计算 MD5var deviceData = {"winding"true,"geometry""data:image/png;base64,iVBORw0KGgo..."};var deviceMd5 = MD5(JSON.stringify(deviceData));  // 约 20188 字符

8.9 deviceToken 校验 MD5

输入格式

WEB#sessionId#encryptedData#version#salt

示例

WEB#ab0***ae1-h-1768717322760-54b***829#Fuijq6okqtLAZhIpSySrZnGKXyZ/lBeZ7BUApHhyv4w...#169#daye,raolewoba!

固定盐值daye,raolewoba!


九、关键发现

9.1 安全机制

  1. 1. 密钥动态下发 - AES密钥由服务器返回,不是固定值
  2. 2. 设备指纹 - 收集大量浏览器/系统特征
  3. 3. 行为分析 - 记录完整鼠标移动轨迹
  4. 4. 时间戳 - 多个时间点校验
  5. 5. 环境检测 - 检测自动化工具/调试器

9.2 潜在弱点

  1. 1. IV 固定 - 012***DEF 是固定值
  2. 2. 加密算法已知 - AES-128-CBC
  3. 3. 数据格式清晰 - 字段结构可解析

十、调试方法

10.1 调试工具

  • • browser-connect MCP: 浏览器连接、网络监控、控制台日志
  • • mcp-js-debugger: 断点调试、表达式求值

10.2 Hook 代码示例

// Hook AES 加密var origAES = window.__ALIYUN_CRYPT.AES.encrypt;window.__ALIYUN_CRYPT.AES.encrypt = function(msg, key, cfg) {console.log('[AES]', {msg: msg?.toString?.().substring(0200),keywindow.__ALIYUN_CRYPT.enc.Hex.stringify(key),iv: cfg?.iv ? window.__ALIYUN_CRYPT.enc.Hex.stringify(cfg.iv) : null  });return origAES.apply(thisarguments);};// Hook HmacSHA1 - 捕获 AccessKeySecretvar origHmac = window.__ALIYUN_CRYPT.HmacSHA1;window.__ALIYUN_CRYPT.HmacSHA1 = function(msg, key) {var keyStr = '';try {if (typeof key === 'string') keyStr = key;elseif (key?.words) keyStr = window.__ALIYUN_CRYPT.enc.Utf8.stringify(key);  } catch(e) {}console.log('[HMAC] Key:', keyStr);  // AccessKeySecret + "&"return origHmac.apply(thisarguments);};

10.3 签名生成示例 (Python)

import hmacimport hashlibimport base64import urllib.parsedefcompute_signature(params, access_key_secret):"""计算 API 签名"""# 1. 移除 Signature 参数并排序    sorted_params = sorted([(k, v) for k, v in params.items() if k != 'Signature'])# 2. 构建规范化查询字符串    query_string = '&'.join([f"{urllib.parse.quote(k, safe='')}={urllib.parse.quote(str(v), safe='')}"for k, v in sorted_params])# 3. 构建待签名字符串    string_to_sign = f"POST&{urllib.parse.quote('/', safe='')}&{urllib.parse.quote(query_string, safe='')}"# 4. 计算签名 (密钥 = AccessKeySecret + "&")    sign_key = (access_key_secret + '&').encode('utf-8')    signature = hmac.new(sign_key, string_to_sign.encode('utf-8'), hashlib.sha1).digest()return base64.b64encode(signature).decode('utf-8')


十一、免责声明

本报告仅供安全研究和学习目的,请勿用于非法用途。本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!擅自使用本文讲解的技术而导致的任何意外,作者均不负责,若有侵权,请在公众号联系作者立即删除

 
打赏
 
更多>同类资讯
0相关评论

推荐图文
推荐资讯
点击排行
网站首页  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报  |  皖ICP备20008326号-18
Powered By DESTOON