js逆向-某验3代滑块验证码分析

声明

本文仅供学习参考,如有侵权可私信本人删除,请勿用于其他途径,违者后果自负!
如果觉得文章对你有所帮助,可以给博主点击关注和收藏哦!

插句个人内容:本人最近正在找工作,工作城市:广州。如果有合适的机会,希望有大佬可以内推,感激不尽。🙏
js逆向马马虎虎,app会弱一些。感兴趣的大佬可以私信本人要简历。

流程分析

本篇使用网站:

aHR0cHM6Ly93d3cuZ2VldGVzdC5jb20vZGVtby9zbGlkZS1mbG9hdC5odG1s

整个滑块验证码的流程如下,其中需要注意的接口都已经标记过。
image.png

分别解释一下用途。

  • 第一个接口

无加密参数参数,返回gtchallenge两个字段,这两个字段贯穿整个流程,十分重要。
image.png

  • 第二个接口

该接口会返回很多字段,能够使用到的也就是c,此时出现了第一个w
image.png

过去旧版的第一个w和第二个w都可以选择置空,但是现在这样做已经校验不过去了。
请求参数如下gtchallenge前面一个接口已经获得了,然后就是这个w了。
image.png

  • 第三个接口

返回了滑块类型,之前一直觉得这个接口没什么用,直接就忽略了,发现怎么都不能校验过去。
image.png
同时该接口的w值也不可忽略,还是要拿下,不可写死或置空处理。

  • 第四个接口

这个接口就是校验验证码缺口的接口了,成功了就会返回success,否则就是fail,当然还有其他的一些状态,可以根据返回的状态去排查对应的问题。

逆向分析

第一个w

第一个接口处,可以在Initiator中跳进js文件打下断点一步步跟栈。
image.png

image.png
或者直接搜索i + r,然后打下断点。
image.png
ir对应生成的值拿下来就可以还原第一个w了。

先看一下r是什么内容。
image.png
先把这个函数直接拿下来,然后运行。
image.png
报错,yCtOu未定义,寻找一下是什么东西。
image.png
将需要的部分都拿下。
重新运行,继续报错。
image.png
X没有定义,继续扣代码。这样做太慢了,可以直接把整个文件copy到本地然后慢慢补。
image.png
然后就可以很轻松的找到需要的内容了。
继续运行,window未定义。
image.png
pe是什么不知道,回到网页中看一下
image.png
image.png
缺少navigator补上就完了,需要的环境大致如下:

window = global;
navigator = {
    appName:'Netscape'
}
pe = navigator

image.png
报错复制到网页上观察一下。
image.png
看样子像一个随机数,找到函数位置。
image.png
image.png
四位随机数生成四次然后进行字符串拼接。
最后结果就出来了。
image.png

o的代码:

o = $_BFo()[$_CEGDt(1108)](de[$_CEGEy(459)](t[$_CEGEy(369)]), t[$_CEGDt(1196)]())

手动解混淆:

o = $_BFo()['encrypt1'](JSON.stringify(t['$_EJV']), t["$_CCHU"])

t[‘$_EJV’]是一个大的对象,除了gt和challenge之外,其他都可以固定。

{
    "gt": "传入gt",
    "challenge": "传入challenge",
    "offline": false,
    "new_captcha": true,
    "product": "float",
    "width": "300px",
    "https": true,
    "api_server": "apiv6.geetest.com",
    "protocol": "https://",
    "type": "fullpage",
    "static_servers": [
        "static.geetest.com/",
        "static.geevisit.com/"
    ],
    "beeline": "/static/js/beeline.1.0.1.js",
    "voice": "/static/js/voice.1.2.4.js",
    "click": "/static/js/click.3.1.0.js",
    "fullpage": "/static/js/fullpage.9.1.9-r8k4eq.js",
    "slide": "/static/js/slide.7.9.2.js",
    "geetest": "/static/js/geetest.6.0.9.js",
    "aspect_radio": {
        "slide": 103,
        "click": 128,
        "voice": 128,
        "beeline": 50
    },
    "cc": 20,
    "ww": true,
    "i": "-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1!!-1"
}

t[“$_CCHU”]则是上一次省的16位随机数,需要和生成r部分保持一致的值。

然后将$_BFo()函数拿下来就得到结果。
image.png

i就简单了,将o生成的数组变成字符串。
image.png
还是缺啥补啥,最终第一个w结果。
image.png

第二个w

