【验证码系列】用逆向思维深度分析滑动验证码(含轨迹算法)

news2024/11/18 8:33:00

文章目录

  • 1. 写在前面
  • 2. 抓包分析
  • 3. 接口分析
  • 4. 滑动验证码弹出分析
  • 5. 滑动验证分析
  • 6. 轨迹生成算法实现
  • 7. 生成W参数值算法

1. 写在前面

  验证码是机器人防护(即爬虫)常用重要手段之一!在爬虫这个领域内专精某一项(验证码识别JS或者APP逆向)都是可以成为大牛存在的

传统的验证码我们都知道是静态图片的形式,它们包含一些阿拉伯数字跟字母加一些干扰(现在而言的话难度系数极低)。目前高级且复杂的验证码那是五花八门,有成熟方案的厂商也是非常之多

在这里插入图片描述

如上图所示,是使用ChatGPT时弹出的验证码!很有创意~

本次主要讲一下滑块验证码,因为目前这类验证码在大部分网站中还是比较常见的,如下所示:

极验、易盾、数美…

分析目标

aHR0cHM6Ly93d3cuZ2VldGVzdC5jb20vZGVtby9zbGlkZS1mbG9hdC5odG1s

滑动验证码的轨迹加密,是逆向的最终目的!所有厂商验证码都是以下步骤

2. 抓包分析

  首先我们打开网站抓包分析,分析各个请求。现在我们来分析下面三个可疑的接口

在这里插入图片描述

3. 接口分析

第一个URL(register-slide?t=1698396900148)带着时间戳,请求滑动验证码并返回一些重要数据,内容如下所示:

// 响应
{
    "success": 1,
    "challenge": "a2243f6f4343698c34cbe0794553e82b",
    "gt": "019924a82c70bb123aae90d483087f94",
    "new_captcha": true
}

这里有两个重要值challengegt,这两个值都是加密的,具体作用我们不知,接着向下分析

第二个URL(gettype.php)猜测是获取滑动验证类型的,因为极验有很多种验证码类型。内容如下所示:

// 响应
geetest_1698396906979({
    "status": "success",
    "data": {
        "type": "fullpage",
        "static_servers": ["static.geetest.com/", "dn-staticdown.qbox.me/"],
        "voice": "/static/js/voice.1.2.3.js",
        "click": "/static/js/click.3.0.9.js",
        "beeline": "/static/js/beeline.1.0.1.js",
        "fullpage": "/static/js/fullpage.9.1.8-bfget5.js",
        "slide": "/static/js/slide.7.9.0.js",
        "geetest": "/static/js/geetest.6.0.9.js",
        "aspect_radio": {
            "slide": 103,
            "click": 128,
            "voice": 128,
            "beeline": 50
        }
    }
})

即返回很多验证码用到的JS,其中fullpage.9.1.8.js就是滑动验证码JS,还有与之相关的JS文件

另外第二个URL请求的参数有gt参数,正是第一个URL响应返回的

在这里插入图片描述

第三个URL(get.php)请求参数包括gtwchallenge。内容如下所示:
在这里插入图片描述

其中gtchallenge均可以通过第一个URL获取拿到。这里说一下w参数,加密的一大串字符串猜测有可能是轨迹、环境检测、参数最终计算生成的

