广告
返回顶部
首页 > 资讯 > 后端开发 > PHP编程 >验证码案例(极验3滑动模式)
  • 220
分享到

验证码案例(极验3滑动模式)

pythonjavascriptnode.js爬虫网络安全 2023-09-02 09:09:31 220人浏览 安东尼
摘要

文章目录 验证码案例 【极验3滑动模式】1 声明2 案例目标2.1 网站2.2 接口2.3 参数2.4 算法 3 验证流程分析3.1 抓包分析3.2 获取验证码图片3.2.1 大致流程3.

文章目录

验证码案例 【极验3滑动模式】

1 声明

本案例中所有内容仅供个人学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!

2 案例目标

2.1 网站

aHR0cHM6Ly93D3cuZ2VldGVzdC5jb20vZGVhttps://blog.csdn.net/NUT_0/article/details/tby9zbGlkZS1mbG9hdC5odG1s

2.2 接口

aHR0cHM6Ly9hcGl2Ni5nZWV0ZXN0LmNvbS9nZXQucGhwaHR0cHM6Ly9hcGkuZ2VldGVzdC5jb20vZ2V0LnBocA==aHR0cHM6Ly9hcGkuZ2VldGVzdC5jb20vYWpheC5waHA=

2.3 参数

生成w以及相关参数

2.4 算法

RSAAESMD5

3 验证流程分析

3.1 抓包分析

1 reGISHttps://blog.csdn.net/NUT_0/article/details/ter-slide?返回challenge ghttps://blog.csdn.net/NUT_0/article/details/t2 gehttps://blog.csdn.net/NUT_0/article/details/thttps://blog.csdn.net/NUT_0/article/details/type.PHP       返回一堆js文件3 gehttps://blog.csdn.net/NUT_0/article/details/t.php    请求参数:ghttps://blog.csdn.net/NUT_0/article/details/t   challenge  w    返回一堆数据4 ajax.php  获取滑块类型    请求参数:ghttps://blog.csdn.net/NUT_0/article/details/t   challenge  w    返回滑块标记 {"shttps://blog.csdn.net/NUT_0/article/details/tahttps://blog.csdn.net/NUT_0/article/details/tus": "success", "dahttps://blog.csdn.net/NUT_0/article/details/ta": {"resulhttps://blog.csdn.net/NUT_0/article/details/t": "slide"}}5 gehttps://blog.csdn.net/NUT_0/article/details/t.php     请求参数:ghttps://blog.csdn.net/NUT_0/article/details/t   challenge w     返回了验证码信息    6 ajax.php  提交验证    请求参数:ghttps://blog.csdn.net/NUT_0/article/details/t   challenge  w    成功  message: "success"    失败  message: "fail"

通过分析我们只需要请求 1===>3===>4===>5===>6 (后面验证后3其实也可以省略)

3.2 获取验证码图片

3.2.1 大致流程

  • 请求regishttps://blog.csdn.net/NUT_0/article/details/ter-slide?接口,拿到ghttps://blog.csdn.net/NUT_0/article/details/tchallenge
  • 带上ghttps://blog.csdn.net/NUT_0/article/details/t、challenge、w可置空请求gehttps://blog.csdn.net/NUT_0/article/details/t.php? 返回c、s
  • 带上ghttps://blog.csdn.net/NUT_0/article/details/t、challenge、w置空 请求ajax.php接口,返回验证码类型slide
  • 带上ghttps://blog.csdn.net/NUT_0/article/details/t、challeng再次请求gehttps://blog.csdn.net/NUT_0/article/details/t.php接口,验证码信息(包含图片背景图、缺口背景图),从JSON中取出新的c、s、challenge值 (c没变)

3.2.2 详细实现

​ 首先,要拿到ghttps://blog.csdn.net/NUT_0/article/details/t和challenge,直接请求获取

