【验证码逆向专栏】最新某度旋转验证码 v2 逆向分析

news2024/11/25 0:56:57

01

声明

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

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

前言

七月底有爬友反馈,某度旋转验证码 v2 的加密算法更新了。对各个站点测试后发现,站长后台的算法及请求参数更新了,因为近期也发过某度系列验证码的文章,为了避免失效部分对粉丝的误导,现再次对相关算法进行逆向分析。

逆向目标

  • 目标:某度旋转验证码 v2,fs 参数逆向分析
  • 网站:aHR0cHM6Ly96aXl1YW4uYmFpZHUuY29tL2xpbmtzdWJtaXQvdXJs
  • 加密算法:AES、MD5、SHA1、SHA256、SHA512、SHA3

01

抓包分析

init 接口有四个请求参数,ver 为固定值 1,_ 为 13 位时间戳,refer 为该网站的 url,ak 是固定值,相当于盾 ID,不同网站不一样,很多厂商的验证码也都会有这么一个参数:

02

init 接口响应返回的参数中 astk 在后续请求中会用到:

03

填写链接地址,点击提交,即会弹出旋转验证码,此时抓包到 style 接口, 请求参数中,tk 参数是 init 接口响应返回的, _ 是时间戳,其他的都是定值:

04

style 接口响应返回的参数中,path 即旋转验证码的底图,backstr 是生成 fs 参数值的关键部分:

05

转动验证码后,会抓包到 log 接口,请求参数中,ak 为盾 ID,tkas 均是之前的接口响应返回的,fs 参数需要逆向分析,由轨迹、旋转角度、asbackstr 参数等加密生成。最新的 v2 较之前多了一个浏览器指纹参数 fuid,不同浏览器的值不一致,相同浏览器的值短时间内不会改变:

# "Edge": "FOCoIC3q5fKa8fgJnwzbE67EJ49BGJeplOzf+4l4EOvDuu2RXBRv6R3A1AZMa49I27C0gDDLrJyxcIIeAeEhD8JYsoLTpBiaCXhLqvzbzmvy3SeAW17tKgNq/Xx+RgOdb8TWCFe62MVrDTY6lMf2GrfqL8c87KLF2qFER3obJGnCfjdYr2J6wEsox+bQtrTEGEimjy3MrXEpSuItnI4KDyOhCNLIvGcJ9TrqWJqhR97vnz96e18U/ntNdoDIMLzy/6P9rOWdIYWmTQAeeG69438PcpN++VzDmPtrURexo5YYWpVFkRs9k5n0AC3djzGRuXr1+yVZXtGGofFzxBmdr9HtaANtMMPysO2XXACLNUNkLLWJN9fLc3OAWce48tpeQQ2ufd7knx4Oo6OM0PpOVDwQcezbGX85VEmymh7f7M5kIyVl+w5yn2AY4BmLrEWEsyw9SzzW8eHQ5zYIUjiw9hXi7OMMoCL+ptOvZYbHZs0R5qLHmmDCW1M8MMX5yyJF0BV1dQvKslKnAJwZu4XCbsXKn3UXosU1U30/poiN2VeXkBPeo8+Xj/4BIoC2I7WZ6zkFa/Uwd5SvC91kvff2a/Z4OwyTQNM7ES9HmRhChdWg0SJ2xEs1aiXAit16RiTlf82esJH+X/j52G7R3ErwQeJT3QoDv64R2702+8NbGIjf1ZOfxhUCpmJqV4jeHSaHRmnKgJZsK91XhhrdJKXdsbt3phIOpxGLupULr2K+v1DNdId8/HuE0776+tTpUl7shVCeM/XWrdkhru42pifhiujnDhIblsLt8grnj5/GRqcD6ZPAXqJW3lLc0/ub9jXgvXK/EczRgKl+7/tTBkPTCrUVtajA0luHLQOrVsXuN1v0/PR3i09SuFzZJkJBKE3M6rYvPttK9NQiBxhxYWDhX82uQu2XK8+8oU3gxCIaJwsQmX/It0kaZ45PZHFqtD40uOX0sXuThvUin4N4RSI2G9d7jPkj5hbBFquQKM4S+tDJ34jmplOTrqqKT7PPVfrdgd4OkK13pEy86BsJ8M0gKXgtivUgM8Bjl1m/pkg0SuDyntWLdrmMxcZYvgySvSSwQ2Qtm8EkKHIMyR/XgfHnpX5vadGpRMro2qaE8u+x8w1gJHIRKib2u6Q1JtQiZE1Rde/vRx8xKfg6uYR37n0BvfgJE5+KbeuwCyAvJRGUA2fpt0VClIfV0m2PRG7bvH00OODKY6cFi7NgWAK6Jc1G4Ugkfp7W8I0ZYwNpTTxVoxIIBF37aBhyiPWPAOeYXBqA"
# Chrome: "FOCoIC3q5fKa8fgJnwzbE67EJ49BGJeplOzf+4l4EOvDuu2RXBRv6R3A1AZMa49IZbsw3/U3NYEqD0LjhKzgMn8fIES5OyXlgwN5I+F8wHowpWWfXkQJw8/9AsO5Q2VOvnc2JlHGIlGS8Vq2z4OA80lVLon08EG3PPxkVZGm39fDi2exK9NDrZB+tNLX6ISxE5PzBgXpCOJ6oP9F1B0OBWaCMD/m01n8FhdDNCvP8EO5cetU79+pgL+ECRdtN6V4VElGJE0mxV4+4Zq4Jf/Xe/q8CkoTNf7Ti1glGYmN32UM9dg0uX+VzET/mmTRe4Dt+MuVHSzsI/bKCjPbpaOqfM8UsxDJUG9hyrGZ8QHa1kC04aTxkkTxI275dv3+ijS1zkWOdjFiy1eD/0R8HcRWYp2smk9EmXBkIAHL4H0gC9lQtdjey37/kyl4JA9Fp4zjuVO0arsD8MrGy1divU++B1KdawGqXpnbOcHZ3CctNGrpgmswaScc6DNWb34jFj0X3tdRE0uuHuqiYa5BClFS2V0TCorKi4CobgR419xWaX8IKLJiaNNLOShWdZdlQO2DXXVxcinzKHqUvWTYx45jsiUVlY78AHQGol6CJLQQ8Q797MShlazvdSwPXgJP5z0uMJp9L+3x/Y2GGhW5sit55sFuMXafALTYf69FCUw5+nVIRs150a4+KK+tA0Eu7Itiu3dM2pflKYWwPE6SDZznyejQ08vd+HpXRB/zhfSUcIYlT5gFEiMIA6SXZCo/XT7vC8D3gHdN+yr46XdVol/WkjFQof0JQH/Vhjj5C1xcAyNxq/VVBT01vdKk6zo6c08e84FEVMLd0m3XWtjFOYu7wRI7lldw2pSxyGnWvA4aiYWcWvvKNJtqB8wHqc5RPr9KRzhbxJnTM5K1vTx4xT/1ZUR3pU7nQKZo/4kP9XycIr/Jg3XMRSnqCBUJlagKAFPt2HF0LdsSk4WWcldb97Ar584nVGbSjPXEUVH0VgbUEm+dADzPoLP+NPMYOyhwgfADiqWaXyKT4UNESYXsPBkdGk6mLCaNSEQsDN1G2677Se3qjzDcyXBnEmHEFptRbmyJzKJ73veHPqfFYtsHO9jH0XnhYk8zKdRuqQ7dnuNIDwxm3UCPo22uFI0ZcgPvQm01s+8jYiMEFJDVra9jWyWTdMpMuhT3p2yYLf70CvUwIkw="

过一段时间,fuid 的值是会变化的:

06

