某信用中心之加速乐实战分析

某信用中心之加速乐实战分析

  • 某信用中心之加速乐实战分析
    • 声明
    • 逆向目标
    • 逆向分析
      • 第一层cookie获取
      • 第二层cookie获取
      • 调试分析JS文件
    • 模拟执行
      • 致谢

某信用中心之加速乐实战分析

声明

本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!

逆向目标

在这里插入图片描述

逆向分析

通过打开F12抓包查看是否存在加密参数

发现我们需要的数据在xhr请求中

在这里插入图片描述

再查看标头和负载,初步看好像没有加密参数,所以我们直接发送request请求尝试能不能获取到数据。

在这里插入图片描述
在这里插入图片描述

发送请求后发现返回一个js文件

在这里插入图片描述

如果有了解过的同学就知道,这是加速乐cookie反爬虫,是知道创宇推出的一款网站CDN加速、网站安全防护平台。

加速乐的特点是访问网站一般有三次请求:

  1. 第一次请求网站,网站返回的响应状态码为 521,响应返回的为经过 AAEncode 混淆的 JS 代码;
  2. 第二次请求网站,网站同样返回的响应状态码为 521,响应返回的为经过 OB 混淆的 JS 代码;
  3. 第三次请求网站,网站返回的响应状态码 200,即可正常访问到网页内容。

我们可以在网页中清除cookie后再尝试抓包查看是否和我们上述所说

在这里插入图片描述

接下来就是重点分析这三个cookie文件

第一层cookie获取

直接查看 response 是显示无响应内容的,所以我们通过之前发送请求包中返回的响应包代码进行分析

在这里插入图片描述

分析响应包,可以看到第一个xyxx-list.do返回的响应内容经过 AAEncode 加密,大致内容如下,可以看到一堆颜表情符号,还挺有意思的:

<script>document.cookie=('_')+('_')+('j')+('s')+('l')+('_')+('c')+('l')+('e')+('a')+('r')+('a')+('n')+('c')+('e')+('_')+('s')+('=')+(-~{}+'')+(6+'')+(3+6+'')+(~~[]+'')+(2+4+'')+(2+6+'')+(([2]+0>>2)+'')+((1+[4]>>1)+'')+((1<<2)+'')+(9+'')+('.')+(1+[0]-(1)+'')+((2<<1)+'')+(1+[0]-(1)+'')+('|')+('-')+(-~0+'')+('|')+('I')+('G')+('j')+('P')+(4+4+'')+('l')+('r')+('j')+('q')+('T')+('P')+('y')+('q')+('v')+('O')+('i')+(4+4+'')+('N')+('i')+('n')+('G')+('B')+('O')+('f')+('r')+('k')+('s')+('%')+(1+2+'')+('D')+(';')+('m')+('a')+('x')+('-')+('a')+('g')+('e')+('=')+(1+2+'')+(3+3+'')+(~~[]+'')+(~~{}+'')+(';')+('p')+('a')+('t')+('h')+('=')+('/');location.href=location.pathname+location.search</script>

document.cookie 里的颜表情串实际上是第一次 __jsl_clearance_s 的值,可以直接通过正则提取到加密内容后,使用execjs.eval()方法即可得到解密后的值:

import re
import execjsjs_clearance = re.findall('cookie=(.*?);location',response.text)[0]
jsl_clearance_s  = execjs.eval(js_clearance).split(';')[0]
print(jsl_clearance_s)// __jsl_clearance_s=1690686292.777|-1|uzTU5s0inLnvhCVdFmuyRXtr69k%3D

在这里插入图片描述

第二层cookie获取

第二层cookie获取可以直接查看第一个xyxx-list.do的响应包,或者通过第一层cookie获取后的__jsl_clearance_s __jsluid_s两个cookie参数发包请求,也能获得对应响应代码,如图所示

在这里插入图片描述

在这里插入图片描述

将文件复制出来分析后发现是一个经过 OB 混淆的 JS 文件,我们需要对其进行调试分析,所以我们首先需要寻找找这个js代码的加密位置,先清除本地浏览器的cookie。

在这里插入图片描述

然后在源代码中勾选住脚本,这样网页执行的每一个js文件都会被我们断住了,当然也可以使用hook注入等方式寻找加密位置

在这里插入图片描述

刷新网页,然后不断进行F8往下,我们首先会看到我们之前分析过的第一个cookie文件,继续F8往下走

在这里插入图片描述

成功找到我们所需要的js文件

在这里插入图片描述

调试分析JS文件