//响应
geetest_1698396904448({
    "status": "success",
    "data": {
        "theme": "wind",
        "theme_version": "1.5.8",
        "static_servers": ["static.geetest.com", "dn-staticdown.qbox.me"],
        "api_server": "api.geetest.com",
        "logo": true,
        "feedback": "https://www.geetest.com/contact#report",
        "c": [12, 58, 98, 36, 43, 95, 62, 15, 12],
        "s": "2c506476",
        "i18n_labels": {
            "copyright": "\u7531\u6781\u9a8c\u63d0\u4f9b\u6280\u672f\u652f\u6301",
            "error": "\u7f51\u7edc\u4e0d\u7ed9\u529b",
            "error_content": "\u8bf7\u70b9\u51fb\u6b64\u5904\u91cd\u8bd5",
            "error_title": "\u7f51\u7edc\u8d85\u65f6",
            "fullpage": "\u667a\u80fd\u68c0\u6d4b\u4e2d",
            "goto_cancel": "\u53d6\u6d88",
            "goto_confirm": "\u524d\u5f80",
            "goto_homepage": "\u662f\u5426\u524d\u5f80\u9a8c\u8bc1\u670d\u52a1Geetest\u5b98\u7f51",
            "loading_content": "\u667a\u80fd\u9a8c\u8bc1\u68c0\u6d4b\u4e2d",
            "next": "\u6b63\u5728\u52a0\u8f7d\u9a8c\u8bc1",
            "next_ready": "\u8bf7\u5b8c\u6210\u9a8c\u8bc1",
            "read_reversed": false,
            "ready": "\u70b9\u51fb\u6309\u94ae\u8fdb\u884c\u9a8c\u8bc1",
            "refresh_page": "\u9875\u9762\u51fa\u73b0\u9519\u8bef\u5566\uff01\u8981\u7ee7\u7eed\u64cd\u4f5c\uff0c\u8bf7\u5237\u65b0\u6b64\u9875\u9762",
            "reset": "\u8bf7\u70b9\u51fb\u91cd\u8bd5",
            "success": "\u9a8c\u8bc1\u6210\u529f",
            "success_title": "\u901a\u8fc7\u9a8c\u8bc1"
        }
    }
})

上响应面重要的可能就是sc的值

4. 滑动验证码弹出分析

  接下来请空之前的请求信息,打开滑块验证码,点击验证码按钮,弹出如下:
在这里插入图片描述

我们按照上图继续简单分析一下请求的URL接口,第一个URL(ajax.php),它的请求信息如下所示:

在这里插入图片描述

跟上面的基本一样gt、challenge、w。这里都按照前面的接口拿需要的参数值即可,唯一不同此时w值会变化,因为我们点击滑动验证码弹出一个验证码来,推测w值有轨迹信息以及一些检验

//响应
geetest_1698400310968({"status": "success", "data": {"result": "slide"}})

点击弹出滑动验证码进行了验证,成功后给出成功的结果!

第二个URL(get.php),它的请求信息跟上面一样带着gt、challenge,不过没有w。这里我们直接看返回的响应:

//响应
geetest_1698400310948({
    "gt": "019924a82c70bb123aae90d483087f94",
    "challenge": "c8c2b2ded3230049af7906ffb5344494gz",
    "id": "ac8c2b2ded3230049af7906ffb5344494",
    "bg": "pictures/gt/cd0bbb6fe/bg/a1152167f.jpg",
    "fullbg": "pictures/gt/cd0bbb6fe/cd0bbb6fe.jpg",
    "link": "",
    "ypos": 39,
    "xpos": 0,
    "height": 160,
    "slice": "pictures/gt/cd0bbb6fe/slice/a1152167f.png",
    "api_server": "https://api.geetest.com",
    "static_servers": ["static.geetest.com/", "dn-staticdown.qbox.me/"],
    "mobile": true,
    "theme": "ant",
    "theme_version": "1.2.6",
    "template": "",
    "logo": true,
    "clean": false,
    "type": "multilink",
    "fullpage": false,
    "feedback": "https://www.geetest.com/contact#report",
    "show_delay": 250,
    "hide_delay": 800,
    "benchmark": false,
    "version": "6.0.9",
    "product": "embed",
    "https": true,
    "width": "100%",
    "show_voice": true,
    "c": [12, 58, 98, 36, 43, 95, 62, 15, 12],
    "s": "62542a52",
    "so": 0,
    "i18n_labels": {
        "cancel": "\u53d6\u6d88",
        "close": "\u5173\u95ed\u9a8c\u8bc1",
        "error": "\u8bf7\u91cd\u8bd5",
        "fail": "\u8bf7\u6b63\u786e\u62fc\u5408\u56fe\u50cf",
        "feedback": "\u5e2e\u52a9\u53cd\u9988",
        "forbidden": "\u602a\u7269\u5403\u4e86\u62fc\u56fe\uff0c\u8bf7\u91cd\u8bd5",
        "loading": "\u52a0\u8f7d\u4e2d...",
        "logo": "\u7531\u6781\u9a8c\u63d0\u4f9b\u6280\u672f\u652f\u6301",
        "read_reversed": false,
        "refresh": "\u5237\u65b0\u9a8c\u8bc1",
        "slide": "\u62d6\u52a8\u6ed1\u5757\u5b8c\u6210\u62fc\u56fe",
        "success": "sec \u79d2\u7684\u901f\u5ea6\u8d85\u8fc7 score% \u7684\u7528\u6237",
        "tip": "\u8bf7\u5b8c\u6210\u4e0b\u65b9\u9a8c\u8bc1",
        "voice": "\u89c6\u89c9\u969c\u788d"
    },
    "gct_path": "/static/js/gct.b71a9027509bc6bcfef9fc6a196424f5.js"
})