同样使用Initiator追溯,向上寻找堆栈,慢慢分析也可以找到。
image.png
不过比较麻烦,可以直接搜索var n = {}
调试发现断点没有经过t[$_CFEEo(1109)]();w还没有生成,所以w肯定在该函数之前生成了。
image.png
image.png

函数很长,直接看return处。
最终定位到。
image.png

手动解混淆:

p['$_HEt'](c["encrypt"](r, i["$_CCHU"]()));

实际上和第一个w的加密一样
重点看一下r,r是一个字符串,反序列化

{
    "lang": "zh-cn",
    "type": "fullpage",
    "tt": "MZ(*((1(j(CM7((",
    "light": -1,
    "s": "c7c3e21112fe4f741921cb3e4ff9f7cb",
    "h": "321f9af1e098233dbd03f250fd2b5e21",
    "hh": "39bd9cad9e425c3a8f51610fd506e3b3",
    "hi": "09eb21b3ae9542a9bc1e8b63b3d9a467",
    "vip_order": -1,
    "ct": -1,
    "ep": {
        "v": "9.1.9-r8k4eq",
        "te": false,
        "$_BBp": true,
        "ven": "Google Inc. (Intel)",
        "ren": "ANGLE (Intel, Intel(R) Iris(R) Xe Graphics (0x000046A6) Direct3D11 vs_5_0 ps_5_0, D3D11)",
        "fp": [
            "move",
            744,
            147,
            1707040727652,
            "pointermove"
        ],
        "lp": [
            "up",
            672,
            82,
            1707040728689,
            "pointerup"
        ],
        "em": {
            "ph": 0,
            "cp": 0,
            "ek": "11",
            "wd": 1,
            "nt": 0,
            "si": 0,
            "sc": 0
        },
        "tm": {
            "a": 1707040721021,
            "b": 1707040721290,
            "c": 1707040721290,
            "d": 0,
            "e": 0,
            "f": 1707040721021,
            "g": 1707040721056,
            "h": 1707040721056,
            "i": 1707040721056,
            "j": 1707040721122,
            "k": 1707040721089,
            "l": 1707040721122,
            "m": 1707040721286,
            "n": 1707040721288,
            "o": 1707040721292,
            "p": 1707040721503,
            "q": 1707040721503,
            "r": 1707040721504,
            "s": 1707040721562,
            "t": 1707040721562,
            "u": 1707040721564
        },
        "dnf": "dnf",
        "by": 0
    },
    "passtime": 1190827,
    "rp": "6fc9d795969c2c344ce5bc11e50c9916",
    "captcha_token": "1265749785",
    "otpj": "jm4jwcx7"
}

经过测试发现,其他值均可固定,但是rp的加密过程passtime参与了,所以要注意保持一致。
再看rp如何生成,向上寻找。(代码比较混乱,我也找了半天o(╥﹏╥)o)
image.png
image.png