由于网站是cookie加密,所以每次刷新JS文件的一些参数都是在动态变换的,所以我们可以使用本地替换的方式固定一套下来再进行调试。然后在该 JS 文件中通过 CTRL + F 搜索 document,只有一个,在第 596 行打断点调试,选中_0x1739('0x93', '3R@K') + 'ie'后进入控制台输入会发现这里就是 cookie 经过混淆后的样式:
在这里插入图片描述

在这里插入图片描述

将等号后面的内容全部选中,进入控制台输入可以发现,这里生成了 Cookie 中 __jsl_clearance_s 参数的值:

在这里插入图片描述

至此,我们知道了 Cookie 生成的位置,接下来就需要了解其加密逻辑和加密方法,然后通过 python 对其进行复现了,document 部分完整的代码如下:

document[_0x1739('0x93', '3R@K') + 'ie'] = _0x3fa957[_0x1739('0x9b', '9PBK') + 'W'](_0x3fa957[_0x1739('0x43', '7C)&') + 'W'](_0x3fa957[_0x1739('0xbc', 'ML*i') + 'X'](_0x3fa957[_0x1739('0x37', 'tfb]') + 'X'](_0x5a3a5f['tn'] + '=', _0x4bca4c[0x0]), _0x1739('0x114', '@XV)') + _0x1739('0x10f', ')!ai') + '='), _0x5a3a5f['vt']), _0x1739('0x20', '711Q') + _0x1739('0xda', 'R2lr') + '\x20/');

这里等号后面的内容比较冗杂,其实我们想要获取的是 jsl_clearance_s 参数的值,通过逐步分析调试可以看到其值由(_0x5a3a5f['tn'] + '=', _0x4bca4c[0x0])生成:

在这里插入图片描述

继续分析可知_0x5a3a5f['tn']对应的部分是__jsl_clearance_s,而其值是_0x4bca4c[0x0],因此我们需要进一步跟踪 _0x4bca4c 生成的位置。

在这里插入图片描述

通过搜索,在第 587行可以找到其定义生成的位置,打断点调试可以看到,_0x4bca4c[0x0]其实就是取了 _0x4bca4c 数组中的第一个位置的值:

在这里插入图片描述

我们来进一步分析 _0x4bca4c 后面代码各自的含义,完整代码如下

_0x3fa957[_0x1739('0x11', '3)Nv') + 'V'](_0x29f4ef, _0x5a3a5f['ct'], _0x5a3a5f[_0x1739('0x68', '&GmG')]);

通过控制台可知_0x3fa957[_0x1739('0x11', '3)Nv') + 'V']取的是后面参数中第一个参数当做函数体,第二和第三个值当做参数传入。
在这里插入图片描述

_0x5a3a5f['ct'])取的是 go 函数传入的字典中 ct 参数的值:

在这里插入图片描述
在这里插入图片描述

分析可知将_0x5a3a5f[_0x1739('0x68', '&GmG')]数组中的值按照某种规则进行拼接就是 __jsl_clearance_s 参数的值,并且_0x1739('0x68', '&GmG')对应字典中 bts 的值:
在这里插入图片描述

所以需要进一步跟踪 _0x29f4ef,可以发现其是个函数体,第 582 行 return 后的返回值就是 __jsl_clearance_s参数的值:

在这里插入图片描述

在第 581 行打断点调试,能知道 hash 后 _0x2cc335 为 __jsl_clearance_s 参数的值:

在这里插入图片描述

hash( _0x2cc335) 的值为 _0x2cc335 经过加密后的结果,在本例中,加密结果特征分析很明显能看出是SHA256的加密长度,其实通过查看之前获取的go字典也能看到他写出了用的什么加密方式。

但加密的方法即 hash 方法不全是 SHA256,多刷新几次发现会变化,实际上这个 hash 方法与原来调用 go 函数传入的字典中 ha 的值相对应,ha 即加密算法的类型,一共有 md5、sha1、sha256 三种,所以我们在本地处理的时候,要同时有这三种加密算法,通过 ha 的值来匹配不同算法。

在这里插入图片描述

进一步观察这里还有个 for 循环,分析发现每次循环 hash(_0x2cc335) 的值是动态变化的,原因是 _0x2cc335 的值是在动态变化的,_0x2cc335 中只有中间两个字母在变化,不仔细看都看不出来:

在这里插入图片描述

跟进 _0x2cc335 生成的位置,分析可知 _0x2cc335 参数的值是由 _0xf7137b 数组的第一个值加上两个字母再加上该数组第二个值组成的结果:

在这里插入图片描述

_0x2cc335的源代码混淆参数很多不好直接分析,建议解混淆后再进行分析

var _0x2cc335 = _0xf7137b[0x0] + _0x5a3a5f[_0x1739('0x89', 'BSbR') + 's'][_0x1739('0xb8', 'jBDG') + 'tr'](_0x107bb7, 0x1) + _0x5a3a5f[_0x1739('0x105', 'kvMu') + 's'][_0x1739('0x6e', 'm%$p') + 'tr'](_0x4ec95b, 0x1) + _0xf7137b[0x1];

解混淆后代码如下

var _0x2cc335 = _0xf7137b[0x0] + _0x5a3a5f['chars']["substr"](_0x107bb7, 0x1) + _0x5a3a5f['chars']["substr"](_0x4ec95b, 0x1) + _0xf7137b[0x1];

中间两个字母是将底下这段写了两次生成的,即 _0x5a3a5f['chars']['substr'][1], 取字典中 chars 参数的一个字母,取了两次,这里通过 for 循环在不断取这两个值,直到其值加密后与 _0x1c0bb7(即 ct)的值相等,则作为返回值传递给 __jsl_clearance_s 参数:

_0x1c0bb7为ct的值:

在这里插入图片描述

最前面_0x3fa957[_0x1739('0xf0', 'oMaE') + 'E']是个方法,我们进一步跟进过去,看这个方式里面实现了什么样的逻辑:

其内容如下,可以看到这个方法返回的值是两个相等的参数:
在这里插入图片描述

模拟执行

综上所述,_0x29f4ef 函数中的逻辑就是判断 _0x2cc335 的值经过 hash 方法加密后的值,是否与 ct 的值相等,若相等则将返回值传递给 __jsl_clearance_s 参数,循环完后还未有成功匹配的值则会执行提示失败,传入参数中 ha 的值是在变化的,即加密算法也是在变化的,有三种加密方式 SHA1SHA256MD5,我们可以扣下三种 hash 方法,也可以直接使用 crypto-js 库来实现:

var CryptoJS = require('crypto-js');function hash(type, value){if(type == 'md5'){return CryptoJS.MD5(value).toString();}if(type == 'sha1'){return CryptoJS.SHA1(value).toString();}if(type == 'sha256'){return CryptoJS.SHA256(value).toString();}
}function cookies(_0x5a3a5f){var _0x26fd06 = new Date();function _0x29f4ef(_0x1c0bb7, _0xf7137b) {var _0x5dfb01 = _0x5a3a5f['chars']['length'];for (var _0x107bb7 = 0x0; _0x107bb7 < _0x5dfb01; _0x107bb7++) {for (var _0x4ec95b = 0x0; _0x4ec95b < _0x5dfb01; _0x4ec95b++) {var _0x2cc335 = _0xf7137b[0x0] + _0x5a3a5f['chars']["substr"](_0x107bb7, 0x1) + _0x5a3a5f['chars']["substr"](_0x4ec95b, 0x1) + _0xf7137b[0x1];if ((hash(_0x5a3a5f['ha'],_0x2cc335) == _0x1c0bb7)) {return [_0x2cc335, new Date() - _0x26fd06];}}}}var _0x4bca4c = _0x29f4ef (_0x5a3a5f['ct'], _0x5a3a5f['bts']);return {'__jsl_clearance_s' : _0x4bca4c[0]};
}console.log(cookies({"bts": ["1690639070.278|0|ihl", "l%2FaY6Y3B%2FKq8I4GT55NZvc%3D"],"chars": "iMyDvZzWmPBnCGdujVpCAJ","ct": "fb9fe0ec006b42f92ffbd372dc71b4612c989e2bf4d095afb8abbfce8ed3d35f","ha": "sha256","is": false,"tn": "__jsl_clearance_s","vt": "3600","wt": "1500"
}))

获取结果如下

在这里插入图片描述

python代码只演示部分关键代码,完整代码可私信联系我