fuidfingerprint.js 文件中生成,由 user-agent、canvas、plugins 等浏览器属性构成,可以逐个跟栈分析,F 方法是对 URI 进行编码,即 encodeURIComponent()U 方法为 AES 加密,加密模式为 ECB,填充方式为 PKCS7,key 为固定值:

  • ECB:Electronic Code Book(电子码本模式),是一种基础的加密方式,密文被分割成分组长度相等的块(不足补齐),然后单独一个个加密,一个个输出组成密文;
  • PKCS7:在填充时首先获取需要填充的字节长度 = 块长度 - (数据长度 % 块长度), 在填充字节序列中所有字节填充为需要填充的字节长度值。

07

相关环境:

{
    "userAgent": "Mozilla%2F5.0%20(Windows%20NT%2010.0%3B%20WOW64)%20AppleWebKit%2F537.36%20(KHTML%2C%20like%20Gecko)%20Chrome%2F86.0.4240.198%20Safari%2F537.36",
    "canvas": "2a5a8f1d4173bc025dab2d50816ba134",
    "language": "zh-CN",
    "colorDepth": "24",
    "deviceMemory": "8",
    "hardwareConcurrency": "8",
    "screenResolution": "1920%2C1080",
    "availableScreenResolution": "1032%2C1920",
    "timezoneOffset": "-480",
    "timezone": "",
    "sessionStorage": "true",
    "localStorage": "true",
    "indexedDb": "true",
    "addBehavior": "false",
    "openDatabase": "true",
    "cpuClass": "",
    "platform": "Win32",
    "plugins": "null",
    "webgl": "1af17d7a73799a2516da34f3b37bb363",
    "webglVendorAndRenderer": "Google%20Inc.~ANGLE%20(NVIDIA%20NVS%205400M%20Direct3D11%20vs_5_0%20ps_5_0)",
    "adBlock": "false",
    "hasLiedLanguages": "false",
    "hasLiedResolution": "false",
    "hasLiedOs": "false",
    "hasLiedBrowser": "false",
    "touchSupport": "0%2Cfalse%2Cfalse",
    "fonts": "42",
    "audio": "null"
}

验证码未转正,响应返回的 op 值为 3:

08

验证码转正,则响应返回的 op 值为 1:

09

urlsubmit 接口的请求参数 dstklog 接口响应返回的,url 为提交的链接地址:

10

以下是目前遇到过的链接提交之后的几种结果:

  1. 提交成功 —> {“over”:0, “status”:0}
  2. 验证码信息有误 —> {“status”:101}
  3. 未输入提交链接 —> {“status”:2}
  4. 未添加 cookies —> not allowed

逆向分析

log 接口有一个加密参数 fs,通过跟栈会发现,和之前一样,fs 参数的加密位置在 mkd_v2.js 这个文件里面,跟进去之后,直接 ctrl + f 搜索 fs = ,有两个结果,这里就是生成 fs 参数的关键位置:

11

先分析第一个 n.fs

n.fs = (0, f.Li)(JSON.stringify(this.rzData), this.secondHandle)

JSON.stringify(this.rzData) 是将 this.rzData 转换成字符串形式,在第 12871 行打下断点,this.rzDatabackstr 及鼠标轨迹等参数构成,backstr 参数是 style 接口响应返回的,ac_c 是旋转比例,现在的底图是 AI 生成的,和之前的风景图不一样了,识别模型最好重新训练,轨迹和旧版不一样,需要模拟构造不能直接固定,且校验相对严格,轨迹中有个参数很重要:

12

向上跟栈,即可定位到计算 ac_c 的位置:

Number((this.distance / (e - 52)).toFixed(2))

13

this.distance 是滑动的距离,e 为定值 290,实际上就是滑动条能够滑动的最大长度:

14

this.secondHandle 主要包含 as 参数,该参数是 init 接口响应返回的:

15

JSON.stringify(this.rzData)this.secondHandle 作为参数传递到 f.Li 函数中,进行加密处理之后生成了第一个 fs 值:

16

鼠标选中 f.Li 后跟进去:

17

encrypt(key, word, !0) 即关键加密函数:

18

