极验4参数分析

目标链接

'aHR0cHM6Ly9ndDQuZ2VldGVzdC5jb20v'

接口分析

  1. 开发者人员工具进行抓包,刷新页面,抓到了一个名为 load?captcha_id=xxx 的包,Query String Parameters 包含了一些参数
    在这里插入图片描述
    captcha_id:验证码 id,固定值,由 adaptive-captcha-demo.js 文件生成,后文分析;
    challenge:动态变化,由 gtc4.js 文件生成,后文分析;
    client_type:表示 web 端;
    risk_type:验证码类型,例如滑块为 slide,无感为 ai;
    lang:语言;
    callback:geetest_ + 时间戳。
    注意这里可以发现参数challenge已经不是像2代、3代那样通过接口生成了,而是相当于一个uuid的生成;同时底图也没做拆分
    在这里插入图片描述
    bg:背景图片地址;
    captcha_type:验证码类型;
    gct_path:gct4 文件路径;
    lot_number:后续生成 pow_msg、w 的关键参数;
    payload:后续 verify 请求接口需要的参数;
    datetime:后续生成 pow_msg 的关键参数;
    process_token:后续 verify 请求接口需要的参数;
    slice:滑块图片地址。

  2. 点击按钮开始验证,弹出滑块验证码,滑动滑块,抓包到 verify?captcha_id=xxx,Query String Parameters 同样包含了一些参数:

captcha_id:与 load 接口请求头中的 captcha_id 一致;
client_type:表示 web 端;
lot_number:load 接口返回的;
risk_type:与 load 接口中的一致,表示验证码类型;
payload:load 接口返回的;
process_token:load 接口返回的;
w:加密参数,由轨迹、滑动时间、滑动距离、userresponse、device_id、pow_msg 等参数加密得到;
callback:geetest_ + 时间戳,主要作用是防止缓存。
在这里插入图片描述
响应预览中返回的内容如下,result 值为 fail 即校验失败,success 为校验通过,通过后携带 seccode 下的参数进行后续业务请求:
在这里插入图片描述

参数分析

  • captcha_id参数
  1. 全局搜索 captcha_id,跟进到 gt4.js 文件中
    在这里插入图片描述

  2. 进去后在第 307 行打上断点,刷新页面即会断住,此时 captcha_id 参数的值已经生成,同时 challenge 参数定义在下一行
    在这里插入图片描述

  3. 向上跟栈到 value,即 adaptive-captcha-demo.js 文件中,会发现其是个固定值
    在这里插入图片描述

  • challenge参数
  1. 前面提到,challenge 参数定义在 captcha_id 参数的下一行,在 gt4.js 文件的第 309 行打下断点:
    在这里插入图片描述

  2. 可以看到,challenge 参数的值由 uuid 函数生成,扣出即可

var uuid = function () {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = Math.random() * 16 | 0;
        var v = c === 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
};

console.log(uuid())
  • w参数
  1. 找加密接口可以通过跟3代验证码那种方式找到或者跟栈。
    在这里插入图片描述

  2. e 也是跟三代类似的参数,r 是将 i 参数和转为字符串的 e 参数加密得到的
    在这里插入图片描述

ar r = (0,d[$_CBHHs(15)])(JSON.stringify(e), i)
  1. 向上跟栈,找到 e 参数中各部分定义生成的位置,跟到 $BHIH 中, 中先生成了四个键值对
    在这里插入图片描述

passtime 和 track 是熟悉的滑动时间和轨迹,setLeft 为识别出来的缺口距离,userresponse 定义在 19593 行, a 为 setLeft 参数的值,t[$_GDFCG(1909)] 为定值 1.0059466666666665:

var _ = {
    "setLeft": a,
    "track": c,
    "passtime": s,
    'userresponse': a / 1.0059347482096355 + 2
};
  1. 接着跟到 $_BCFj 中,e 定义在第 6201 行,下面几行定义了 e 中的 device_id、lot_number、pow_msg、pow_sign:
    在这里插入图片描述
    device_id 同一个网站是固定值,lot_number 是 load 响应返回的,控制台打印一下 pow_msg(看过请求参数都知道这些是请求参数里面的)、pow_sign 的结果:
    在这里插入图片描述