返回的滑块验证码的图片等一些数据

5. 滑动验证分析

  接上面我们开始滑动滑块验证,拖动滑块到缺口处现实验证成功即可,该动作也就是我们之后要模拟的轨迹
在这里插入图片描述

携带的参数还是以前生成的gt、challenge,以及新的w值,每一次的w都是变化的,由此可以推测出w值确实包含着滑动的轨迹。如下图所示:

在这里插入图片描述

接口返回的则是成功验证后的信息,如下所示:

//响应
geetest_1698401308875({
    "success": 1,
    "message": "success",
    "validate": "57aa8ef66d49966e169d10b8eef6886e",
    "score": "1"
})

6. 轨迹生成算法实现

import math
import random
import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl


class GTrace:
    def __init__(self):
        self.__pos_x = []
        self.__pos_y = []
        self.__pos_z = []

    def __set_pt_time(self):
        """
        设置各节点的时间
        分析不同时间间隔中X坐标数量的占比
        统计结果: 1. 80%~90%的X坐标在15~20毫秒之间
                2. 10%~15%在20~200及以上,其中 [-a, 0, x, ...] 这里x只有一个,取值在110~200之间
                    坐标集最后3~5个坐标取值再50~400之间,最后一个坐标数值最大

        滑动总时间的取值规则: 图片宽度260,去掉滑块的宽度剩下200;
                        如果距离小于100,则耗时1300~1900之间
                        如果距离大于100,则耗时1700~2100之间
        """
        __end_pt_time = []
        __move_pt_time = []
        self.__pos_z = []

        total_move_time = self.__need_time * random.uniform(0.8, 0.9)
        start_point_time = 0
        __start_pt_time = [0, 0, int(start_point_time)]

        sum_move_time = 0

        _tmp_total_move_time = total_move_time
        while True:
            delta_time = random.uniform(15, 20)
            if _tmp_total_move_time < delta_time:
                break

            sum_move_time += delta_time
            _tmp_total_move_time -= delta_time
            __move_pt_time.append(int(start_point_time+sum_move_time))

        last_pt_time = __move_pt_time[-1]
        __move_pt_time.append(last_pt_time+_tmp_total_move_time)

        sum_end_time = start_point_time + total_move_time
        other_point_time = self.__need_time - sum_end_time
        end_first_ptime = other_point_time / 2

        while True:
            delta_time = random.uniform(110, 200)
            if end_first_ptime - delta_time <= 0:
                break

            end_first_ptime -= delta_time
            sum_end_time += delta_time
            __end_pt_time.append(int(sum_end_time))

        __end_pt_time.append(int(sum_end_time + (other_point_time/2 + end_first_ptime)))
        # self.__pos_z.extend(__start_pt_time)
        self.__pos_z.extend(__move_pt_time)
        self.__pos_z.extend(__end_pt_time)

    def __set_distance(self, _dist):
        """
        设置要生成的轨迹长度
        """
        self.__distance = _dist

        if _dist < 100:
            self.__need_time = int(random.uniform(500, 1500))
        else:
            self.__need_time = int(random.uniform(1000, 2000))

    def __get_pos_z(self):
        return self.__pos_z

    def __get_pos_y(self):
        _pos_y = []
        point_count = len(self.__pos_z)
        x = np.linspace(-10, 15, point_count - len(_pos_y))
        arct_y = np.arctan(x)

        for _, val in enumerate(arct_y):
            _pos_y.append(val)

        return _pos_y

    def __get_pos_x(self, _distance):
        """
        绘制标准的数学函数图像: 以 tanh 开始 以 arctan 结尾
        根据此模型用等比时间差生成X坐标
        """
        # first_val = random.uniform(-40, -18)
        # _distance += first_val
        # _pos_x = [random.uniform(-40, -18), 0]
        _pos_x = []
        self.__set_distance(_distance)
        self.__set_pt_time()

        point_count = len(self.__pos_z)
        x = np.linspace(-1, 19, point_count-len(_pos_x))
        ss = np.arctan(x)
        th = np.tanh(x)

        for idx in range(0, len(th)):
            if th[idx] < ss[idx]:
                th[idx] = ss[idx]

        th += 1
        th *= (_distance / 2.5)

        i = 0
        start_idx = int(point_count/10)
        end_idx = int(point_count/50)
        delta_pt = abs(np.random.normal(scale=1.1, size=point_count-start_idx-end_idx))
        for idx in range(start_idx, point_count):
            if idx*1.3 > len(delta_pt):
                break

            th[idx] += delta_pt[i]
            i+=1

        _pos_x.extend(th)
        return _pos_x[-1], _pos_x

    def get_mouse_pos_path(self, distance):
        """
        获取滑动滑块鼠标的滑动轨迹坐标集合
        """
        result = []
        _distance, x = self.__get_pos_x(distance)
        y = self.__get_pos_y()
        z = self.__get_pos_z()

        for idx in range(len(x)):
            result.append([int(x[idx]), int(y[idx]), int(z[idx])])

        return int(_distance), result