先来分析下传入的三个参数,!0 为 true,word 参数即 JSON.stringify(this.rzData)key 参数定义在第 13312 行,旧版 v2 的 fs 参数是 AES 加密,key 为 "as + appsapi2",新版的 key 经过 getNewKey(params.as) 方法做了进一步的处理,params.asinit 接口响应返回的,跟进到 getNewKey 函数中去:

19

taset + "appsapi2"r 取了 e 的最后一位字符,下面是一段 switch…case 语句,根据 r 的值选择相应的加密算法,截取加密后的字符串的前 16 位,即是 key 值,目前主要碰到过三种加密算法,MD5、SHA3-256 以及 SHA3-512,以下通过 JavaScript 对其进行复现:

const CryptoJS = require('crypto-js');

function getNewKey(as){
     /**
     * encryptedStr(SHA3-256) ---> f25f1614appsapi2
     * encryptedValue ---> 49d3a9685870cc30f63330b8136c7adfdb8859c6b538308992a1c9a456db2e59
     *
     * encryptedValue(MD5) ---> 5e4ebc8cappsapi2
     * encryptedValue ---> c30b8b5289e46489598de382a658cc7f
    */
    var encryptedStr = as + "appsapi2";
    var r = as.substr(as.length - 1, 1);
    switch (true) {
        case ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'a', 'b', 'c', 'd', 'e', 'f', 'g'].includes(r):
            encryptedValue = CryptoJS.MD5(encryptedStr).toString();
            break;
        case ['H', 'I', 'J', 'K', 'L', 'M', 'N', 'h', 'i', 'j', 'k', 'l', 'm', 'n'].includes(r):
            encryptedValue = CryptoJS.SHA1(encryptedStr).toString(CryptoJS.enc.Hex);
            break;
        case ['O', 'P', 'Q', 'R', 'S', 'T', 'o', 'p', 'q', 'r', 's', 't'].includes(r):
            encryptedValue = CryptoJS.SHA256(encryptedStr).toString(CryptoJS.enc.Hex);
            break;
        case ['U', 'V', 'W', 'X', 'Y', 'Z', 'u', 'v', 'w', 'x', 'y', 'z'].includes(r):
            encryptedValue = CryptoJS.SHA512(encryptedStr).toString(CryptoJS.enc.Hex);
            break;
        case ['0', '1', '2', '3', '4'].includes(r):
            encryptedValue = CryptoJS.SHA3(encryptedStr, { outputLength: 256 }).toString(CryptoJS.enc.Hex);
            break;
        case ['5', '6', '7', '8', '9'].includes(r):
            encryptedValue = CryptoJS.SHA3(encryptedStr, { outputLength: 512 }).toString(CryptoJS.enc.Hex);
            break;
    default:
        encryptedValue = e;
    }
    var key = encryptedValue.slice(0, 16);
    return key;
}

var as = "7d7f8765";
var key = getNewKey(as);
console.log('key:', key);

SHA3-512 结果校验一致:

20

至此 key 参数分析完了,回到第 13315 行,跟进到加密函数 encrypt 中,和旧版 v2 一样,是 AES 加密,不同点在于:1. 旧版的 key = as + “appsapi2”,新版 key 的值为 as + “appsapi2” 加密后取前 16 位字符;2. 旧版的填充方式 padding 为 Pkcs7,新版的为 ZeroPadding:

  • PKCS7:在填充时首先获取需要填充的字节长度 = 块长度 - (数据长度 % 块长度), 在填充字节序列中所有字节填充为需要填充的字节长度值;
  • ZeroPadding:在填充时首先获取需要填充的字节长度 = 块长度 - (数据长度 % 块长度), 在填充字节序列中所有字节填充为 0 。

21

接下来分析第二个 n.fs,也就是最终的 fs 参数的值,同样是经过 f.Li 函数加密生成,不过传入的两个参数发生了改变,common_en 的值即第一个 n.fs 的值,backstr 以及 as 是前面接口响应返回的值,key 即上文所述的 AES 算法加密的密钥值:

n.fs = (0, f.Li)(JSON.stringify(
{
    common_en: n.fs,
    backstr: this.cfg.backstr
}), {
    key: this.newKey,
    as: this.cfg.as,
    method: "aes-ecb"
})

在第 12873 行打下断点,此时第一个 n.fs 参数的值生成了:

22

在第 12882 行打下断点,此时生成了第二个 n.fs 参数的值,即最终的 fs 参数的值,对比验证一下:

23

结果验证

24

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

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

相关文章

使用requests如何实现自动登录

不知道大家有没有注意到,好多网站我们登录过后,在之后的某段时间内访问该网页时,不会给出请登录的提示,时间到期后就会提示请登录!这样在使用爬虫访问网页时还要登录,打乱我们的节奏,那么如何使…

ISC 2023 大会成功举办,向量数据库公司 Zilliz 成大模型论坛焦点

近日,第十一届互联网安全大会(ISC 2023)在北京盛大开幕。大会由 ISC 互联网安全大会组委会、中国互联网协会、中国网络空间安全协会、全国工商联大数据运维(网络安全)委员会、中国人工智能学会、中国软件行业协会、中国企业联合会、360 互联网安全中心主办;中国通信企业协…

使用阿里云服务器部署和使用GitLab

本文阿里云百科分享使用阿里云服务器部署和使用GitLab,GitLab是Ruby开发的自托管的Git项目仓库,可通过Web界面访问公开的或者私人的项目。本教程介绍如何部署和使用GitLab。 目录 准备工作 部署GitLab环境 使用GitLab 登录GitLab 生成密钥对文件并…

HoloLens 2设备MR 应用交互设计

AR 眼镜实现了虚拟世界与现实世界的融合,完成屏幕的“跨越”,人机交互设计也从二维平面迈向三维世界。目前,MR 应用的人机交互界面仍然处于早期发展阶段,各种理念和方法仍处于逐步形成与应用阶段,低成本地完成使用者从…

记录一下Java实体转json字段顺序问题

特殊需求,和C交互他们那边要求字段顺序要和他们定义的一致(批框架) 如下: Data public class UserDto {private String name;private Integer age;private String addr; }未转换前打印: 转换后打印: 可以看到转换为json顺序打印…

第9届Python编程挑战赛北京赛区复赛真题剖析-2023年全国青少年信息素养大赛

[导读]:超平老师计划推出《全国青少年信息素养大赛Python编程真题解析》50讲,这是超平老师解读Python编程挑战赛系列的第16讲。 全国青少年信息素养大赛(原全国青少年电子信息智能创新大赛)是“世界机器人大会青少年机器人设计与…

Spring与Spring Bean

Spring 原理 它是一个全面的、企业应用开发一站式的解决方案,贯穿表现层、业务层、持久层。但是 Spring 仍然可 以和其他的框架无缝整合。 Spring 特点 轻量级 控制反转 面向切面 容器 框架集合 Spring 核心组件 Spring 总共有十几个组件核心容器(Spring core) S…

02.Deep Visual-Semantic Alignments for Generating Image Descriptions

目录 前言泛读摘要IntroductionRelated Work小结 精读Model3.1 学习对齐视觉与语言数据图片表征句子表征对齐目标损失函数解码文本片段对齐图像 MRNN生成描述优化 实验结论 代码 前言 本课程来自深度之眼《多模态》训练营,部分截图来自课程视频。 文章标题&#xf…

湘大 XTU OJ 1290 Alice and Bob 题解(非常详细):字符串 分类讨论 简单模拟

一、链接 1290 Alice and Bob 二、题目 题目描述 Alice和Bob玩剪刀-石头-布的游戏,请你写个程序判断一下比赛的结果。 输入 第一行是一个整数K,表示样例的个数。 以后每行两个单词,rock表示石头,paper表示布,scis…

ETL技术入门之ETLCloud初认识

首先ETL是什么? ETL代表“Extract, Transform, Load”,是一种用于数据集成和转换的过程。它在数据管理和分析中扮演着重要的角色。下面我们将分解每个步骤: Extract(抽取): 这一步骤涉及从多个不同的数据源…