使用到了gt、challenge以及passtime,加密长度32位,盲猜一波md5。 ![image.png](https://cdn.nlark.com/yuque/0/2024/png/39047339/1707042842696-bb495516-f94b-4b69-b857-e2177b168e7b.png#averageHue=%23f6f5f4&clientId=u7beac4ef-06cb-4&from=paste&height=367&id=u837eeb7b&originHeight=459&originWidth=778&originalType=binary&ratio=1.25&rotation=0&showTitle=false&size=52709&status=done&style=stroke&taskId=uaad1ca3c-47d4-418b-892d-69fb067be2b&title=&width=622.4) 完全一致,rp就已经生成了。 i"$_CCHU"依然是第一次生成的16位随机字符串,也需要使用同样的秘钥。不然会出现 param decrypt error`的错误。

至此w生成完毕。

第三个w

这个w网上有很多现成的文章了,直接搜索"\u0077"即可定位,也可以选择上面的方法,跟堆栈。
image.png

这个w其实和上面的加密方式一样,没什么好说的,这里就不展开了。
说一下不同的地方。

{
    "lang": "zh-cn",
    "userresponse": "9777999999979766a",
    "passtime": 266,
    "imgload": 73,
    "aa": "K,,(!!Msssyyt!)!)ttusYsx(!!($)/(/0101010110$nd)c",
    "ep": {
        "v": "7.9.2",
        "$_BIE": false,
        "me": true,
        "tm": {
            "a": 1707046714483,
            "b": 1707046715148,
            "c": 1707046715148,
            "d": 0,
            "e": 0,
            "f": 1707046714484,
            "g": 1707046714533,
            "h": 1707046714533,
            "i": 1707046714533,
            "j": 1707046714614,
            "k": 1707046714574,
            "l": 1707046714614,
            "m": 1707046714724,
            "n": 1707046714741,
            "o": 1707046715150,
            "p": 1707046715369,
            "q": 1707046715369,
            "r": 1707046715370,
            "s": 1707046715434,
            "t": 1707046715434,
            "u": 1707046715435
        },
        "td": -1
    },
    "h9s9": "1816378497",
    "rp": "6ca7d8a547390ce95dc57399fd88f50d"
}

userresponse 、aa和rp是需要处理的部分,其他固定即可。

  • userresponse 部分

image.png

H(滑动距离,34位challenge)

将H函数扣下来就可以实现该算法了。

  • aa部分

image.png
此时的aa已经生成了,向上找一层。
image.png

n[$_DAAAU(985)][$_CJJJU(1075)]有三个参数,分别是轨迹加密得到的结果,接口的cs(和34位challenge为一个接口)
然后将剩余代码补齐即可得到结果。
十次成功率80%

image.png

参考

  • 【验证码逆向专栏】某验三代滑块验证码逆向分析
  • 【验证码逆向专栏】某验四代滑块验证码逆向分析
  • js逆向案例-zzjg之jy3/ast/woff.2
  • 极验滑块验证码破解与研究(四):滑块轨迹构造

最后

最近开通了个人公众号,有一些被博客下架的文章后续也会同步上去。
大佬们可以关注一波。
微信公众号.png

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

alibabacloud学习笔记05(小滴课堂)

高并发下的微服务存在的问题 高并发下的微服务容错方案 介绍什么是分布式系统的流量防卫兵Sentinel 微服务引入Sentinel和控制台搭建 每个服务都加上这个依赖。 启动方式: 讲解AliababCloud微服务整合Sentinel限流配置实操 我们在order和video模块都加上。 分别启动…

第三百零六回

文章目录 1. 概念介绍2. 思路与方法2.1 实现思路2.2 实现方法 3. 示例代码4. 内容总结 我们在上一章回中介绍了"分享三个使用TextField的细节"沉浸式状态样相关的内容,本章回中将介绍如何创建单例模式.闲话休提,让我们一起Talk Flutter吧。 1.…

回归预测 | Matlab实现POA-CNN-LSTM-Attention鹈鹕算法优化卷积长短期记忆网络注意力多变量回归预测(SE注意力机制)

回归预测 | Matlab实现POA-CNN-LSTM-Attention鹈鹕算法优化卷积长短期记忆网络注意力多变量回归预测(SE注意力机制) 目录 回归预测 | Matlab实现POA-CNN-LSTM-Attention鹈鹕算法优化卷积长短期记忆网络注意力多变量回归预测(SE注意力机制&…

超时引发的牛角尖二(hystrix中的超时)

至今我都清楚记得自己负责的系统请求云上关联系统时所报的异常信息。为了解决这个异常,我坚持让这个关联系统的负责人查看,并且毫不顾忌他的嘲讽和鄙视,甚至无视他烦躁的情绪。不过我还是高估了自己的脸皮,最终在其恶狠狠地抛下“…

智能决策的艺术:探索商业分析的最佳工具和方法

文章目录 一、引言二、商业分析思维概述三、数据分析在商业实践中的应用四、如何培养商业分析思维与实践能力五、结论《商业分析思维与实践:用数据分析解决商业问题》亮点内容简介作者简介目录获取方式 一、引言 随着大数据时代的来临,商业分析思维与实…

前端小案例——滚动文本区域(HTML+CSS, 附源码)

一、前言 实现功能: 这个案例实现了一个具有滚动功能的文本区域&#xff0c;用于显示长文本内容&#xff0c;并且可以通过滚动条来查看完整的文本内容。 实现逻辑&#xff1a; 内容布局&#xff1a;在<body>中&#xff0c;使用<div>容器创建了一个类名为listen_t…

vue3 之 组合式API—watch函数

watch函数 作用&#xff1a;侦听一个或者多个数据的变化&#xff0c;数据变化时执行回调函数 两个额外参数&#xff1a; 1.immediate&#xff08;立即执行&#xff09;2.deep&#xff08;深度侦听&#xff09; 场景&#xff1a;比如选择不同的内容请求后端不同数据时 如下图 …

【算法与数据结构】300、674、LeetCode最长递增子序列 最长连续递增序列

文章目录 一、300、最长递增子序列二、674、最长连续递增序列三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、300、最长递增子序列 思路分析&#xff1a; 第一步&#xff0c;动态数组的含义。 d p [ i ] dp[i] dp[i…

IDEA 配置以及一些技巧

1. IDEA设置 1.1 设置主题 1.2 设置字体和字体大小 1.3 编辑区的字体用ctrl鼠标滚轮可以控制大小 1.4 自动导包和优化多余的包 1.5 设置编码方式 1.6 配置 maven 1.7 设置方法形参参数提示 1.8 设置控制台的字体和大小 注意&#xff1a;设置控制台字体和大小后需要重启IDEA才会…

异步解耦之RabbitMQ(二)_RabbitMQ架构及交换机

异步解耦之RabbitMQ(一)-CSDN博客 RabbitMQ架构 RabbitMQ是一个基于AMQP&#xff08;Advanced Message Queuing Protocol&#xff09;协议的消息代理中间件&#xff0c;它通过交换机和队列实现消息的路由和分发。以下是RabbitMQ的架构图&#xff1a; Producer&#xff08;生产…

LabVIEW风力发电机在线监测

LabVIEW风力发电机在线监测 随着可再生能源的发展&#xff0c;风力发电成为越来越重要的能源形式。设计了一个基于控制器局域网&#xff08;CAN&#xff09;总线和LabVIEW的风力发电机在线监测系统&#xff0c;实现风力发电机的实时监控和故障诊断&#xff0c;以提高风力发电的…

ArrayList在添加元素时报错java.lang.ArrayIndexOutOfBoundException

一、添加单个元素数组越界分析 add源码如下 public boolean add(E e) {ensureCapacityInternal(size 1); // Increments modCount!!elementData[size] e;return true; } size字段的定义 The size of the ArrayList (the number of elements it contains). ArrayList的大…

【面试官问】Redis 持久化

目录 【面试官问】Redis 持久化 Redis 持久化的方式RDB(Redis DataBase)AOF(Append Only File)混合持久化:RDB + AOF 混合方式的持久化持久化最佳方式控制持久化开关主从部署使用混合持久化使用配置更高的机器参考文章所属专区

【Django】Cookie和Session的使用

Cookies和Session 1. 会话 从打开浏览器访问一个网站&#xff0c;到关闭浏览器结束此次访问&#xff0c;称之为一次会话。 HTTP协议是无状态的&#xff0c;导致会话状态难以保持。 Cookies和Session就是为了保持会话状态而诞生的两个存储技术。 2. Cookies 2.1 Cookies定…

机器学习系列——(六)数据降维

引言 在机器学习领域&#xff0c;数据降维是一种常用的技术&#xff0c;旨在减少数据集的维度&#xff0c;同时保留尽可能多的有用信息。数据降维可以帮助我们解决高维数据带来的问题&#xff0c;提高模型的效率和准确性。本文将详细介绍机器学习中的数据降维方法和技术&#…

【Linux取经路】进程控制——程序替换

文章目录 一、单进程版程序替换看现象二、程序替换的基本原理三、程序替换接口学习3.1 替换自己写的可执行程序3.2 第三个参数 envp 验证四、结语一、单进程版程序替换看现象 #include <stdio.h> #

Vue学习笔记之组件基础

1、组件的定义 一般将 Vue 组件定义在一个单独的 .vue 文件中&#xff0c;称做单文件组件&#xff1b;当然也可以将组件直接定义在js文件中&#xff0c;如下js代码&#xff0c;定义一个组件BlogPost&#xff0c;通过props定义对外暴露属性title&#xff0c;父组件传递title&am…

List的模拟实现 迭代器

———————————————————— list与vector相比&#xff0c;插入、删除等操作实现的成本非常低&#xff0c;如果在C语言阶段熟悉理解过链表&#xff0c;那么现在实现起来list就显得比较简单&#xff0c;可以说操作层面上比vector更简洁&#xff0c;因为list没有扩…

C++ 动态规划 线性DP 最长上升子序列

给定一个长度为 N 的数列&#xff0c;求数值严格单调递增的子序列的长度最长是多少。 输入格式 第一行包含整数 N 。 第二行包含 N 个整数&#xff0c;表示完整序列。 输出格式 输出一个整数&#xff0c;表示最大长度。 数据范围 1≤N≤1000 &#xff0c; −109≤数列中的数…

istio 限流

#详细参数看官网&#xff0c;我参数就不解释https://istio.io/latest/docs/reference/config/networking/destination-rule/cat << EOF > dr.yaml apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata:name: my-testnamespace: demon spec:hos…
最新文章