【JavaScript 逆向】521 加速乐多层响应 Cookie 逆向

2023-11-02

前言

        现在一些网站对 JavaScript 代码采取了一定的保护措施,比如变量名混淆、执行逻辑混淆、反调试、核心逻辑加密等,有的还对数据接口进行了加密,这次的案例是对加速乐、AAEncode、OB 混淆方式的破解。

声明

        本文章中所有内容仅供学习交流,相关链接做了脱敏处理,若有侵权,请联系我立即删除!

案例分析

目标网址:aHR0cHM6Ly93d3cubXBzLmdvdi5jbi9pbmRleC5odG1s

加速乐:加速乐是知道创宇旗下的一款网站安全防护平台产品

加速乐反爬特点:

  1. 第一次请求网站,响应状态码为 521,服务器返回的 Set-Cookie 中携带 jsluid_s 参数;

  2. 第二次请求网站,响应状态码仍为 521,Cookie 中携带 jsl_clearance_s 参数;

  3. 第三次请求网站,响应状态码 200,即可正常访问到网页内容。

下图所示,为加速乐的基本样式,521 为其明显特征,其他地方几乎看不到这个状态码:

逆向突破

在使用 Fiddler 对目标网站进行抓包分析之前,先 F12 打开开发者人员工具,在 Application 中清除浏览器缓存,清除可能存在的干扰方便之后调试分析:

打开 Fiddler ,对目标网站进行标记,方便查找到我们需要的内容: 

开启抓包,能够发现该网站符合我们上述加速乐的特点:

我们打开第一个 521,可以看到返回的响应内容是一堆很有意思的颜表情符,这是典型的 AAEncode 加密方式的特点,并且 Set-Cookie 中携带了 jsluid_s 参数:

Set-Cookie: __jsluid_s=236185b3155a49cb575bd722bc62e6d2; max-age=31536000; path=/; HttpOnly; SameSite=None; secure

我们可以通过正则提取到 AAEncode 加密部分的内容,然后使用  execjs 模块的 eval 方法执行输出后就能得到 jsluid_s 参数的值:

import re
import requests
import execjs

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"
}
url = "aHR0cHM6Ly93d3cubXBzLmdvdi5jbi9pbmRleC5odG1s"
response = requests.get(url=url, headers=headers)

js_clearance = re.findall('cookie=(.*?);location', response.text)[0]
result = execjs.eval(js_clearance).split(';')[0]
print(result)

获取到了 jsluid_s 参数的值后,我们可以携带其再次访问目标网站,就能和获取到第二层响应内容,可以看到,响应返回的 JS 文件经过了 OB 混淆,Cookie 中多了一个参数  jsl_clearance_s,我们可以推测该参数就是此 JS 文件生成的:

Cookie: __jsluid_s=236185b3155a49cb575bd722bc62e6d2; __jsl_clearance_s=1658887255.608|-1|epHb9ouMB4EutgWPsoWjiqRoqM4%3D

我们将第二层响应内容的 JS 代码复制到本地,会发现其经过了压缩,不便于调试分析,我们可以通过一些爬虫工具网站对其格式化处理,例如 爬虫工具库,稍作更改后如下为部分代码样式: 

<script>
var _0x1c58 = ['wpDCsRDCuA==', 'AWc8w7E=', ......, 'HEVzUg==', 'woAhwrDDiQ==']; (function(_0x191b8d, _0x1c5888) {
    var _0x2a9aca = function(_0x405cb0) {
        while (--_0x405cb0) {
            _0x191b8d['push'](_0x191b8d['shift']());
        }
    };
    _0x2a9aca(++_0x1c5888);
} (_0x1c58, 0xcd));
...
...
</script>

一般情况下,我们得开始在开发者人员工具中全局搜索关键词或跟栈定位 JS 代码位置了,但是经过调试发现,这种方式几乎找不到该 JS 文件,所以得转变思路,我们可以将该 JS 代码保存到本地并在代码中加入 debugger; 以断点形式断到 JS 文件中,然后通过 Fiddler 进行文件替换:

以上操作完成后,清除浏览器缓存,然后打开 Fiddler 进行抓包,即可成功断住:

接下来就可以进行调试分析了,JavaScript 中一般使用 document.cookie 方法来创建 Cookie,我们可以在文件中 ctrl f 局部搜索 document,可以看到有一个结果,在这行打断点,经过调试分析,可以看到这里就是 cookie 生成的关键位置:

等号后面部分的 _0x60274b['tn'] + '=' + _0x732635[0x0] 生成了如下字符串内容,显而易见:

  • _0x60274b['tn'] 为 jsl_clearance_s
  • _0x732635[0x0] 就是 jsl_clearance_s 参数的值:

 我们想要知道的是值是怎么生成的,所以进一步跟踪 _0x732635 的位置,通过搜索可以看到其是在第 538 行定义的,打断点调试可知:

  • _0x14e035 是在第 527 行定义的一个函数,故括号里为传参内容,其具体含义后面再分析
  • _0x60274b['ct'] 是 go 函数传入字典中 ct 对应的值

// 该部分内容再 JS 文件的最后面
go({
    "bts": ["1658906704.293|0|YYj", "Jm5cKs%2B1v1GqTYAtpQjthM%3D"],
    "chars": "vUzQIgamgWnnFOJyKwXiGK",
    "ct": "690f55a681f304c95b35941b20538480",
    "ha": "md5",
    "tn": "__jsl_clearance_s",
    "vt": "3600",
    "wt": "1500"
})
  •  _0x60274b[_0x2a9a('0xf9', 'uUBi')] 是 jsl_clearance_s 参数中的部分内容

  • _0x2a9a('0xf9', 'uUBi') 是上述字典中 bts 对应的值

_0x732635 的构造,分析完了,我们现在只需要跟进 _0x14e035 就能知道 jsl_clearance_s 的具体生成逻辑,上文知道其是一个函数,具体内容如下:

function _0x14e035(_0x56cbce, _0x5e5712) {
        var _0x2d0a43 = _0x60274b[_0x2a9a('0xb3', '9vV&') + 's'][_0x2a9a('0x38', '9vV&') + 'th'];
        for (var _0x212ce4 = 0x0; _0x212ce4 < _0x2d0a43; _0x212ce4++) {
            for (var _0x8164 = 0x0; _0x2228a0[_0x2a9a('0x3a', 'uUBi') + 'z'](_0x8164, _0x2d0a43); _0x8164++) {
                var _0x2a7ea9 = _0x2228a0[_0x2a9a('0x84', ']A89') + 'o'](_0x2228a0[_0x2a9a('0x47', '8a*W') + 'x'](_0x2228a0[_0x2a9a('0xfd', 'hEgr') + 'W'](_0x5e5712[0x0], _0x60274b[_0x2a9a('0xb1', 'B%^W') + 's'][_0x2a9a('0x5a', 'ZN)]') + 'tr'](_0x212ce4, 0x1)), _0x60274b[_0x2a9a('0x45', 'XXkw') + 's'][_0x2a9a('0x5a', 'ZN)]') + 'tr'](_0x8164, 0x1)), _0x5e5712[0x1]);
                if (_0x2228a0[_0x2a9a('0x6d', 'U0Y3') + 's'](hash(_0x2a7ea9), _0x56cbce)) {
                    return [_0x2a7ea9, _0x2228a0[_0x2a9a('0x9b', 'Z^dq') + 'u'](new Date(), _0x34d7a8)];
                }
            }
        }
    };

_0x56cbce 对应 ct 的值,_0x5e5712 对应 bts 的值,在第 533 行 return 处打下断点调试分析,可知 _0x2a7ea9 就是 jsl_clearance_s 的值,其定义在第 532 行:

经过分析跟踪后知道,以下三部分内容都是在对其后参数进行加法计算:

_0x2228a0[_0x2a9a('0x84', ']A89') + 'o'](_0x2228a0[_0x2a9a('0x47', '8a*W') + 'x'](_0x2228a0[_0x2a9a('0xfd', 'hEgr') + 'W']

所以我们可以将 _0x2a7ea9 的定义部分进行如下优化:

var _0x2a7ea9 = _0x5e5712[0] + _0x60274b["chars"]["substr"](_0x212ce4, 1) + _0x60274b["chars"]["substr"](_0x8164, 1) + _0x5e5712[1];

将以上内容用鼠标各自选中后会出现各自所对应的含义:

  • _0x5e5712[0x0]:1658906704.293|0|YYj
  • _0x60274b[ chars ][ substr ](_0x212ce4, 0x1):取字典中 chars 对应的值中的一个数
  • _0x60274b[ chars ][ substr ](_0x8164, 0x1):取字典中 chars 对应的值中的一个数
  • _0x5e5712[0x1]:Jm5cKs%2B1v1GqTYAtpQjthM%3D

所以 jsl_clearance_s 参数的组成为:

1658906704.293|0|YYj + chars 中的两个数 + Jm5cKs%2B1v1GqTYAtpQjthM%3D

在第 532 行 if 判断语句中 跟踪 _0x2228a0 发现其是个函数,返回值为相等的两个参数,所以这里的判断逻辑为:_0x2a7ea9 的值经过 hash 方法处理后,与 ct 的值作比较,若相等,则将 _0x2a7ea9 的值作为返回值传递给jsl_clearance_s 参数,经调试分析发现 hash 对应的是字典中 ha 的值,即 MD5 加密算法,但是后面程序调试过程中发现,ha 是三种加密方式动态调整的,分别为 SHA1、SHA256、MD5,加密算法不匹配会导致程序报错,所以需要对其进行判断,以上即全部的逻辑分析,将 jsl_clearance_s 和 一开始获取到的 jsluid_s 的值传递给 cookie,携带该 cookie 即可成功访问网站,拿到正常的 html 页面。

Cookie: __jsluid_s=236185b3155a49cb575bd722bc62e6d2; __jsl_clearance_s=1658887255.714|0|bdaxwfZVODrJVQKEl3RHaOBV%2Bbw%3D

完整代码

JavaScript

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


var hash = {
    'md5': function(a){return CryptoJS.MD5(a).toString()},
    'sha1': function(a){return CryptoJS.SHA1(a).toString()},
    'sha256': function(a){return CryptoJS.SHA256(a).toString()}
}


var _0x2228a0 = {
    "mLZyz" : function(_0x435347, _0x8098d) {
        return _0x435347 < _0x8098d;
    },
    "DRnYs" : function(_0x4573a2, _0x3855be) {
        return _0x4573a2 == _0x3855be;
    },
    "ZJMqu" : function(_0x3af043, _0x1dbbb7) {
        return _0x3af043 - _0x1dbbb7;
    },
};


function cookies(_0x60274b){
    var _0x34d7a8 = new Date();
    function _0x14e035(_0x56cbce, _0x5e5712) {
    var _0x2d0a43 = _0x60274b['chars']['length'];
    for (var _0x212ce4 = 0x0; _0x212ce4 < _0x2d0a43; _0x212ce4++) {
        for (var _0x8164 = 0x0; _0x2228a0["mLZyz"](_0x8164, _0x2d0a43); _0x8164++) {
            var _0x2a7ea9 = _0x5e5712[0] + _0x60274b["chars"]["substr"](_0x212ce4, 1) + _0x60274b["chars"]["substr"](_0x8164, 1) + _0x5e5712[1];
            if (hash[_0x60274b['ha']](_0x2a7ea9) == _0x56cbce) {
                return [_0x2a7ea9, _0x2228a0["ZJMqu"](new Date(), _0x34d7a8)];
            }
        }
    }
    }
    var _0x732635 = _0x14e035(_0x60274b['ct'], _0x60274b['bts']);
    return {'__jsl_clearance_s' : _0x732635[0]};
}

python

import json
import re
import requests
import execjs

cookies = {}
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"
}

url = "aHR0cHM6Ly93d3cubXBzLmdvdi5jbi9pbmRleC5odG1s"
resp_first = requests.get(url=url, headers=headers)
# 获取 jsluid_s
cookies.update(resp_first.cookies)
js_clearance = re.findall('cookie=(.*?);location', resp_first.text)[0]
aa_result = execjs.eval(js_clearance).split(';')[0]
# 获取第一次响应生成的 __jsl_clearance_s 参数
cookies['__jsl_clearance_s'] = aa_result.split("=")[1]
resp_second = requests.get(url=url, headers=headers, cookies=cookies)
dd = re.findall(';go\((.*?)\)</script>', resp_second.text)[0]
# 获取字典内容
params = json.loads(dd)
with open('jiasule.js', 'r', encoding='utf-8') as f:
    jsl_js = f.read()
js_clearance_s = execjs.compile(jsl_js).call('cookies', params)
# 获取第二次响应生成的 js_clearance_s 参数
cookies.update(js_clearance_s)
resp_third = requests.get(url=url, headers=headers, cookies=cookies)
resp_third.encoding = 'utf-8'
print(resp_third.text)

注意:

链接做了脱敏处理,不能直接运行

执行 python 程序前关闭掉 Fiddler 抓包进程,否则会有以下报错出现:

requests.exceptions.SSLError: HTTPSConnectionPool(host='XXX', port=443)

总结

        以上是对某网站加速乐加密方式的逆向分析,如有任何见解欢迎评论区或私信指正交流~       

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【JavaScript 逆向】521 加速乐多层响应 Cookie 逆向 的相关文章

随机推荐

  • 打不开磁盘“E:\Virtual Machines\CentOS 7 64 位\CentOS 7 64 位-000003.vmdk”或它所依赖的某个快照磁盘。

    vmware下启动Centos虚拟机报错虚拟无法打开磁盘 打不开磁盘 E Virtual Machines CentOS 7 64 位 CentOS 7 64 位 000003 vmdk 或它所依赖的某个快照磁盘 或它所依赖的某个快照磁盘
  • 【Android动画渲染及混合模式】

    Android动画渲染及混合模式 public class GradientLayout extends View private Paint mPaint private Shader mShader private Bitmap mBi
  • CSMA/CD工作原理

    CSMA CD就是载波监听多点接入 碰撞检测 CSMA CD工作原理可以概括如下 1 先听后说 边听边说 2 一旦冲突 立即停说 3 等待时机 然后再说 在发送数据前 先监听总线是否空闲 若总线忙 则不发送 若总线空闲 则把准备好的数据发送
  • Java打印变量的参数类型

    具体方法如下 public static String getType Object o if ObjectUtils isEmpty o return 当前参数为空 else return o getClass toString 测试案例
  • 如何判断是字符型注入还是整形注入

    1 数字型注入 当输入的参数为整形时 如果存在注入漏洞 可以认为是数字型注入 测试步骤 1 加单引号 URL www text com text php id 3 对应的sql select from table where id 3 这时
  • UITabBarController使用

    文章目的 如何用纯代码的方式创建UITabBarController 方法 1 首先开启XCode并建立一个Empty Application 2 加入一个Objective C Class并继承自UIViewController 取名为F
  • 硬件模块化开发的例子:LD3320语音模块与Source Insight的使用

    目录 硬件模块化开发的行情 LD3320语音模块使用手册介绍 语音模块验货测试 硬件连接效果图 测试结果良好 Source Insight代码查看器 创建工程 修改字体 配色方案 中文乱码 关联代码 语音识别模块代码分析 语音识别模块二次开
  • day 33 css

    day 33 css 基本选择器 1 元素选择器 p color red 2 ID选择器 i1 background color red 3 类选择器 复制代码 c1 font size 14px p c1 color red 复制代码 注
  • uniCloud 云函数/云对象 node版本改变成12或18解决方案

    爆红信息 right hand side of instanceof is not an object 今天卡到一个本地跑好好的云对象部署云端直接报错了 原因是这样的 1 你去看看你云函数依赖那npm install的插件node版本是不是
  • kyocera client tool 安装_使用官方gdc-client软件下载TCGA数据

    要是有gdc client软件下载数据 需要以下三步才能完成 1 GDC筛选检索下载需要数据的Manifest文件 TCGA改版后 下载方式变得大为不同 数据都整合在GDC Genomic Data Commons 的DATA PORTAL
  • 牛客网试题+答案分析+大牛面试经验(3)

    1 串的长度是指 A 串中所含不同字母的个数 B 串中所含字符的个数 C 串中所含不同字符的个数 D 串中所含非空格字符的个数 答案 B 解析 串的长度定义为串中字符的数目 所以选项B为正确答案 选项C不正确 因为串中可以含有相同的字符 选
  • plt绘制3D渐变填充柱状图

    from mpl toolkits mplot3d import Axes3D import matplotlib pyplot as plt import matplotlib colors import numpy as np def
  • 四种常见Bug类型

    1 粗心 pwd input 请输入密码 if pwd 520666 print 正确 这是验证用户密码的代码 如果你把它放进运行 会报如下错误 找一下这段代码错误 修改代码让它成功运行 pwd input 请输入密码 if pwd 520
  • QT slot,signal,connect

    connect三种写法 函数 指针 宏 lambda 函数 指针 connect sender QObject destroyed this MyObject objectDestroyed 宏 connect sender SIGNAL
  • Qstring类的常见使用

    Qstring 数据块 初始化 QSring类型之间的相互转换 Qstring转成其他类型 其他类型转Qstring Qstring类的常用方法 拼接字符 格式化 查找特定位置的字符 插入字符 起始位置插入数据 替换指定位置的几个字符 查询
  • QT QPushButton 通过stylesheet 设置样式

    1 QT QPushButton 通过stylesheet 设置样式 ui gt pushButton gt setStyleSheet QPushButton background color rgba 255 178 0 100 col
  • Mysql8完全卸载教程

    0 备份所有需要保留的数据库 在Navicat中选择对应库表选择导出为Sql文件即可 如果卸载数据库的来由是因为数据库已经无法正常使用打开所以需要卸载数据库进行重新安装的话可以跳过这一步 1 停止所有Mysql相关服务 Win11直接搜索服
  • 农作物地块范围识别(图像分割)

    来源 机器学习AI算法工程 知乎 Now more 本文约5500字 建议阅读15分钟本文为你介绍 以薏仁米作物识别以及产量预测为比赛命题 及对对应获奖的开发算法模型 农作物的资产盘点与精准产量预测是实现农业精细化管理的核心环节 当前 我国
  • Unity实现全景图

    1 前言 实现全景查看有两种方式 一种是创建天空盒 另外一种是全景图渲染到一个球形上 从内球内部看 两者都可以用天空盒材质Skybox实现 2 创建天空盒材质 先创建一个材质球命名为Sky 在 Shader 下拉选单中 单击 Skybox
  • 【JavaScript 逆向】521 加速乐多层响应 Cookie 逆向

    前言 现在一些网站对 JavaScript 代码采取了一定的保护措施 比如变量名混淆 执行逻辑混淆 反调试 核心逻辑加密等 有的还对数据接口进行了加密 这次的案例是对加速乐 AAEncode OB 混淆方式的破解 声明 本文章中所有内容仅供