Query Shttps://blog.csdn.net/NUT_0/article/details/tring Paramehttps://blog.csdn.net/NUT_0/article/details/ters、FORM Dahttps://blog.csdn.net/NUT_0/article/details/ta 和 Requeshttps://blog.csdn.net/NUT_0/article/details/t Payload 都是 HTTP 请求中传递数据的方式,主要区别在于数据的格式和传递方式。1. Query Shttps://blog.csdn.net/NUT_0/article/details/tring Paramehttps://blog.csdn.net/NUT_0/article/details/ters:是通过 URL 的查询字符串传递数据的一种方式。查询字符串是 URL 中 ? 后面的部分,它包含了若干个键值对,用 & 分隔。例如,hhttps://blog.csdn.net/NUT_0/article/details/thttps://blog.csdn.net/NUT_0/article/details/tps://www.example.com/search?q=keyWord&sorhttps://blog.csdn.net/NUT_0/article/details/t=desc 中的 q 和 sorhttps://blog.csdn.net/NUT_0/article/details/t 都是 Query Shttps://blog.csdn.net/NUT_0/article/details/tring Paramehttps://blog.csdn.net/NUT_0/article/details/ters。这种方式适合于传递简单的数据,如搜索关键字、分页等。2. Form Dahttps://blog.csdn.net/NUT_0/article/details/ta:是通过 html 表单提交数据的一种方式。表单数据被编码为一系列键值对,通过 POST 请求发送到服务器。这种方式适合于传递更复杂的数据,如用户注册信息、文章发布等。3. Requeshttps://blog.csdn.net/NUT_0/article/details/t Payload:是通过 HTTP 请求主体传递数据的一种方式。它适用于传递复杂的结构化数据,如 JSON 或 XML 格式的数据。Requeshttps://blog.csdn.net/NUT_0/article/details/t Payload 通常与 RESTful api 和 Ajax 交互中使用。Query Shttps://blog.csdn.net/NUT_0/article/details/tring Paramehttps://blog.csdn.net/NUT_0/article/details/ters 适合传递简单的数据,Form Dahttps://blog.csdn.net/NUT_0/article/details/ta 适合传递表单数据,而 Requeshttps://blog.csdn.net/NUT_0/article/details/t Payload 适合传递结构化数据,具有更大的灵活性和可扩展性。
第一个gehttps://blog.csdn.net/NUT_0/article/details/t.php,带上ghttps://blog.csdn.net/NUT_0/article/details/t、challenge、callback是geehttps://blog.csdn.net/NUT_0/article/details/teshttps://blog.csdn.net/NUT_0/article/details/t+时间戳、w可置空请求gehttps://blog.csdn.net/NUT_0/article/details/t.php? 返回c、s

ajax.php:

​ 带上ghttps://blog.csdn.net/NUT_0/article/details/t、challenge、w置空 请求接口,返回验证码类型slide

第二次请求gehttps://blog.csdn.net/NUT_0/article/details/t.php

​ 带上ghttps://blog.csdn.net/NUT_0/article/details/t、challeng再次请求接口,验证码信息(包含图片背景图、缺口背景图),从json中取出新的c、s、challenge值 (c没变)

坑在这个返回的challenge,比之前的值后面多了两字符

看到获取的图片是乱码的,接下来需要对图片进行还原。

3.3底图还原

由于某验验证码是用canvas绘图的(F12查看验证码元素可以看出)

第一种方法:打上canvas断点,画布创建时会短住

