前言
在ai还没有如今这么强大的时候,当我们遇到了防水墙滑块的时候,可能最常用的方案就是Selenium方案,甚至在早期的时候有人曾言只有自动化可以通过滑块验证码。
那么为什么会有这种说法呢?---->其实原因很简单,因为某些大厂的验证码确实很难,对于小白和经验不是很丰富的人来说,通过逆向的方式实现,这完全是一个不可能完成的挑战。
以防水墙为例来说,其中包含了vmp、webpack、高度代码混淆、控制流平坦化、僵尸代码等,这些技术的处理对于一个经验丰富的人员来说也需要很长的一个周期才能解决。
现在AI飞速发展,对于那些经验不是很丰富的人,只要对逆向有了解,也可以在AI的辅助下逆向出验证码。
一、挑战:某防水墙滑块验证码
1、什么是jsvmp
JSVMP(JavaScript Virtual Machine Protection,JS代码虚拟化保护)是一种企业级的JavaScript代码高强度加密混淆技术。
它通过将原始JS代码转换为一种特定的、自定义的字节码,并在浏览器或Node.js中运行私有的解析器,使代码反编译和逆向分析极度困难,常用于保护Web应用的关键算法。
某防水墙滑块验证码对jsvmp的应用:
1、__TENCENT_CHAOS_STACK---自定义的字节码解释器
2、字节码以大数组形式内联(数万个数字)
3、所有的 collect 和 eks 加密逻辑都在 VM 内部执行
4、逆向难度极高,需要还原整个 VM 指令集
2、webpack打包 + 变量混淆
webpack打包---模块化混淆,函数调用链难以追踪
变量混淆---单字母变量名 (a, b, c),无语义
3、随机变量名
window.KcYVdONjSbHEDgmXanKNEdRPYPMTPdOh 存储 eks,每次加载变化
二、使用AI辅助分析
1、准备工作
在正式进行分析时可以让AI写一个design.md、tasks.md、requirements.md文件,这样可以使得你的项目更加的有层次感
requirements.md---需求文档,可以根据你自己的需要来进行进一步改进,这部分AI会根据你的需求写好一个requirements.md
design.md---设计文档,AI根据需求设计出一个方案
tasks.md---任务文档,AI会根据设计文档列出下面它需要做的事
2、分析启动
1)抓包预览
通过 Chrome DevTools 抓包,核心只有 2 步:
[1] GET /cap_union_prehandle → 初始化,获取 sess + 图片配置 + PoW 挑战
[2] POST /cap_union_new_verify → 提交答案,获取 ticket
这里面的Chrome DevTools大家可能都不陌生,AI能自己调度浏览器抓包主要是基于Chrome DevTools MCP
2)prehandle 请求分析
| 参数 | 说明 | 示例 |
|------|------|------|
| aid | 应用 ID | 199999861 |
| ua | Base64 编码的 User-Agent | TW96aWxsYS81LjA... |
| lang | 语言 | zh-cn |
| entry_url | 来源页面 | https://cloud.tencent.com/... |
| subsid | 子会话 ID(递增) | 1 |
| callback | JSONP 回调名 | _aq_191730 |
3)verify 请求分析
| 参数 | 说明 |
|------|------|
| collect | TDC 加密的设备指纹 + 轨迹数据 |
| tlg | collect 字符串长度 |
| eks | TDC 生成的加密密钥信息 |
| sess | 会话标识 |
| ans | 滑块答案 JSON |
| pow_answer | PoW 计算结果 |
| pow_calc_time | PoW 计算耗时(毫秒) |
3、跟进分析JS文件
1)核心JS文件清单
| 文件 | 大小 | 作用 | 混淆程度 |
|------|------|------|---------|
| TCaptcha.js | 入口 | 加载器 | 低 |
| tcaptcha-frame.js | 207KB | 主框架逻辑 | 中(Webpack) |
| dy-ele.js | 209KB | 滑块核心逻辑 | 中(Webpack) |
| tdc.js | 78KB | 设备指纹采集 | 极高(JSVMP) |
2)混淆技术分析
dy-ele.js 混淆特征:
-
Webpack 打包,模块化结构
-
变量名混淆(单字母变量)
-
部分字符串 Base64 编码
-
可通过断点调试还原
tdc.js 混淆特征(重点):
[JavaScript] 纯文本查看 复制代码
var TENCENT_CHAOS_STACK = [];var TENCENT_CHAOS_VM = function(bytecode) { // 数万行的字节码解释器 // 无法直接阅读,需要还原 VM 指令集};__TENCENT_CHAOS_VM([12345, 67890, ...]); // 数万个数字
说实话,分析完都有哪些核心文件和对抗技术之后,如果是我自己手搓的话可能需要很长的一段时间才能搞定,但是有了AI之后,工作量就可以减轻很多了,每天花几个小时,在一两天的时间内就能搞定。
3、算法分析
1)PoW (Proof of Work) 算法
就是一个暴力搜索的md5
暴力搜索: md5(nonce + counter) === target
返回:
ans: counter,
duration: +new Date - startTime
2)ft (浏览器特征指纹) 生成
在dy-ele.js中收集环境信息
ft 是一个编码后的浏览器特征字符串,包含 50+ 项检测:
检测项列表(部分)
[JavaScript] 纯文本查看 复制代码
var features = [ "matches" in div, // Element.matches "msMatchesSelector" in div, // IE 特有 "webkitMatchesSelector" in div, // Chrome 特有 !!window.matchMedia, // 媒体查询 !!CSS.supports, // CSS 支持检测 !!document.createRange, // Range API !!window.CustomEvent, // 自定义事件 "scrollIntoView" in div, // 滚动 API !!navigator.getUserMedia, // 媒体设备 !!window.IntersectionObserver, // 交叉观察器 "ontouchstart" in window, // 触摸支持 !!window.performance, // 性能 API // ... 共 50 项];
3)TDC接口
TDC (Tencent Data Collection) 是腾讯的设备指纹采集模块,暴露以下接口:
[JavaScript] 纯文本查看 复制代码
window.TDC = {setData(data) // 设置采集数据(轨迹、指纹等)getData(flag) // 获取加密后的 collect 数据getInfo() // 返回 { info: "eks", tokenid: "数字" }clearTc() // 清除采集数据};
数据流:
1. dy-ele.js 调用 TDC.setData({ft: "浏览器特征字符串"})
2. 用户滑动过程中,TDC 自动采集鼠标轨迹
3. TDC.getData(true) 返回加密后的 collect
4. TDC.getInfo().info 返回 eks
4、补环境复现collect 和 eks 的加密算法
1)先看一下都收集了哪些环境
技术 | 具体表现 |
|------|---------|
| 浏览器指纹 | 50+ 项特征检测(ft) |
| Node.js 检测 | 检测 process、require、module 等 |
| DOM API 行为检测 | 检测 API 返回值是否符合真实浏览器 |
| performance.timing | 采集页面加载时序数据 |
| WebGL 指纹 | 显卡信息采集 |
| Canvas 指纹 | 绘图指纹采集 |
| AudioContext 指纹 | 音频指纹采集 |
2)AI辅助补环境
可能大家也或多或少的通过补环境的方案解决过js代码中加密算法的调用,但是这里面其实有一个小坑:在补环境的时候补少了肯定是不行的,但是补多了有时候也会导致算法调用失败。
自己手动挂代理去补环境的话,第一是费时费力;第二是补环境基本上都是凭借经验去补,但是具体都检测了哪些环境,又有哪些环境一定要补哪些环境不用补,哪些环境补了反而会导致算法复现失败,这些东西要确定的话最好的办法就是在js源码中一点点调试,但是这样的话工作量很大不说还很浪费时间成本
使用AI进行补环境的好处是什么?
1、AI可以在chrome中模拟执行js代码,同时收集检测的环境
2、AI在js代码本地运行报错或与页面结果差异很大时,通过对比本地环境和chrome环境来更新本地环境并进行测试
3、AI可以通过chrome中的轨迹模拟滑块的轨迹采集样点及轨迹算法
模拟事件监听器:
[JavaScript] 纯文本查看 复制代码
模拟事件监听器: javascript// 捕获 TDC 注册的事件监听器document._eventListeners = {};document.addEventListener = function(type, fn, opts) {if (!document._eventListeners[zxsq-anti-bbcode-type]) {document._eventListeners[zxsq-anti-bbcode-type] = [];}document._eventListeners[zxsq-anti-bbcode-type].push(fn);}; // 模拟鼠标轨迹function simulateMouseTrack(track) {for (var i = 0; i < track.length; i++) {var evt = { type: 'mousemove', clientX: track[zxsq-anti-bbcode-i].x, clientY: track[zxsq-anti-bbcode-i].y, timeStamp: track[zxsq-anti-bbcode-i].timestamp, // ... 完整事件属性 };// 触发 TDC 的监听器document._eventListeners['mousemove'].forEach(fn => fn(evt));}}
3)实现自动化流程
让AI将整个流程都写成代码,整个流程如下:
┌─────────────────────────────────────────────────────────────────┐
│ 防水墙滑块验证码自动化流程 │
└─────────────────────────────────────────────────────────────────┘
Step 1: 初始化请求 (prehandle)
├── GET /cap_union_prehandle
├── 参数: aid, ua(Base64), lang, entry_url, subsid, callback
├── 解析 JSONP 响应
└── 获取: sess, pow_cfg, sprite_url, bg_url, fg_elem_list
Step 2: 下载图片
├── GET /cap_union_new_getcapbysig?img_index=0 → sprite 图
└── GET /cap_union_new_getcapbysig?img_index=1 → 背景图
Step 3: 图像处理
├── 从 sprite 图裁剪滑块 (sprite_pos + size_2d)
├── OpenCV Canny 边缘检测
├── 模板匹配定位缺口位置
└── 计算滑动距离 = 缺口X - 初始X
Step 4: 轨迹生成
├── 加速阶段 (0-70% 距离)
├── 减速阶段 (70-100% 距离)
├── 微调阶段 (随机抖动)
└── 输出: [[x, y, timestamp], ...]
Step 5: PoW 计算
├── 输入: prefix + target_md5
├── 暴力搜索: md5(prefix + N) == target
└── 输出: pow_answer, pow_calc_time
Step 6: TDC 数据生成
├── 生成 ft (浏览器特征指纹)
├── 模拟鼠标轨迹事件
├── TDC.setData({ft: ft})
├── TDC.getData(true) → collect
└── TDC.getInfo().info → eks
Step 7: 提交验证 (verify)
├── POST /cap_union_new_verify
├── 参数: collect, tlg, eks, sess, ans, pow_answer, pow_calc_time
└── 响应: ticket + randstr (成功) 或 errorCode (失败)
三、总结
1、AI辅助的优势
1)处理大量的环境采集工作:浏览器特征字符串,包含 50+ 项检测
2)调用链追踪:AI可以快速定位各调用栈间的联系
3)代码还原:AI可以根据你需要的语言自动生成代码
2、AI存在的局限性
1)在模拟滑块进行滑动时,可能因为页面元素定位等限制导致无法实现模拟滑动,需要人工滑动,AI来抓包
2)AI存在幻觉现象,同时AI也可能会因为复杂的逻辑分析陷入死循环,这个时候需要人工指引方向
四、展望
AI正在飞速的发展,利用AI进行辅助逆向分析慢慢会变成趋势,让AI伴我们通行,顶峰相见!
免责声明:本文仅用于安全研究和技术交流,请遵守相关法律法规。