var _ = {
    "setLeft": a,
    "track": c,
    "passtime": s,
    'userresponse': a / 1.0059347482096355 + 2,
    'device_id': i['deviceId'],
    'lot_number': i['lotNumber'],
    'pow_msg': n['options']['powMsg'],
    'pow_sign': n['options']['powSign']
};
  1. pow_msg 很明显是由几部分组成的,pow_sign 经过加密,向上跟栈到 init 中,分别定义在第 5837 行和第 5838 行,为 d 字典的键,根据键名取值:
    在这里插入图片描述
var c = t['toDataURL']()['replace']('data:image/png;base64,', "")
_ = new w[('default')][('MD5')]()['hex'](c)
a['options']['deviceId'] = _;
var h = a["options"]
    , l = h['powDetail']
    , p = h['lotNumber']
    , f = h['captchaId']

d = v['default'](p, f, l['hashfunc'], l['version'], l['bits'], l['datetime'], "")

进去d执行的函数可以看到结果预计就是执行了这句将传入参数拼接起来
在这里插入图片描述加盐值这里进去可以发现跟极验2 3一样的随机字符串16位
在这里插入图片描述
还原整个加密部分

function get_pow(e, t, n, i, r, s, o) {
    // let pow_msg = i + "|" + r + "|" + n + "|" + s + "|" + t + "|" + e + "|" + o + "|"
    let pow_msg = "1|0|md5|2023-01-17T16:10:27.042878+08:00|54088bb07d2df3c46b79f80300b0abbe|9ddbfcbf25f846c3a47f89603050a9b0||"
    // let h = getRandomStr()
    let h = 'e699e453328fb1a0'
    let l = pow_msg + h
    p = X(l)
    return {
        'pow_msg': pow_msg + h,
        'pow_sign': p
    };

}
  1. 还差一部分未分析完
    在这里插入图片描述
    em 等定值就不分析了,注意 kqg5:“1557244628”,这个参数值和三代滑块中一样,每隔几个小时会改变,向上跟栈到 $_BCFj 中,在第 6207 行打下断点,此时 e 中这个值还未生成:
    在这里插入图片描述

下一行打下断点,下步断点,即执行完 n[ C B H I E ( 791 ) ] ( e ) ; 后,这个参数值就生成了,证明是 n [ _CBHIE(791)](e); 后,这个参数值就生成了,证明是 n[ CBHIE(791)](e);后,这个参数值就生成了,证明是n[_CBHIE(791)] 方法生成的,跟进去:

在这里插入图片描述

跳转到第 5766 行,在第 5779 行打下断点,此时的 n 中还未生成此参数:
在这里插入图片描述
执行了 _gct(n) 后即生成:
在这里插入图片描述
可见其生成位置在 _gct 方法中,跟进去后到 gct4.js 文件,和三代大差不差:
在这里插入图片描述
终于把入参分析完了

  1. 可以将值导出,至此 e 就分析完了,接着回到r,跟进到加密函数 d[$_CBHHO(84)] 中,定义在第 11772 行
    在这里插入图片描述

d[$_DIEIG(198)])© + u; 即 r 参数的值,c 为一个大数组,u 明显也经过加密了,所以 r 参数的值就是数组 c 加密后再加上 u 得到的:
在这里插入图片描述

  1. 现在又到了分析c和u的时候了
    先跟进到 u,其定义在第 11705 行,解混淆后如下
i = d[$_DIEHH(178)](),
u = new l[($_DIEHH(15))]()['encrypt'](i)

i 是随机数,跟进到加密函数 l[($_DIEHS(84))] 中,在第 12725 行,于 12741 行打下断点,可以看到这里就是个 RSA 加密,扣代码或者直接引库即可,我是直接把里面的自执行直接全扣然后new出来的

u = new r()['encrypt'](i)

回到 c 参数,c 参数的值为一个大数组,其定义在第 11705 行,解混淆后内容如下:

var c = s[a]["symmetrical"]["encrypt"](e, i);

e 之前分析完了,i 为随机数,两个参数已经分析完了,跟进到加密方法中,在第 12174 行,于 12186 行打下断点,控制台打印一下混淆部分内容,很熟悉的东西,这里就是 AES 加密,iv 为初始向量,加密模式为 CBC
在这里插入图片描述
最后c再经过了一层加密
在这里插入图片描述

在这里插入图片描述
总结:
整个扣跟3代大同小异
只是存在入参不同
混淆程度不通

备注:本文仅供学习,有问题可以找博主共同进步

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值