def get_first_cookie():global cookiesresp_first = requests.post(url, headers=headers,  data=data)# 获取 cookie 值 __jsluid_scookies.update(resp_first.cookies)# 获取第一层响应内容, AAEncode 加密content_first = re.findall('cookie=(.*?);location', resp_first.text)[0]jsl_clearance_s = execjs.eval(content_first).split(';')[0]# 获取 cookie 值 __jsl_clearance_scookies['__jsl_clearance_s'] = jsl_clearance_s.split("=")[1]def get_second_cookie():global cookies# 通过携带 jsluid_s 和 jsl_clearance_s 值的 cookie 获取第二层响应内容resp_second = requests.get(url=url, headers=headers, cookies=cookies)# 获取 go 字典参数go_params = re.findall(';go\((.*?)\)</script>', resp_second.text)[0]params = json.loads(go_params)return paramsdef get_third_cookie():with open('jsl.js', 'r', encoding='utf-8') as f:jsl_js = f.read()params = get_second_cookie()# 传入字典third_cookie = execjs.compile(jsl_js).call('cookies', params)cookies.update(third_cookie)def main():get_first_cookie()get_third_cookie()resp_third = requests.post(url, headers=headers,cookies=cookies , data=data)resp_third.encoding = 'utf-8'print(resp_third.text)if __name__ == '__main__':main()

获取结果如下

在这里插入图片描述

致谢

部分思路代码通过以下文章学习:【JS 逆向百例】某网站加速乐 Cookie 混淆逆向详解

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

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

相关文章

QTday2信号和槽

点击登录按钮,关闭Widget登录窗口,打开QQList窗口 widget.cpp #include "widget.h"void my_setupUI(Widget *w);Widget::Widget(QWidget *parent): QWidget(parent) {my_setupUI(this); }Widget::~Widget() { }void Widget::login_slots() {//fixemit jump_signal(…

CAN学习笔记1:计算机网络

计算机网络 1 概述 计算机网络就是把多种形式的计算机用通信线路连接起来&#xff0c;并使其能够互相进行交换的系统。实际上&#xff0c;计算机网络包括了计算机、各种硬件、各种软件、组成网络的体系结构、网络传输介质和网络通信计数。因此&#xff0c;计算机网络是计算机…

SpringCloudAlibaba之Ribbon

Ribbon是nacos自带的负载均衡器&#xff0c;属于客户端的负载均衡 但是在Spring高级版本中让LoadBalancer替代了 本人用的是2.1.0的nacos&#xff0c;ribbon还没有被替换。 使用&#xff1a; 在配置类中&#xff1a;LoadBalanced BeanLoadBalancedpublic RestTemplate restT…

【点云处理教程】05-Python 中的点云分割

一、说明 这是我的“点云处理”教程的第 5 篇文章。“点云处理”教程对初学者友好&#xff0c;我们将在其中简单地介绍从数据准备到数据分割和分类的点云处理管道。 在上一教程中&#xff0c;我们看到了如何过滤点云以减少噪声或其密度。在本教程中&#xff0c;我们将应用一些聚…

Redis(五)—— Redis进阶部分

一、Redis配置文件详解 注意这是Redis服务本身的配置文件&#xff0c;相当于maven的settings.xml&#xff0c;而不是我们在springboot去配置Redis的那个application.yml。 核心部分include 引入其他redis配置文件&#xff0c;相当于spring的<import>bind 设置IP&#xf…

Elasticsearch:通过动态修剪实现更快的基数聚合

作者&#xff1a;Adrien Grand Elasticsearch 8.9 通过支持动态修剪&#xff08;dynamic pruning&#xff09;引入了基数聚合加速。 这种优化需要满足特定的条件才能生效&#xff0c;但一旦实现&#xff0c;通常会产生惊人的结果。 我们观察到&#xff0c;通过此更改&#xff0…

C语言指针应该这么学?

数组名的意义&#xff1a; 1. sizeof(数组名)&#xff0c;这里的数组名表示整个数组&#xff0c;计算的是整个数组的大小。 2. &数组名&#xff0c;这里的数组名表示整个数组&#xff0c;取出的是整个数组的地址。 3. 除此之外所有的数组名都表示首元素的地址。 根据以上数…

C++代码格式化工具clang-format详细介绍

文章目录 clang-format思考代码风格指南生成您的配置运行 clang-format禁用一段代码的格式设置clang-format的设置预览 clang-format 我曾在许多编程团队工作过&#xff0c;这些团队名义上都有“编程风格指南”。该指南经常被写下来并放置在开发人员很少查看的地方。几乎在每种…

网络编程 IO多路复用 [select版] (TCP网络聊天室)

//head.h 头文件 //TcpGrpSer.c 服务器端 //TcpGrpUsr.c 客户端 select函数 功能&#xff1a;阻塞函数&#xff0c;让内核去监测集合中的文件描述符是否准备就绪&#xff0c;若准备就绪则解除阻塞。 原型&#xff1a; #include <sys/select.…