if __name__ == "__main__":
    _color = ["blue", "green", "red", "cyan", "magenta"]
    trace = GTrace()
    distance , res = trace.get_mouse_pos_path(100)
    print(res)

7. 生成W参数值算法

  w参数值生成需要关键参数如下:

c、s、gt、challenge、轨迹、滑动时间、滑动距离

代码比较多也比较复杂,这里直接展示最终的参数生成代码,只需传入对应的参数即可,如下图所示:

function generate_w(params){
    /**
     * 生成w, params需要传入distance, passtime, track, c, s, gt, challenge
     */
    var u = new U()["encrypt"](rt_)  // 这里的rt是一个随机值,但是需要和下面保持一致
    o = {
        "lang": "zh-cn",
        "userresponse": H(params['distance'], params['challenge']),  // 把滑动距离和challenge传入H函数,得到userresponse
        "passtime": params['passtime'],  // 滑动时间,要和轨迹里的滑动时间一致
        "imgload": 155,  // 加载时间,可以是随机值
        "aa": sign_aaa(params['track'], params['c'], params['s']),  // 传入轨迹、c、s,生成aa
        "ep": sign_ep(),  // 一些版本号和时间等信息
        "h9s9": "1816378497",  // 固定值
        "rp": md5Hash(params['gt'] + params['challenge'].slice(0, 32) + params['passtime'])  // 传入gt、challenge、passtime,md5生成rp
    }
    var l = V['encrypt'](gt['stringify'](o), rt_)
    var h = m["$_FCp"](l)
    return h + u
}

  好了,到这里又到了跟大家说再见的时候了。创作不易,帮忙点个赞再走吧。你的支持是我创作的动力,希望能带给大家更多优质的文章

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1150446.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

