首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【验证码逆向专栏】某奇艺滑块验证码逆向分析

【验证码逆向专栏】某奇艺滑块验证码逆向分析

原创
作者头像
K哥爬虫
发布2025-08-18 18:11:33
发布2025-08-18 18:11:33
5800
代码可运行
举报
文章被收录于专栏:Python 爬虫Python 爬虫
运行总次数:0
代码可运行
EGAqIQ.png
EGAqIQ.png

声明

本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!

本文章未经许可禁止转载,禁止任何修改后二次传播,擅自使用本文讲解的技术而导致的任何意外,作者均不负责,若有侵权,请在公众号【K哥爬虫】联系作者立即删除!

前言

近期分析了亚马逊、某手相关的验证码,上周又有粉丝提问关于某奇艺相关的验证码,说该站一直过不去,提示异常,实在找不出是哪的问题,那么趁热打铁,我们本篇就对该站进行逆向分析:

EEsLhQ.jpg
EEsLhQ.jpg

逆向目标

  • 目标:CDK 兑换详情页滑块验证码全参数
  • 地址:aHR0cHM6Ly92aXAuaXFpeWkuY29tL2ppaHVvbWEuaHRtbA==

抓包分析

进入 cdk 兑换页面,频繁点击兑换,弹出验证码,第一个接口为 initToken.action 会返回一个 token,后续接口会用到:

EGKXJa.png
EGKXJa.png

紧接着经过 sbox_init_key 返回了 sidsr,请求参数有 secure 拼接加密需要解决:

EGgLoI.png
EGgLoI.png

然后是 verifycenter/initpage 获取验证码图片,同样请求参数以及返回值解密需要处理:

EGhalB.png
EGhalB.png

最后是验证接口,需要解决 cryptSrcData 以及返回值解密,cryptVersion 同上:

EG89Ts.png
EG89Ts.png

逆向分析

sbox_init_key 分析

首要分析的就是 init_key 接口,需要逆向的参数就是 secure ,从堆栈进入 /verifycenter.js 文件,在 initSDK 处,发现 secure 参数:

EGx7Bb.png
EGx7Bb.png

其由 r[_0x444a("0x84e")]() 生成,进入后发现其由 getSecure 方法生成,如下:

EGxEbe.png
EGxEbe.png

x、a 生成则是直接返回的变量,说明在初始化的时候就已经完成了:

EGxQRP.png
EGxQRP.png

那么生成位置必然就在上方的不远处,定位到后下断点刷新页面,发现成功断下,都是调用 o.getRandom(64, c) 这个方法生成的,逻辑复现如下:

代码语言:javascript
代码运行次数:0
运行
复制
function generateRandomString(length = 32) {
  return crypto.randomBytes(length)
    .toString('base64')
    .replace(/[+/=]/g, '')
    .slice(0, length);
}
function get_initkey(){
	e = generateRandomString(64)
	i = generateRandomString(32)
	return [e, i]
}
EGxNZw.png
EGxNZw.png

接着分析 t 通过调用 t = e[_0x444a("0x7be")](x["hexEncode"]()) 完成生成,x 为上文随机值,那么它必然魔改了 String 方法,通过 x["hexEncode"]() 生成 hex 值,单步跟进,如下:

EGxuq6.png
EGxuq6.png

将这个 String 方法整体扣下即可,接着分析 e[_0x444a("0x7be")] 方法,单步跟进:

EGxwDO.png
EGxwDO.png

其生成逻辑如下:

代码语言:javascript
代码运行次数:0
运行
复制
s[_0x444a("0x85d")](_);
var o = new e;
o.setPrivateKey(r);
var c = {
    encrypt: function f(x) {
        return function a(x) {
            return function i(x) {
                for (var a = "", t = 0; t < x.length; t++) {
                    var e = x.charCodeAt(t)[_0x444a("0x18")](16);
                    a += 1 == e[_0x444a("0x5")] ? "0" + e : e
                }
                return a
            }(n[_0x444a("0x858")](x))
        }(function t(x) {
            return s[_0x444a("0x7be")](x)
        }(function e(x) {
            for (var a = [], t = 0; t < x[_0x444a("0x5")]; t += 2)
                a[_0x444a("0xc")](parseInt(x[_0x444a("0x652")](t, 2), 16));
            return a
        }(x)))
    },

将 s 模块扣下,如果部分扣错则会走 catch 逻辑返回 false,扣的时候可以把 catch 放开,这样方便定位报错,整体扣下基本在 3000 行以内,s 模块也可以直接用库,但是要注意接收的是数组,需要在调用 s[_0x444a("0x7be")](x) 时将明文用 fromCharCode 进行处理一下,至此 s 模块就分析完毕了,最终就是调用 f[_0x444a("0x866")](s, n, a, t) 完成验签加密,将最后的这个函数扣下即可。

至此 box_init_key 接口就分析完毕:

EGxruI.png
EGxruI.png

initpage 分析

该接口是获取图片的接口,cryptVersion 参数由上文接口返回的 sid 组成,cryptSrcData 为主要分析对象,全局搜索定位到如下:

EGxtOV.png
EGxtOV.png

持续跟进,发现套了 5、6 层:

EGxziL.png
EGxziL.png

加密由以下函数生成:

代码语言:javascript
代码运行次数:0
运行
复制
var e = f[_0x444a("0x86f")](x);
return e[_0x444a("0x297")] ? (t[_0x444a("0x13")] = f.signForEncrypt(e.data),

再跟:

EGxClJ.png
EGxClJ.png

进入到 _[_0x444a("0x7be")] 后,继续跟进,最终由这部分生成:

EGxJVG.png
EGxJVG.png

但是此时 key 已成生成,说明 key 很有可能在初始化的时候就已经生成了,还是在附近寻找,发现生成位置如下:

EGxXXB.png
EGxXXB.png
代码语言:javascript
代码运行次数:0
运行
复制
generateAESKey: function(x) {
                                    return u.setSR(x),
                                    _ = o.sha256(e)[_0x444a("0x652")](0, 4) + o[_0x444a("0x856")](i)[_0x444a("0x652")](0, 8) + o[_0x444a("0x856")](n).substr(0, 4),
                                    u[_0x444a("0x857")](),
                                    _
                                }

主要是由刚刚我们生成的二轮随机密钥,以及上文接口返回的 sr 参数经过签名运算生成,扣下复现即可。最终加密后再和 sign 签名函数完成组装:

EGxnTt.png
EGxnTt.png

至此,cryptSrcData 分析就结束了。接口响应成功后,返回的是密文的形式,对于这种返回值加密,直接定位 XHR 部分:

EGxIhb.png
EGxIhb.png

找到他的处理方法,解密必然就在这些函数里面,最终分析后它调用 catch 部分完成解密:

EGxMYe.png
EGxMYe.png

最终解密部分依旧嵌套,和加密逻辑基本相似,这里不做分析了,依旧用初始化的随机值以及上文接口返回的参数进行解密:

EGxfdP.png
EGxfdP.png

box_init_key 接口与获取图片接口是相关联的,如果 init 接口的参数不对,那么获取图片的接口返回的密文长度很短,解密也会失败,这里多在浏览器,替换值对比,就可以少走很多弯路。

verify 接口

验证接口和上个接口加密是基本一致的,依旧还是俩个随机数和 sr 参数进行加密,唯一不同的就是需要轨迹 riskData

EGxsww.png
EGxsww.png

轨迹这里校验贝塞尔,经过测试一、三阶贝塞尔是过不去的(也有可能是写的不对)。

轨迹不通过会提示:

  • {'code': 'B00008', 'msg': '行为校验异常,请重试', 'data': '10025840dbe54ef7aa8bfaeecc73961f'}

坐标错误提示:

  • {'code': 'B00006', 'msg': '校验失败,请重试', 'data': '100252724ccc4741be8acf2dfb51bf9d'}

最终用的是变速的方法进行通过的:

EGx6iO.png
EGx6iO.png

后期如果有小伙伴在这里卡住了,星球中会提供相关代码以供参考,最终我们将加密全部整合,即可通过。

结果展示

EGx2O6.png
EGx2O6.png

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 声明
  • 前言
  • 逆向目标
  • 抓包分析
  • 逆向分析
    • sbox_init_key 分析
    • initpage 分析
    • verify 接口
    • 结果展示
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档