
某象「刮刮乐」验证码分析本文为技术分析探讨验证码的交互机制与数据编码方式。一、这是什么验证码常见的验证码无非是滑块、点选、旋转。但某象有一种比较少见的类型——刮刮乐Scratch。交互过程页面展示一张被打乱的图片你需要在图片上反复刮擦直到刮出下方隐藏的内容系统判定你是否刮在了正确的位置。整个交互数据流分三步Step 1: 请求题目 → 服务器返回 {sid, type:2, 混淆图URL} Step 2: 还原图片 → 找到目标位置 Step 3: 生成数据 → 提交 → 拿token看上去就三步但真正有意思的藏在第二步和第三步里面。二、请求参数概览获取题目GET /api/a的关键参数参数含义备注ak应用标识固定值c设备指纹 token会动态过期不是固定值jsvSDK版本号目前是 5.1.53cid场景ID刮刮乐固定为 72556577aid会话标识每轮随机生成提交答案POST /api/v3的关键参数参数含义ac核心参数sid第一步返回的会话IDAPI 交互本身并不复杂。真正的难点是两个问题图片里的目标在哪以及ac 这个几百字符的字符串到底是什么。三、图片是怎么被混淆的3.1 混淆方式某象返回的图被纵向切成 32 个竖条strip打乱了顺序。人眼完全无法辨认里面的内容。有意思的是还原密钥直接嵌在图片URL里https://static.xxx.com/picture/xxx/abc123def456.png └─── hash_data ───┘文件名去掉.png后缀就是这个 hash 字符串。3.2 还原思路核心是一个哈希 → 排列映射的过程——URL 文件名作为种子通过一个特定的映射算法生成 strip 的排列顺序。然后按这个排列把 strip 从混淆图里取出来按正确顺序拼回去。整个还原算法并不长但前提是你得从某象那 4000 多行混淆过的 JS 里把映射算法还原出来。这才是真正花时间的地方。还原为如下还原代码fromPILimportImagedefrestore_img(file_path,save_file_path,hash_data):defget_order(hash_value):defget_unique_num(i,used):numi%32ifnumnotinused:used.add(num)returnnumreturnget_unique_num(i1,used)used_numbersset()data[]forcharinhash_value:iord(char)unique_numget_unique_num(i,used_numbers)data.append(unique_num)returndata imageImage.open(file_path)width,heightimage.size swidth//32new_imageImage.new(RGBA,(width,height))orderget_order(hash_data)[32]k0foridxinorder:cidx*s pieceimage.crop((c,0,c16,height))new_image.paste(piece,(k,0))ks new_image.save(save_file_path,formatPNG)print(f✅ 还原完成 →{save_file_path})restore_img(img.png,output.png,hashdata )img.png 是输入图片名称output.png是还原后的图片名第三个参数是前文所讲的hash data四、怎么定位目标图片还原后需要在图里找到一个特定的目标区域。传统方案各有各的问题模板匹配泛化不了目标的外观会变边缘检测不稳定还原图背景嘈杂OCR 也不太适用目标可能不是纯文字。这种场景下深度学习目标检测是一个比较自然的选择。用 YOLO 这类模型标注几十张同类图训练一轮模型就能学会识别目标。因为不管外观怎么变目标的语义是不变的。五、AC参数到底是什么5.1 AC 不是一个简单的加密串ac encode([ 加密(刮擦行为轨迹), ← 完整的鼠标/触摸路径不是几个坐标 网格覆盖编码, ← 刮擦动作覆盖了画布上哪些区域 会话令牌绑定 ← 与本次 sid 的关联 ])5.2 前端 SDK 内部在做什么从某象前端混淆 JS 中还原出来的逻辑链路大致有六个步骤生成刮擦轨迹不是画一个矩形这么简单。需要模拟人手反复涂抹的效果——蛇形路径在矩形区域内来回扫每行有缓入缓出曲线Y 轴有微小抖动行尾偶尔冲出边界再收回时间间隔随机波动初始化行为追踪器将本次验证会话的 sid 绑定进去逐帧喂入轨迹点每个点的[x, y, t]被记录时间戳在 JS 执行时实时计算加密轨迹数据JSON 序列化 → Base64魔改字符表 → 自定义混淆 → 拼接计算刮擦覆盖数据把画布划分为网格计算每个格子的笔刷覆盖面积生成一个位图再编码为十六进制字符串。注意这个编码必须和你声称的矩形坐标自洽——对不上就拒合并打包所有加密结果合并为最终输出的 ac5.3 为什么这个设计值得琢磨这里有一个双重闭环校验的设计第一层行为轨迹本身要像人——匀速直线是机器有缓入缓出抖动偶尔冲出才有人的特征第二层轨迹覆盖的网格区域必须与你声称的矩形坐标自洽——你说刮了 (45,78) 到 (132,156) 这块那网格编码里的被覆盖格子必须确实落在这个范围内这意味着即使你找到了正确位置如果行为不像人、或者覆盖数据和坐标不自洽一样过不了。这种将行为仿真和坐标校验耦合在一起的设计比单纯的滑块验证码复杂了不止一个量级。六、实际会遇到哪些坑图片宽度不被 32 整除还原算法必须处理末尾余数否则右边 strip 会整体错位YOLO 返回的坐标不保证顺序x1 可能大于 x2需要 swap不然轨迹直接生成到反方向去设备指纹 C 值会过期它不是固定值需要通过独立的 constid 接口定期刷新否则后端直接拒绝可能返回二次验证你以为拿到 token 了结果回来的是msg: 二次验证里面是一个完整的新题目需要递归处理轨迹参数直接影响通过率缓入缓出曲线的选型、抖动幅度、冲出概率——这几个参数调不好坐标再对也过不了某象的 JS SDK 更新频繁代码结构会变今天能跑的方案明天可能需要适配如果你对以下内容感兴趣欢迎来知识星球限时九折优惠AC 参数内部逻辑的深度拆解轨迹生成的每个参数为什么这样取值、曲线选型的考量、网格覆盖编码的端到端实现设备指纹 constid 逆向研究 Canvas/WebGL/字体列表等几十个字段的组装与加密二次验证的递归处理与死循环防控机制https://t.zsxq.com/v60KZ这些内容来自真实的工程实践。星球见。声明本文为技术分析探讨验证码的工作机制。所述内容仅供学习研究。