BUG:pm2启动verdaccio报错:Invalid or unexpected toke

输入命令&#xff1a; pm2 state verdaccio 问题描述&#xff1a; pm2 logs verdaccio报错翻译&#xff1a;数据格式错误 导致我呢提原因&#xff0c;没有找到运行文件&#xff0c; 发现问题&#xff1a;因为命令默认查找verdaccio是去系统盘查找。 解决方式 1&#xff1a;…

Java+bcprov库实现对称和非对称加密算法

BouncyCastle&#xff0c;即BC&#xff0c;其是一款开源的密码包&#xff0c;包含了大量的密码算法。 本篇主要演示BC库引入&#xff0c;对称加密算法AES、SM4和 非对称加密EC算法的简单实现&#xff0c;以下是实现过程。 一、将BC添加到JRE环境 前提&#xff1a;已安装JRE环…

C# Socket实际应用案例与属性详解

引言 Socket是一个在网络编程中非常常见和重要的概念&#xff0c;它提供了一种通信机制&#xff0c;使不同的计算机之间可以进行数据传输。本文将介绍C#中Socket的实际应用案例&#xff0c;并对Socket的常用属性进行详细解析。 文章目录 1. Socket的实际应用案例2. Socket的属…

SqlServer读写分离对等发布

SqlServer读写分离对等发布: 对等发布支持多主复制。发布服务器将事务流式传输到拓扑中的所有对等方。所有对等节点可以读取和写入更改,且所有更改将传播到拓扑中的所有节点。 注意点: 1.各服务器的数据库名字要保证一样。 2.发布名称必须保持一致。 3.各服务器必须都是…

【论文阅读】The Deep Learning Compiler: A Comprehensive Survey

论文来源&#xff1a;Li M , Liu Y , Liu X ,et al.The Deep Learning Compiler: A Comprehensive Survey[J]. 2020.DOI:10.1109/TPDS.2020.3030548. 这是一篇关于深度学习编译器的综述类文章。 什么是深度学习编译器 深度学习&#xff08;Deep Learning&#xff09;编译器将…

【Maven】让maven更高效,优化maven构建项目速度

打开idea的setting&#xff0c;找到maven&#xff0c;设置它多线程数&#xff0c;重启后即可&#xff01; 我这里是8&#xff0c;你们可以随便设置。 如下图&#xff1a;

Github git clone 和 git push 特别慢的解决办法

1.在本地上使用 SSH 命令无法git push 上传 github 项目 2.使用 git clone 下载项目特别慢总是加载不了 解决办法1 将 *** 的连接模式换成&#xff1a;D-i-r-e-c-t&#xff08;好像不太有用&#xff09; 后面再找找能不能再G-l-o-b-a-l 下解决该问题 解决办法 2 mac下直接设…

Spring Data【Spring Data Redis、Spring Data ElasticSearch】(二)-全面详解(学习总结---从入门到深化)

目录 四、 Spring Data Redis 五、 Spring Data ElasticSearch 四、 Spring Data Redis Redis 是一个基于内存的数据结构存储系统&#xff0c;它可以用作数据库或者缓存。它支持多种 类型的数据结构&#xff0c;这些数据结构类型分别为 String&#xff08;字符串&#xff09…

Flutter 开发者工具 Android Studio 开发Flutter应用

Flutter 开发者工具 在 Android Studio 开发Flutter应用 &#x1f525; Android Studio 版本更新 &#x1f525; Android Studio Check for Update Connection failed ​ 解决方案 如果是运行的是32位的android studio需要在andriod studio的启动目录下找到studio.exe.vmoptio…

WIZnet W5100S-EVB-Pico DHCP 配置教程(三)

DHCP协议介绍 什么是DHCP&#xff1f; 动态主机配置协议DHCP&#xff08;Dynamic Host Configuration Protocol&#xff09;是一种网络管理协议&#xff0c;用于集中对用户IP地址进行动态管理和配置。 DHCP于1993年10月成为标准协议&#xff0c;其前身是BOOTP协议。DHCP协议由…

Python批量下载主播照片,实现人脸识别, 进行颜值评分,制作颜值排行榜

昨晚一回家&#xff0c;表弟就神神秘秘的跟我说&#xff0c;发现一个高颜值网站&#xff0c;非要拉着我研究一下她们的颜值高低。 我心想&#xff0c;这还得要我一个个慢慢看&#xff0c;太麻烦了~ 于是反手用Python给他写了一个人脸识别代码&#xff0c;把她们的照片全部爬下…