【验证码逆向专栏】某采购网,360 磐云盾、文字点选验证码逆向分析
字数 1427 2025-08-29 22:41:38
360磐云盾及文字点选验证码逆向分析教学文档
1. 目标网站分析
1.1 目标网站
- 网站类型:政府采购网
- 防护系统:360磐云盾
- 验证码类型:文字点选验证码
1.2 360磐云盾简介
- 产品介绍:360网站云防护系统
- 功能特点:
- 所有访问请求先经过防御平台过滤
- 实现源站隐身,不暴露在公网
- 依托360全面攻击样本库实时甄别恶意流量
2. 逆向流程分析
2.1 初始访问流程
-
首次访问
procurementList.html:- 响应返回HTML的title为"请稍候... | 磐云"
- 响应cookie:
PYCCV
-
第二次请求:
- 携带参数
answer和cookiePYCCV - 响应状态码302重定向
- 响应cookie:
PYCCS
- 携带参数
-
第三次请求:
- 携带cookie
PYCCS - 获取正确HTML页面
- 响应cookie:
xincaigou
- 携带cookie
2.2 关键参数answer分析
answer参数是动态变化的,不是通过常规JS算法生成,而是通过eval函数输出的自执行JS代码生成。
2.2.1 自执行函数结构
eval(function(p, a, c, k, e, d) {
e = function(c) {
return (c < a ? "" : e(parseInt(c / a))) +
((c = c % a) > 35 ? String.fromCharCode(c + 29) : c.toString(36))
};
if (!''.replace(/^/, String)) {
while (c--) d[e(c)] = k[c] || e(c);
k = [function(e) { return d[e] }];
e = function() { return '\\w+' };
c = 1;
};
while (c--) if (k[c]) p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]);
return p;
}(...))
2.2.2 参数说明
p: 被编码的JavaScript代码a: 基数(58),用于解码字符串c: 关键字数量(58)k: 关键字数组e: 解码函数d: 存储解码后的键值对
2.2.3 解码过程
-
e函数功能:- 递归将c除以基数a生成高位字符
- 取余后,若余数c%a > 35转为ASCII字符,否则转为base36字符串
-
字符串替换:
- 构建字典d,将混淆字符还原为原始关键字
- 将混淆代码字符串p中的占位符替换为实际值
2.2.4 还原后的算法
var _$ = ['\x23\x63\x68\x61\x6c\x6c\x65\x6e\x67\x65', '\x23\x77\x61\x66\x5f\x61\x6e\x73\x77\x65\x72', '\x23\x43\x68\x61\x6c\x6c\x65\x6e\x67\x65\x46\x6f\x72\x6d'];
$(_$[0])["\x73\x68\x6f\x77"]();
$(function() {
setTimeout(function() {
var x06dd1a = {};
var x0fcad9;
var x08c924 = 0x14;
var x01c264 = navigator["\x75\x73\x65\x72\x41\x67\x65\x6e\x74"]["\x74\x6f\x4c\x6f\x77\x65\x72\x43\x61\x73\x65"]();
x08c924 = x08c924 * 0x0f;
(x0fcad9 = x01c264["\x6d\x61\x74\x63\x68"](/msie ([\d.]+)/)) ? x06dd1a["\x69\x65"] = x0fcad9[0x1] :
(x0fcad9 = x01c264["\x6d\x61\x74\x63\x68"](/firefox\/([\d.]+)/)) ? x06dd1a["\x66\x69\x72\x65\x66\x6f\x78"] = x0fcad9[0x1] :
(x0fcad9 = x01c264["\x6d\x61\x74\x63\x68"](/chrome\/([\d.]+)/)) ? x06dd1a["\x63\x68\x72\x6f\x6d\x65"] = x0fcad9[0x1] :
(x0fcad9 = x01c264["\x6d\x61\x74\x63\x68"](/opera.([\d.]+)/)) ? x06dd1a["\x6f\x70\x65\x72\x61"] = x0fcad9[0x1] :
(x0fcad9 = x01c264["\x6d\x61\x74\x63\x68"](/version\/([\d.]+).*safari/)) ? x06dd1a["\x73\x61\x66\x61\x72\x69"] = x0fcad9[0x1] : 0x0;
x08c924 = x08c924 + 0x20;
if (x06dd1a["\x69\x65"] || x06dd1a["\x66\x69\x72\x65\x66\x6f\x78"] || x06dd1a["\x63\x68\x72\x6f\x6d\x65"] || x06dd1a["\x6f\x70\x65\x72\x61"] || x06dd1a["\x73\x61\x66\x61\x72\x69"]) {
x08c924 = (x08c924 * 0x3 + 0x7);
if (x08c924 < 0x7b) x08c924 = x08c924 + 0x929;
var x0b515d = $(_$[1]);
if (x08c924 > 0x929) x08c924 = Math["\x66\x6c\x6f\x6f\x72"](x08c924 / 0x7b);
x0b515d["\x76\x61\x6c"](x08c924);
$(_$[2])["\x73\x75\x62\x6d\x69\x74"]()
}
}, 0x3e8)
});
2.2.5 算法逻辑解析
-
浏览器信息检测:
- 检测浏览器类型(IE/Firefox/Chrome/Opera/Safari)
- 获取浏览器版本号
-
计算answer值:
answer = 20; // 初始值0x14 answer = answer * 15; // 20*15=300 answer += 32; // 300+32=332 if (检测到浏览器信息) { answer = (answer * 3) + 7; // 332*3+7=1003 if (answer < 123) { answer += 2345; // 下限保护 } if (answer > 2345) { answer = Math.floor(answer / 123); // 上限保护 } }
2.3 文字点选验证码分析
2.3.1 验证码流程
- 触发条件:翻页时触发
- 接口调用:
/captcha.get.svc:获取验证码- 返回参数:
originalImageBase64:验证码图片secretKey:密钥token:令牌wordList:需要点击的文字列表
- 返回参数:
/captcha.check.svc:验证验证码
2.3.2 关键参数分析
-
clientUid:- 从localStorage中读取
- 生成方式:UUID
- 存储位置:
localStorage.setItem("point", uuid)
-
pointJson:- AES加密(ECB模式)
- key:
secretKey(从接口返回) - 加密内容:点选的坐标
-
captchaCheckFlag:- 生成算法:
var captchaVerification = aesEncrypt( _this.backToken + JSON.stringify(_this.checkPosArr), _this.secretKey )
- 生成算法:
3. 逆向技术总结
3.1 关键点总结
-
360磐云盾防护:
- 三层请求流程
- 动态
answer参数验证
-
验证码系统:
- 文字点选验证码
- 基于AES的加密验证
3.2 逆向技巧
-
对于混淆代码:
- 分析自执行函数结构
- 理解字符串编码方式
- 逐步还原算法逻辑
-
对于验证码:
- 抓包分析接口调用流程
- 定位关键参数生成位置
- 分析加密算法和密钥来源
-
调试技巧:
- 合理使用断点调试
- 关注localStorage/cookie变化
- 搜索关键参数名定位代码
4. 防御建议
4.1 对于网站开发者
- 加强关键参数的保护
- 增加代码混淆复杂度
- 实现动态密钥机制
4.2 对于逆向研究者
- 仅用于学习研究
- 遵守相关法律法规
- 尊重网站防护机制