七人拼团模式:颠覆你的购物观念,499元产品让你赚翻天!

七人拼团模式是一种创新的消费模式&#xff0c;通过聚集消费者的购买力&#xff0c;让消费者能够以更优惠的价格购买到优质的商品。下面我们以499元的产品为例&#xff0c;详细介绍七人拼团模式的玩法规则和收益计算。 玩法规则&#xff1a; 消费者购买499元的指定产品后&…

wireshark捕获DNS

DNS解析&#xff1a; 过滤项输入dns&#xff1a; dns查询报文 应答报文&#xff1a; 事务id相同&#xff0c;flag里 QR字段1&#xff0c;表示响应&#xff0c;answers rrs变成了2. 并且响应报文多了Answers 再具体一点&#xff0c;得到解析出的ip地址&#xff08;最底下的add…

write_edif 生成 AD9361 配置的自定义IP核

将AD9361配置文件设置为顶层 设置里&#xff1b; -mode out_of_context 替换文字 综合 导出 IP 核 write_edif -security_mode all D:/tops.edfD:/tops.edf write_verilog -mode synth_stub D:/tops_stub.vD:/tops_stub.v 调用 AD9361 IP 核

OpenAI将推出ChatGPT Plus会员新功能,有用户反馈将支持上传文件和多模态

&#x1f989; AI新闻 &#x1f680; OpenAI将推出ChatGPT Plus会员新功能&#xff0c;有用户反馈将支持上传文件和多模态 摘要&#xff1a;OpenAI为ChatGPT Plus会员推出了一些新功能&#xff0c;包括上传文件、处理文件和多模态支持。用户不再需要手动选择模式&#xff0c;…

视频直播与制作软件 Wirecast Pro mac中文版软件功能

Wirecast Pro mac是一款专业的视频直播和流媒体软件&#xff0c;由Telestream公司开发和发布&#xff0c;适用于各种场景&#xff0c;包括企业会议、体育赛事、音乐演出、教育培训等。 Wirecast Pro mac软件功能 支持多摄像头连接&#xff0c;实现多角度拍摄和切换。 可导入图片…

电脑文件夹怎么压缩?分享三个简单的方法!

为了节省存储空间和便于管理&#xff0c;压缩文件夹可以将多个文件或文件夹整合成一个压缩文件&#xff0c;从而节省存储空间。此外&#xff0c;压缩文件夹还可以方便地管理文件&#xff0c;那么电脑文件夹怎么压缩呢&#xff1f;一起来看看吧~ 一、电脑自带的压缩功能 1、找到…

虹科新闻 | 高性能超声波测距仪来袭,虹科与MaxBotix正式建立合作伙伴关系

近日&#xff0c;虹科与MaxBotix正式建立合作关系&#xff0c;将共同致力于提供高精度、工业级耐用性、功能先进和有防水保护的超声波传感器&#xff0c;重新定义距离测量技术。 虹科CEO陈秋苑表示&#xff1a;“我们非常自豪地宣布&#xff0c;与MaxBotix合作&#xff0c;为我…

在WEB应用使用MyBatis(使用MVC架构模式)

2023.10.30 本章将在web应用中使用MyBatis&#xff0c;实现一个银行转账的功能。整体架构采用MVC架构模式。 数据库表的初始化 环境的初始化配置 web.xml文件的配置&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <web-app xmlns"h…

Linux多线程服务端编程:使用muduo C++网络库 学习笔记 第六章 muduo网络库简介

2010年3月作者写了一篇《学之者生&#xff0c;用之者死——ACE历史与简评》&#xff08;http://blog.csdn.net/Solstice/archive/2010/03/10/5364096.aspx&#xff0c;ACE是&#xff08;Adaptive Communication Environment&#xff09;是一个C编写的开源框架&#xff0c;用于开…

如何使用IP归属地查询API加强网络安全