小说推文怎么做详细教程。小说推文项目拆解及分享

科思创业汇 大家好,这里是科思创业汇,一个轻资产创业孵化平台。赚钱的方式有很多种,我希望在科思创业汇能够给你带来最快乐的那一种! 如何制作小说推文的详细教程! 我做自媒体已经五年了,在自媒体行业也…

YOLOv5、YOLOv8改进:MobileViT:轻量通用且适合移动端的视觉Transformer

MobileViT: Light-weight, General-purpose, and Mobile-friendly Vision Transformer 论文:https://arxiv.org/abs/2110.02178 1简介 MobileviT是一个用于移动设备的轻量级通用可视化Transformer,据作者介绍,这是第一次基于轻量级CNN网络性…

CMake语法中的PUBLIC、PRIVATE、INTERFACE关键字含义

在CMake语法中,经常见到PUBLIC、PRIVATE、INTERFACE关键字,它们是什么意思呢?下面举例说明。 如上图,说明如下: RIVATE:私有的。生成 libhello-world.so时,只在 hello_world.c 中包含了 hello.h&#xff0…

C# 随机法求解线性规划问题 蒙特卡洛

线性规划问题: max3x12x2 x12x2<5 2x1x2<4 4x13x2<9 x1>0 x2>0 正确的结果:x11.5; x21, max z6.5 Random random1 new Random(DateTime.Now.Millisecond);Random random2 new Random(DateTime.Now.Millisecond*DateTime.Now.Millisecond);double max-9999,x1…

【electron】electron项目创建的方式:

文章目录 【1】npm init quick-start/electron&#xff08;推荐&#xff09;【2】 克隆仓库&#xff0c;快速启动【3】 通过脚手架搭建项目【4】 手动创建项目 【Electron官网】https://www.electronjs.org/zh/docs/latest/api/app 【1】npm init quick-start/electron&#xf…

六 动手学深度学习v2 ——权重衰退+dropout

1. 权重衰退 最常见的用来处理过拟合的方法 使用均方范数作为硬性限制 使用均方范数作为软性限制 总结&#xff1a; 正则化是处理过拟合的常用方法&#xff1a;在训练集的损失函数中加入惩罚项&#xff0c;以降低学习到的模型的复杂度。 保持模型简单的一个特别的选择是使用…

PostgreSQL查询慢sql原因和优化方案

PostgreSQL sql查询慢优化方案有一下几种解决方案&#xff1a; 1.关闭会话 查询慢sql的执行会话&#xff0c;关闭进程。 查看数据库后台连接进程 SELECT count(*) FROM pg_stat_activity;SELECT * FROM pg_stat_activity; 查看数据库后台连接进程&#xff0c;但是此条SQL不…

稳定的亚马逊测评需要具备哪些条件

自养号测评已经在跨境电商领域变得司空见惯。绝大部分卖家都已开始对店铺产品进行自测评。虽然平台和消费者对测评补单持反感态度&#xff0c;但在普遍测评的环境下&#xff0c;不参与测评可能会导致被市场淘汰。 目前&#xff0c;为了提高安全性&#xff0c;许多卖家已开始自…

自动化测试:你根本不懂自动化测试的快乐

接触了不少同行&#xff0c;由于他们之前一直做手工测试&#xff0c;现在很迫切希望做自动化测试&#xff0c;其中不乏工作5年以上的人。 本人从事软件自动化测试已经近6年&#xff0c;从server端到web端&#xff0c;从API到mobile&#xff0c;切身体会到自动化带来的好处与痛楚…

一分钟上手Vue VueI18n Internationalization(i18n)多国语言系统开发、国际化、中英文语言切换!

这里以Vue2为例子 第一步&#xff1a;安装vue-i18n npm install vue-i18n8.26.5 第二步&#xff1a;在src下创建js文件夹&#xff0c;继续创建language文件夹 在language文件夹里面创建zh.js、en.js、index.js这仨文件 这仨文件代码分别如下&#xff1a; zh.js export de…