for (var a = r / 2, _ = 0; _ < 52; _ += 1) {    // 取数组 Uhttps://blog.csdn.net/NUT_0/article/details/t[_]对 26 取模,乘以 12 再加 1,结果赋值给变量 c    var c = Uhttps://blog.csdn.net/NUT_0/article/details/t[_] % 26 * 12 + 1;    var u = 25 < Uhttps://blog.csdn.net/NUT_0/article/details/t[_] ? a : 0;    // 在画布上将像素数据绘制到指定位置    var l = o['puhttps://blog.csdn.net/NUT_0/article/details/tImageDahttps://blog.csdn.net/NUT_0/article/details/ta'](c, u, 10, a);    // 获取指定矩形区域内的像素数据 ImageDahttps://blog.csdn.net/NUT_0/article/details/ta 对象    s['gehttps://blog.csdn.net/NUT_0/article/details/tImageDahttps://blog.csdn.net/NUT_0/article/details/ta'](l, _ % 26 * 10, 25 < _ ? a : 0);}

第二种方法

​ 可以hook创建canvas对象的地方,直接百度参考一个:

// hook canvas(funchttps://blog.csdn.net/NUT_0/article/details/tion() {    'use shttps://blog.csdn.net/NUT_0/article/details/trichttps://blog.csdn.net/NUT_0/article/details/t';    lehttps://blog.csdn.net/NUT_0/article/details/t creahttps://blog.csdn.net/NUT_0/article/details/te_elemenhttps://blog.csdn.net/NUT_0/article/details/t = documenhttps://blog.csdn.net/NUT_0/article/details/t.creahttps://blog.csdn.net/NUT_0/article/details/teElemenhttps://blog.csdn.net/NUT_0/article/details/t.bind(documenhttps://blog.csdn.net/NUT_0/article/details/t);    documenhttps://blog.csdn.net/NUT_0/article/details/t.creahttps://blog.csdn.net/NUT_0/article/details/teElemenhttps://blog.csdn.net/NUT_0/article/details/t = funchttps://blog.csdn.net/NUT_0/article/details/tion (_elemenhttps://blog.csdn.net/NUT_0/article/details/t) {        console.log("creahttps://blog.csdn.net/NUT_0/article/details/te_elemenhttps://blog.csdn.net/NUT_0/article/details/t:",_elemenhttps://blog.csdn.net/NUT_0/article/details/t);        if (_elemenhttps://blog.csdn.net/NUT_0/article/details/t === "canvas") {            debugger;        }        rehttps://blog.csdn.net/NUT_0/article/details/turn creahttps://blog.csdn.net/NUT_0/article/details/te_elemenhttps://blog.csdn.net/NUT_0/article/details/t(_elemenhttps://blog.csdn.net/NUT_0/article/details/t);    }})();

这里逻辑还是很清晰的,但如果扣js的话相对来说要麻烦一些,还要依赖第三方canvas库,不如直接用pyhttps://blog.csdn.net/NUT_0/article/details/thon复写逻辑(用到了PIL库) Uhttps://blog.csdn.net/NUT_0/article/details/t是定值

还原之后类似下图:

3.4 获取缺口距离生成轨迹

缺口距离识别,可以手动,也可以第三方平台,这里选择DDDdocr识别效果还不错 直接上代码

    def gehttps://blog.csdn.net/NUT_0/article/details/t_x(self):        slide = ddddocr.DdddOcr(dehttps://blog.csdn.net/NUT_0/article/details/t=False, ocr=False)        wihttps://blog.csdn.net/NUT_0/article/details/th open('bg.jpg', 'rb') as f:            https://blog.csdn.net/NUT_0/article/details/targehttps://blog.csdn.net/NUT_0/article/details/t_byhttps://blog.csdn.net/NUT_0/article/details/tes = f.read()        wihttps://blog.csdn.net/NUT_0/article/details/th open('full.jpg', 'rb') as f:            background_byhttps://blog.csdn.net/NUT_0/article/details/tes = f.read()        res = slide.slide_comparison(https://blog.csdn.net/NUT_0/article/details/targehttps://blog.csdn.net/NUT_0/article/details/t_byhttps://blog.csdn.net/NUT_0/article/details/tes, background_byhttps://blog.csdn.net/NUT_0/article/details/tes)        rehttps://blog.csdn.net/NUT_0/article/details/turn res.gehttps://blog.csdn.net/NUT_0/article/details/t('https://blog.csdn.net/NUT_0/article/details/targehttps://blog.csdn.net/NUT_0/article/details/t')[0]

通过缓动函数生成轨迹,参考hhttps://blog.csdn.net/NUT_0/article/details/thttps://blog.csdn.net/NUT_0/article/details/tps://easings.nehttps://blog.csdn.net/NUT_0/article/details/t/zh-cn#easeOuhttps://blog.csdn.net/NUT_0/article/details/tExpo

    def __ease_ouhttps://blog.csdn.net/NUT_0/article/details/t_expo(self,sep):        """        缓动函数 easeOuhttps://blog.csdn.net/NUT_0/article/details/tExpo        参考:hhttps://blog.csdn.net/NUT_0/article/details/thttps://blog.csdn.net/NUT_0/article/details/tps://easings.nehttps://blog.csdn.net/NUT_0/article/details/t/zh-cn#easeOuhttps://blog.csdn.net/NUT_0/article/details/tExpo        """        if sep == 1:            rehttps://blog.csdn.net/NUT_0/article/details/turn 1        else:            rehttps://blog.csdn.net/NUT_0/article/details/turn 1 - pow(2, -10 * sep)    def gehttps://blog.csdn.net/NUT_0/article/details/t_slide_https://blog.csdn.net/NUT_0/article/details/track(self,dishttps://blog.csdn.net/NUT_0/article/details/tance):        """        根据滑动距离生成滑动轨迹        :param dishttps://blog.csdn.net/NUT_0/article/details/tance: 需要滑动的距离        :rehttps://blog.csdn.net/NUT_0/article/details/turn: 滑动轨迹: [[x,y,https://blog.csdn.net/NUT_0/article/details/t], ...]            x: 已滑动的横向距离            y: 已滑动的纵向距离, 除起点外, 均为0            https://blog.csdn.net/NUT_0/article/details/t: 滑动过程消耗的时间, 单位: 毫秒        """        if nohttps://blog.csdn.net/NUT_0/article/details/t isinshttps://blog.csdn.net/NUT_0/article/details/tance(dishttps://blog.csdn.net/NUT_0/article/details/tance, inhttps://blog.csdn.net/NUT_0/article/details/t) or dishttps://blog.csdn.net/NUT_0/article/details/tance < 0:            raise ValueError(f"dishttps://blog.csdn.net/NUT_0/article/details/tance类型必须是大于等于0的整数: dishttps://blog.csdn.net/NUT_0/article/details/tance: {dishttps://blog.csdn.net/NUT_0/article/details/tance}, https://blog.csdn.net/NUT_0/article/details/type: {https://blog.csdn.net/NUT_0/article/details/type(dishttps://blog.csdn.net/NUT_0/article/details/tance)}")        # 初始化轨迹列表        slide_https://blog.csdn.net/NUT_0/article/details/track = [            [random.randinhttps://blog.csdn.net/NUT_0/article/details/t(-50, -10), random.randinhttps://blog.csdn.net/NUT_0/article/details/t(-50, -10), 0],            [0, 0, 0],        ]        # 共记录counhttps://blog.csdn.net/NUT_0/article/details/t次滑块位置信息        counhttps://blog.csdn.net/NUT_0/article/details/t = 30 + inhttps://blog.csdn.net/NUT_0/article/details/t(dishttps://blog.csdn.net/NUT_0/article/details/tance / 2)        # 初始化滑动时间        https://blog.csdn.net/NUT_0/article/details/t = random.randinhttps://blog.csdn.net/NUT_0/article/details/t(50, 100)        # 记录上一次滑动的距离        _x = 0        _y = 0        for i in range(counhttps://blog.csdn.net/NUT_0/article/details/t):            # 已滑动的横向距离            x = round(self.__ease_ouhttps://blog.csdn.net/NUT_0/article/details/t_expo(i / counhttps://blog.csdn.net/NUT_0/article/details/t) * dishttps://blog.csdn.net/NUT_0/article/details/tance)            # 滑动过程消耗的时间            https://blog.csdn.net/NUT_0/article/details/t += random.randinhttps://blog.csdn.net/NUT_0/article/details/t(10, 20)            if x == _x:                conhttps://blog.csdn.net/NUT_0/article/details/tinue            slide_https://blog.csdn.net/NUT_0/article/details/track.append([x, _y, https://blog.csdn.net/NUT_0/article/details/t])            _x = x        slide_https://blog.csdn.net/NUT_0/article/details/track.append(slide_https://blog.csdn.net/NUT_0/article/details/track[-1])        rehttps://blog.csdn.net/NUT_0/article/details/turn slide_https://blog.csdn.net/NUT_0/article/details/track

3.5 加密轨迹并提交

  • ​ 可以看到最后ajax.php带上新的ghttps://blog.csdn.net/NUT_0/article/details/t,chanllenge,w参数想都不用想肯定是包含轨迹内容的。

直接搜索w是搜索不到的,JS里面是被编码的,可以把W值编码,进行查找,在JS里面搜索u0077":

或者通过解混淆,还原后搜索w,参考JS逆向:AST还原极验混淆JS实战 (qq.com)

然后搜索"w",可以看到"w": h + u ,h在5980行,u在5978行 还原如下:

var u = r[$_CAHJe(785)](), l = V['encryphttps://blog.csdn.net/NUT_0/article/details/t'](ghttps://blog.csdn.net/NUT_0/article/details/t['shttps://blog.csdn.net/NUT_0/article/details/tringify'](o), r[$_CAIAj(761)]()), h = m[$_CAIAj(783)](l)

3.5.1 u参数

先解决u这个函数,滑动滑块之后短住,进去看看

进去之后发现是rehttps://blog.csdn.net/NUT_0/article/details/turn的e **https://blog.csdn.net/NUT_0/article/details/this$_CBFJv(761)**是生成的随机数 然后经过加密得到的

进去之后发现就在上面 返回的 **rhttps://blog.csdn.net/NUT_0/article/details/t()**是16位随机数

里面又是由4个随机数**https://blog.csdn.net/NUT_0/article/details/t()**相加生成的

还原之后Mahttps://blog.csdn.net/NUT_0/article/details/th.random() 是随机选取大于等于 0.0 且小于 1.0 的伪随机 double 值,https://blog.csdn.net/NUT_0/article/details/toShttps://blog.csdn.net/NUT_0/article/details/tring(16) 为十六进制字符串

(65536 * (1 + Mahttps://blog.csdn.net/NUT_0/article/details/th["random"]()) | 0)["https://blog.csdn.net/NUT_0/article/details/toShttps://blog.csdn.net/NUT_0/article/details/tring"](16)["subshttps://blog.csdn.net/NUT_0/article/details/tring"](1)

通过js复现,后续传入16位随机数可以直接通过pyhttps://blog.csdn.net/NUT_0/article/details/thon写死!方便调试

funchttps://blog.csdn.net/NUT_0/article/details/tion random() {    var random_shttps://blog.csdn.net/NUT_0/article/details/tr = "";    for (var index = 0; index < 4; index++) {        random_shttps://blog.csdn.net/NUT_0/article/details/tr += (65536 * (1 + Mahttps://blog.csdn.net/NUT_0/article/details/th["random"]()) | 0)["https://blog.csdn.net/NUT_0/article/details/toShttps://blog.csdn.net/NUT_0/article/details/tring"](16)["subshttps://blog.csdn.net/NUT_0/article/details/tring"](1);    }    rehttps://blog.csdn.net/NUT_0/article/details/turn random_shttps://blog.csdn.net/NUT_0/article/details/tr;}

接下来看U里面包括了三个方法 很显然是RSA加密 需要设置公钥

进入new U()[‘encryphttps://blog.csdn.net/NUT_0/article/details/t’] 来到lhttps://blog.csdn.net/NUT_0/article/details/t()方法 2853行 往上找 uhttps://blog.csdn.net/NUT_0/article/details/t方法 在2850打上断点重新拉滑块 发现了Invalid RSA public key字样

uhttps://blog.csdn.net/NUT_0/article/details/t 函数传入了两个值,https://blog.csdn.net/NUT_0/article/details/t 为公钥值,e 为公钥模数,都是固定值

https://blog.csdn.net/NUT_0/article/details/t='00C1E3934D1614465B33053E7F48EE4EC87B14B95EF88947713D25EECBFF7E74C7977D02DC1D9451F79DD5D1C10C29ACB6A9B4D6FB7D0A0279B6719E1772565F09AF627715919221AEF91899CAE08C0D686D748B20A3603BE2318CA6BC2B59706592A9219D0BF05C9F65023A21D2330807252AE0066D59CEEFA5F2748EA80BAB81'e='10001'

这里我们直接利用pyhttps://blog.csdn.net/NUT_0/article/details/thon RSA实现,通过rsa加密随机数就是U

    def rsa_encryphttps://blog.csdn.net/NUT_0/article/details/t(self,random):        """        rsa加密        :param random: 随机数        :rehttps://blog.csdn.net/NUT_0/article/details/turn: 加密后的随机数        """        #公钥模数        n ='00C1E3934D1614465B33053E7F48EE4EC87B14B95EF88947713D25EECBFF7E74C7977D02DC1D9451F79DD5D1C10C29ACB6A9B4D6FB7D0A0279B6719E1772565F09AF627715919221AEF91899CAE08C0D686D748B20A3603BE2318CA6BC2B59706592A9219D0BF05C9F65023A21D2330807252AE0066D59CEEFA5F2748EA80BAB81'        #公钥指数        e = '10001'        #构造公钥        key = rsa.PublicKey(e = inhttps://blog.csdn.net/NUT_0/article/details/t(e, 16), n = inhttps://blog.csdn.net/NUT_0/article/details/t(n, 16))        # prinhttps://blog.csdn.net/NUT_0/article/details/t('key:',key)        #加密        message = rsa.encryphttps://blog.csdn.net/NUT_0/article/details/t(random.encode('uhttps://blog.csdn.net/NUT_0/article/details/tf-8'), key)        #转换成16进制        encryphttps://blog.csdn.net/NUT_0/article/details/t_dahttps://blog.csdn.net/NUT_0/article/details/ta  = message.hex()        rehttps://blog.csdn.net/NUT_0/article/details/turn encryphttps://blog.csdn.net/NUT_0/article/details/t_dahttps://blog.csdn.net/NUT_0/article/details/ta

3.5.2 L参数

l = V['encryphttps://blog.csdn.net/NUT_0/article/details/t'](ghttps://blog.csdn.net/NUT_0/article/details/t['shttps://blog.csdn.net/NUT_0/article/details/tringify'](o), r[$_CAIAj(761)]())

可以先看里面的参数 o是有一个参数对象组成 r$_CAIAj(761)为之前的16位随机数 有shttps://blog.csdn.net/NUT_0/article/details/tringify方法所以ghttps://blog.csdn.net/NUT_0/article/details/t肯定为JSON V为一个加密方法

3.5.2.1 o参数

这里先解决o参数,通过两次对比箭头所指的四个参数在变化 需要分析

  • aa: “a()(T!!LKwswshttps://blog.csdn.net/NUT_0/article/details/tssss*https://blog.csdn.net/NUT_0/article/details/tshttps://blog.csdn.net/NUT_0/article/details/thttps://blog.csdn.net/NUT_0/article/details/thttps://blog.csdn.net/NUT_0/article/details/tsshttps://blog.csdn.net/NUT_0/article/details/tsssshttps://blog.csdn.net/NUT_0/article/details/ts!*x(!!( )9/9−−/010−.−01q2,2,−.−,7/5−5 )9/9--/010-.-01q2,2,-.-,7/5-5 )9/9/010.01q2,2,.,7/55*R” //轨迹加密
  • ep: {v: ‘7.9.0’, $_BIo: false, me: https://blog.csdn.net/NUT_0/article/details/true, https://blog.csdn.net/NUT_0/article/details/tm: {…}, https://blog.csdn.net/NUT_0/article/details/td: -1} //可以随机或者写死
  • h9s9: “1816378497” //可以写死
  • imgload: 257 //图片加载时间可写死
  • lang: “zh-cn”
  • passhttps://blog.csdn.net/NUT_0/article/details/time: 406 //轨迹滑动时间
  • rp: “bcb6b32f4b49185db3212719c93a9bef” //ghttps://blog.csdn.net/NUT_0/article/details/t + 32 位 challenge + passhttps://blog.csdn.net/NUT_0/article/details/time,再经过 MD5 加密
  • userresponse: “66666be4” //滑动距离x + challenge 的值

aa

往上找到o 在5917打上断点 aa是有e生成的

直接跳过了 发现在上边没有e 跟上个栈

跳第2个栈8066行、查看第2个参数l 就是这个参数

l = n['$_CICa']['$_BBEI'](n['$_CICa']['$_FDL'](), n['$_CJV']['c'], n['$_CJV']['s');

后面两个参数是前面gehttps://blog.csdn.net/NUT_0/article/details/t.php返回的新的cs

外层** F D L ∗ ∗ 和 ∗ ∗ _FDL**和** FDL_BBEI ** 直接进去全扣就行了

$_FDL转到3990行4030这里是轨迹

chttps://blog.csdn.net/NUT_0/article/details/t里面的**$_CAd**对轨迹进行了做差运算

passhttps://blog.csdn.net/NUT_0/article/details/time

去轨迹的最后一个列表的的最后一位数

passhttps://blog.csdn.net/NUT_0/article/details/time = https://blog.csdn.net/NUT_0/article/details/track[-1][-1] #滑动时间
userresponse

https://blog.csdn.net/NUT_0/article/details/t为滑动距离x **i[‘challenge’]**为gehttps://blog.csdn.net/NUT_0/article/details/t.php返回的新chanllenge

H(https://blog.csdn.net/NUT_0/article/details/t, i['challenge'])

H()在668行全口还原一下就行

rp

这个rp为32位盲猜一波 MD5 控制台输出一下

还原之后 rp :ghttps://blog.csdn.net/NUT_0/article/details/t + 32 位 challenge + passhttps://blog.csdn.net/NUT_0/article/details/time,再经过 MD5 加密

o['rp'] = X(i['ghttps://blog.csdn.net/NUT_0/article/details/t'] + i['challenge']['slice'](0, 32) + o['passhttps://blog.csdn.net/NUT_0/article/details/time'])

3.5.2.2 V方法

进入V方法 控制台还原一下参数 很明显是AES加密 初始向量 iv 值为 “0000000000000000”:

这里通过引库实现

var Cryphttps://blog.csdn.net/NUT_0/article/details/toJS = require('cryphttps://blog.csdn.net/NUT_0/article/details/to-js')funchttps://blog.csdn.net/NUT_0/article/details/tion aesV(o_https://blog.csdn.net/NUT_0/article/details/texhttps://blog.csdn.net/NUT_0/article/details/t, random_shttps://blog.csdn.net/NUT_0/article/details/tr) {    var key = Cryphttps://blog.csdn.net/NUT_0/article/details/toJS.enc.Uhttps://blog.csdn.net/NUT_0/article/details/tf8.parse(random_shttps://blog.csdn.net/NUT_0/article/details/tr);    var iv = Cryphttps://blog.csdn.net/NUT_0/article/details/toJS.enc.Uhttps://blog.csdn.net/NUT_0/article/details/tf8.parse("0000000000000000");    var srcs = Cryphttps://blog.csdn.net/NUT_0/article/details/toJS.enc.Uhttps://blog.csdn.net/NUT_0/article/details/tf8.parse(o_https://blog.csdn.net/NUT_0/article/details/texhttps://blog.csdn.net/NUT_0/article/details/t);    var encryphttps://blog.csdn.net/NUT_0/article/details/ted = Cryphttps://blog.csdn.net/NUT_0/article/details/toJS.AES.encryphttps://blog.csdn.net/NUT_0/article/details/t(srcs, key, {        iv: iv,        mode: Cryphttps://blog.csdn.net/NUT_0/article/details/toJS.mode.CBC,        padding: Cryphttps://blog.csdn.net/NUT_0/article/details/toJS.pad.Pkcs7    });    for (var r = encryphttps://blog.csdn.net/NUT_0/article/details/ted, o = r.cipherhttps://blog.csdn.net/NUT_0/article/details/texhttps://blog.csdn.net/NUT_0/article/details/t.words, i = r.cipherhttps://blog.csdn.net/NUT_0/article/details/texhttps://blog.csdn.net/NUT_0/article/details/t.sigByhttps://blog.csdn.net/NUT_0/article/details/tes, s = [], a = 0; a < i; a++) {        var c = o[a >>> 2] >>> 24 - a % 4 * 8 & 255;        s.push(c);    }    rehttps://blog.csdn.net/NUT_0/article/details/turn s;};

通过对比结果一致

3.5.3 h参数

通过**m[‘$_FEE’]**对l参数就行加密

h = m['$_FEE'](l)

进入$_FEE 跳转到1609行 发现最后是返回的e里面的两个参数

进去e里面看看 跳转**$_FCc**到1564行 返回的也是res:n 和 end:r

混淆还原之后改写一下方法

funchttps://blog.csdn.net/NUT_0/article/details/tion $_FCc(https://blog.csdn.net/NUT_0/article/details/t) {    // var o = https://blog.csdn.net/NUT_0/article/details/this;    // i || (i = o);    for (var e = funchttps://blog.csdn.net/NUT_0/article/details/tion(https://blog.csdn.net/NUT_0/article/details/t, e) {        for (var n = 0, r = 24 - 1; 0 <= r; r -= 1)            1 === $_FBv(e, r) && (n = (n << 1) + $_FBv(https://blog.csdn.net/NUT_0/article/details/t, r));        rehttps://blog.csdn.net/NUT_0/article/details/turn n;    }, n = '', r = '', s = https://blog.csdn.net/NUT_0/article/details/t['lenghttps://blog.csdn.net/NUT_0/article/details/th'], a = 0; a < s; a += 3) {        var _;        if (a + 2 < s)            _ = (https://blog.csdn.net/NUT_0/article/details/t[a] << 16) + (https://blog.csdn.net/NUT_0/article/details/t[a + 1] << 8) + https://blog.csdn.net/NUT_0/article/details/t[a + 2],            n += $_EJu(e(_, 7274496)) + $_EJu(e(_, 9483264)) + $_EJu(e(_, 19220)) + $_EJu(e(_, 235));        else {            var c = s % 3;            2 == c ? (_ = (https://blog.csdn.net/NUT_0/article/details/t[a] << 16) + (https://blog.csdn.net/NUT_0/article/details/t[a + 1] << 8),            n += $_EJu(e(_, 7274496)) + $_EJu(e(_, 9483264)) + $_EJu(e(_, 19220)),            r = ".") : 1 == c && (_ = https://blog.csdn.net/NUT_0/article/details/t[a] << 16,            n += $_EJu(e(_, 7274496)) + $_EJu(e(_, 9483264)),            r = '.' + '.');        }    }    rehttps://blog.csdn.net/NUT_0/article/details/turn n+r;}

3.5.4 w

w = h+u

到此轨迹加密就完成了!!!!

4 结果展示

5 总结

在里面也遇到了很多坑,这种扣算法+js好处就在于不用不用补环境缺点就在于如果没有经验是不知道他的算法的,还有一种全扣的方法需要补环境可以上proxy()拦截环境进行补充比较简单,推荐新手尝试。

来源地址:hhttps://blog.csdn.net/NUT_0/article/details/thttps://blog.csdn.net/NUT_0/article/details/tps://blog.csdn.nehttps://blog.csdn.net/NUT_0/article/details/t/NUT_0/arhttps://blog.csdn.net/NUT_0/article/details/ticle/dehttps://blog.csdn.net/NUT_0/article/details/tails/130668772

--结束END--

本文标题: 验证码案例(极验3滑动模式)

本文链接: https://www.lsjlt.com/news/390531.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 验证码案例(极验3滑动模式)
    文章目录 验证码案例 【极验3滑动模式】1 声明2 案例目标2.1 网站2.2 接口2.3 参数2.4 算法 3 验证流程分析3.1 抓包分析3.2 获取验证码图片3.2.1 大致流程3....
    99+
    2023-09-02
    python javascript node.js 爬虫 网络安全
  • Java selenium处理极验滑动验证码示例
    要爬取一个网站遇到了极验的验证码,这周都在想着怎么破解这个,网上搜了好多知乎上看到有人问了这问题,我按照这思路去大概实现了一下。1.使用htmlunit(这种方式我没成功,模拟鼠标拖拽后轨迹没生成,可以跳过)我用的是java,我首先先想到了...
    99+
    2023-05-31
    java selenium ava
  • selenium+java破解极验滑动验证码的示例代码
    摘要分析验证码素材图片混淆原理,并采用selenium模拟人拖动滑块过程,进而破解验证码。人工验证的过程打开威锋网注册页面移动鼠标至小滑块,一张完整的图片会出现(如下图1)点击鼠标左键,图片中间会出现一个缺块(如下图2)移动小滑块正上方图案...
    99+
    2023-05-30
  • Python破解极验滑动验证码的示例分析
    这篇文章将为大家详细讲解有关Python破解极验滑动验证码的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。极验滑动验证码以上图片是最典型的要属于极验滑动认证了,极验官网:http://www.ge...
    99+
    2023-06-15
  • Python破解极验滑动验证码详细步骤
    目录极验滑动验证码实现位移移动需要的基础知识对比两张图片,找出缺口获得图片按照位移移动详细代码极验滑动验证码 以上图片是最典型的要属于极验滑动认证了,极验官网:http://www...
    99+
    2022-11-12
  • 如何使用php+js实现极验,拖动滑块验证码验证表单
    这篇文章给大家分享的是有关如何使用php+js实现极验,拖动滑块验证码验证表单的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。   代码实现   html文件   <!...
    99+
    2022-10-19
  • 用Python爬虫破解滑动验证码的案例解析
    做爬虫总会遇到各种各样的反爬限制,反爬的第一道防线往往在登录就出现了,为了限制爬虫自动登录,各家使出了浑身解数,所谓道高一尺魔高一丈。 今天分享个如何简单处理滑动图片的验证码的案例。...
    99+
    2022-11-12
  • Java实现滑动验证码的示例代码
    目录1.效果演示2.后端代码控制层工具类3.前端页面功能:java实现滑动验证码 项目是采用springboot,maven 开发工具:采用idea 1.效果演示 2.后端代码...
    99+
    2022-11-13
  • 使用 Node.js 模拟滑动拼图验证码操作的示例代码
    近几年,网页上各种新型验证码层出不穷,其中一种比较常见的是滑动验证码,比如下图这种。 本文介绍了一种使用纯前端方法寻找滑动终点并模拟滑动的方法。 我们需要三个依赖库: puppeteer 、 Resemb...
    99+
    2022-06-04
    验证码 示例 拼图
  • Vue插件之滑动验证码的示例分析
    小编给大家分享一下Vue插件之滑动验证码的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!预览目前仅前端实现,支持移动端滑...
    99+
    2022-10-19
  • Android自定义滑动验证条的示例代码
    本文介绍了Android自定义滑动验证条的示例代码,分享给大家,具体如下:*注:不知道为什么,h6的标签在这里没用了,所以我也只能用Markdown的语法来写了项目地址:https://github.com/994866755/handso...
    99+
    2023-05-30
    android 滑动验证条 roi
  • 基于C#实现图片滑动验证码的示例代码
    目录图片准备合成目标实现1.创建项目2.Nuget添加ImageSharp3.vscode打开4.引入图片5.生成out_bg.jpg6.生成out_slider.png全部代码最后...
    99+
    2022-11-13
  • JS如何实现PC手机端和嵌入式滑动拼图验证码三种效果
    这篇文章将为大家详细讲解有关JS如何实现PC手机端和嵌入式滑动拼图验证码三种效果,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。PC和手机端网站滑动拼图验证码效果源码,同时...
    99+
    2022-10-19
  • Android 中使用ContentObserver模式获取短信用正则自动填充验证码
    最近做注册的时候看到很多app在手机接受到短信的时候直接填写验证码到界面省略用户自动输入,感觉这样确实蛮人性化的呵呵,于是自己也做了一个 步骤: 首先我使用了ContentOb...
    99+
    2022-06-06
    自动 信用 验证码 正则 Android
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作