引言 在当今数字化时代&#xff0c;网络安全对于个人和组织来说至关重要。恶意网络活动的威胁不断增加&#xff0c;因此采取有效的措施来加强网络安全至关重要。其中之一是利用IP归属地查询API。这个工具可以为您的网络安全策略提供宝贵的信息&#xff0c;帮助您更好地保护自己…

微软bing大声朗读文档或网页卡顿老是中断,用离线的huihui就很流畅但没那么自然

默认的xiaoxiao_online好听&#xff0c;但卡顿&#xff0c;朗读功能确实受到了网络状态的影响。 大概率是网络问题。

概念解析 | 动态非线性系统 VS 非线性系统 VS 线性系统

KaTeX parse error: \newcommand{\blue} attempting to redefine \blue; use \renewcommand 注1:本文系“概念解析”系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:动态非线性系统 VS 非线性系统 VS 线性系统。 概念解析 | 动态非线性系统 VS 非线性…

国产射频功率放大器技术指标有哪些内容

射频功率放大器是一种广泛应用于通信、雷达、卫星等领域的高频电子设备&#xff0c;其作用是将微弱的电磁信号放大到足以传输或检测的强度。射频功率放大器技术指标是衡量其性能优劣的重要标准&#xff0c;其主要内容包括以下几个方面。 频率范围&#xff1a;射频功率放大器需要…

接雨水 DP 双指针

力扣 接雨水 public class 接雨水 {public static int trap(int[] height){int res 0;int len height.length;int[] maxLeft new int[len];//存 i 左边最高的高度int[] maxRight new int[len];//存 i 右边最高的高度maxLeft[0] 0;maxRight[len - 1] 0; // DPfor (int i…

leetcode每日一题复盘(10.30~11.5)

leetcode 93 复原ip地址 这一题和上一次的回文串那题差不多&#xff0c;都是给一串数据&#xff0c;在数据中挑出符合要求的放进结果集中 整个题目可以分成三部分&#xff0c;用来判断是否符合条件的函数&#xff0c;回溯函数&#xff0c;主函数 首先是判断函数&#xff0c;这…

ubuntu安装python以及conda

切换国内镜像源 备份下 sudo cp /etc/apt/sources.list /etc/apt/sources_init.list 更换源 sudo vi /etc/apt/sources.list 开头加 deb http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ trusty-sec…

项目解读_v2

1. 项目介绍 如果使用task2-1作为示例时&#xff0c; 运行process.py的过程中需要确认 process调用的是函数 preprocess_ast_wav2vec(wav, fr) 1.1 任务简介 首个开源的儿科呼吸音数据集&#xff0c; 通过邀请11位医师标注&#xff1b; 数字听诊器的采样频率和量化分辨率分…

单目标应用:进化场优化算法(Evolutionary Field Optimization,EFO)求解微电网优化MATLAB

一、微网系统运行优化模型 微电网优化模型介绍&#xff1a; 微电网多目标优化调度模型简介_IT猿手的博客-CSDN博客 二、进化场优化算法EFO 进化场优化算法&#xff08;Evolutionary Field Optimization&#xff0c;EFO&#xff09;由Baris Baykant Alagoz等人于2022年提出&…

HarmonyOS鸿蒙原生应用开发设计- 音效库

HarmonyOS设计文档中&#xff0c;为大家提供了独特的音效库&#xff0c;开发者可以根据需要直接引用。 音效库可以分为拟物音效、系统音效、特殊效果音。具体分为提示音、UI交互音、来电铃声、闹铃、拟物音效、乐器、科幻等。 整体分类 开发者直接使用官方提供的音效库内容&a…

S32DS踩坑日记二、调试和SPI

J-Link调试需要注意以下配置&#xff1a; 一&#xff1a;从下图中Debug Configurations进入配置J-Link 二&#xff1a; 三&#xff1a; 关于初始化&#xff1a; 还有一个宏&#xff1a; FEATURE_HAS_HIGH_SPEED_RUN_MODE需要改成0&#xff0c;因为高温型号不支持1。 如果不…