【JS逆向案例】某加速乐cookie逆向分析

声明

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

本文未经许可禁止转载,禁止任何形式的修改后进行二次传播,若有侵权,请联系作者删除!

逆向目标

网站:aHR0cHM6Ly93d3cubXBzLmdvdi5jbi9pbmRleC5odG1s

加速乐

加速乐的特点是一般有三次请求:

  1. 第一次请求网站返回的状态码是521,响应返回的数据经过了AAEncode混淆
  2. 第二次请求网站返回的状态码也是521,响应返回的数据经过了OB混淆
  3. 第三次请求网站返回的状态码是正常的200,成功访问网页

逆向思路

根据加速乐的特点,思路分为以下三点:

  1. 第一次请求响应头中会返回__jsluid_s参数,响应内容解密后得到第一次__jsl_clearance_s参数
  2. 第二次请求携带上第一次请求得到的cookie值,响应内容解密后得到第二次__jsl_clearance_s参数
  3. 第三次请求携带上最终的cookie,即可成功访问网页

逆向分析

先对目标网站抓个包分析一下,可以看到请求同一个页面发生了三次请求,前两次都是返回521状态码,最后一次是200,符合加速乐特征

第一次请求

点击第一次请求,我们看到服务器给我们返回了cookie参数__jsluid_s,但响应内容无法看到,这时可以使用fiddler抓包工具查看,是一段混淆后的内容

【JS逆向案例】某加速乐cookie逆向分析_第1张图片

【JS逆向案例】某加速乐cookie逆向分析_第2张图片

【JS逆向案例】某加速乐cookie逆向分析_第3张图片

我们把响应内容拿出来,粘贴到notepad++,内容大致是一个经过AAEncode混淆的cookie

直接拿出document.cookie等号后的值控制台输出一下,果然是一段cookie,在Python中可以使用execjs.eval()解混淆(可以使用正则将混淆的cookie提取出来)

第二次请求

点击查看第二次请求,返回的也是一段混淆的

【JS逆向案例】某加速乐cookie逆向分析_第4张图片

这里我也不知道怎么解混淆,参考了下K哥的教程,提到了两种方法,一种是本地替换,一种是hook,我这里直接就选择了hook方法,使用了编程猫插件

//当前版本hook工具只支持Content-Type为html的自动hook
//下面是一个示例:这个示例演示了hook全局的cookie设置点
(function() {
    //严谨模式 检查所有错误
    'use strict';
    //document 为要hook的对象   这里是hook的cookie
	var cookieTemp = "";
    Object.defineProperty(document, 'cookie', {
		//hook set方法也就是赋值的方法 
		set: function(val) {
        if(val.indexOf("__jsl_clearance_s") != -1){
            debugger;
        }           
				//这样就可以快速给下面这个代码行下断点
				//从而快速定位设置cookie的代码
				console.log('Hook捕获到cookie设置->', val);
				cookieTemp = val;
				return val;
		},
		//hook get方法也就是取值的方法 
		get: function()
		{
			return cookieTemp;
		}
    });
})();

可以看到成功hook到cookie参数__jsl_clearance_s

【JS逆向案例】某加速乐cookie逆向分析_第5张图片

下面开始跟栈调试,在这里设置了cookie

【JS逆向案例】某加速乐cookie逆向分析_第6张图片

找到了cookie生成的位置是下面这段代码

var _0x2cb0e1 = _0x293413[_0x5c39('0x4b', 'fbqw') + 'c'](_0x1ab968['tn'] + '=' + _0x1f2023[0x0] + (_0x5c39('0xab', 'FMv#') + _0x5c39('0x75', '%^JY') + '=') + _0x1ab968['vt'], _0x293413[_0x5c39('0x94', 'aZ9(') + 'o']);

将这段代码优化下,发现cookie由_0x1f2023[0x0]生成,继续跟栈调试,找到_0x1f2023[0x0]的生成位置是如下代码

var _0x1f2023 = _0x293413[_0x5c39('0x35', '34sA') + 'R'](_0x47a5cd, _0x1ab968['ct'], _0x1ab968[_0x5c39('0xfe', '7oIp')]);

先将代码本地保存一份到notepad++,因为该js代码是动态变化的,方便我们调试。我们直接在开发者工具新建代码片段进行调试,记得清除cookie再断点调试

【JS逆向案例】某加速乐cookie逆向分析_第7张图片

经过调试发现,cookie参数由如下代码生成,其关键处是hash函数,当hash函数加密后的数据等于_0x393bf1时,返回cookie参数的值

function _0x47a5cd(_0x393bf1, _0xf58bf1) {
    var _0x15efa8 = {};
    _0x15efa8[_0x5c39('0xae', 'm$PE') + 'S'] = function(_0x555149, _0x3f2144, _0x255dc1) {
        return _0x555149(_0x3f2144, _0x255dc1);
    }
    ;
    _0x15efa8[_0x5c39('0x5a', '#2#0') + 'Z'] = function(_0x9f6fcd, _0x54edcc, _0x37d23d) {
        return _0x293413[_0x5c39('0x5c', '(aB&') + 'h'](_0x9f6fcd, _0x54edcc, _0x37d23d);
    }
    ;
    var _0x283d83 = _0x15efa8;
    if (_0x293413[_0x5c39('0x104', 'swkp') + 'k'] !== _0x293413[_0x5c39('0xd7', '*)&)') + 'k']) {
        a = _0x283d83[_0x5c39('0xf4', '%^JY') + 'S'](AddUnsigned, a, _0x283d83[_0x5c39('0x6b', '2Qrn') + 'Z'](AddUnsigned, AddUnsigned(F(b, c, d), x), ac));
        return _0x283d83[_0x5c39('0x1e', 'fbiV') + 'Z'](AddUnsigned, RotateLeft(a, s), b);
    } else {
        var _0x3c0e1f = _0x1ab968[_0x5c39('0x7e', 'Q#%8') + 's'][_0x5c39('0xfd', 'w[O^') + 'th'];
        for (var _0x14a05f = 0x0; _0x293413[_0x5c39('0x121', '62a0') + 's'](_0x14a05f, _0x3c0e1f); _0x14a05f++) {
            for (var _0x56321d = 0x0; _0x56321d < _0x3c0e1f; _0x56321d++) {
                var _0x1919fd = _0xf58bf1[0x0] + _0x1ab968[_0x5c39('0x129', '72K6') + 's'][_0x5c39('0xbc', '#2#0') + 'tr'](_0x14a05f, 0x1) + _0x1ab968[_0x5c39('0xf2', 'Zw9a') + 's'][_0x5c39('0xf8', '!Y%v') + 'tr'](_0x56321d, 0x1) + _0xf58bf1[0x1];
                if (_0x293413[_0x5c39('0x4e', '%^JY') + 'A'](hash(_0x1919fd), _0x393bf1)) {
                    return [_0x1919fd, _0x293413[_0x5c39('0x72', '7XT8') + 'i'](new Date(), _0x534ce4)];
                }
            }
        }
    }
}

调试这段代码可以发现里面所用参数来自go函数传入,并且hash函数所使用的加密方法是动态变化的,由go["ha"]决定,有三种加密方式md5、sha1、sha256,找个在线网站或者编程猫插件可以验证hash函数是标准的加密方式,直接调用crypto-js库实现算法

go = {
    "bts": ["1699759180.198|0|gI4", "2F4ybqrb3R3XniRZUgcbpvJI%3D"],
    "chars": "IVwNuGnmmWkymG%lYdqCqQ",
    "ct": "6f455c7207ae7bdee69232d4b9df739f",
    "ha": "md5",
    "is": true,
    "tn": "__jsl_clearance_s",
    "vt": "3600",
    "wt": "1500"
}
const 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();
    }
}

第三次请求

cookie逆向已经完成,直接编写Python代码进行请求,验证是否可用

# @Time    : 2023/11/11 16:18
# @Author  : 车厘子
# @Software: PyCharm
import re
import json
import execjs
import requests
from loguru import logger


url = ''
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36',
}
cookies = {}

def get_first_cookie():
    global cookies
    response = requests.get(url, headers=headers)
    # 获取 cookie 值 __jsluid_s
    cookies.update(response.cookies)
    # 获取第一层响应内容, AAEncode 加密
    AAEncode_text = re.search('document.cookie=(.*?);location', response.text).group(1)
    __jsl_clearance_s = execjs.eval(AAEncode_text).split(";")[0]
    # 获取 cookie 值 __jsl_clearance_s
    cookies["__jsl_clearance_s"] = __jsl_clearance_s.split("=")[1]

def get_second_cookie():
    global cookies
    # 通过携带 __jsluid_s 和 __jsl_clearance_s 值的 cookie 获取第二层响应内容
    response = requests.get(url, headers=headers, cookies=cookies)
    go_params = re.findall(';go\((.*?)\)', response.text)[0]
    go_params = json.loads(go_params)
    return go_params

def get_response_data(go_params):
    global cookies
    __jsl_clearance_s = execjs.compile(open("__jsl_clearance_s.js","r", encoding="utf-8").read()).call("get__jsl_clearance_s",go_params)
    cookies["__jsl_clearance_s"] = __jsl_clearance_s
    response = requests.get(url, headers=headers, cookies=cookies)
    response.encoding = "utf-8"
    logger.success(response.text)

def main():
    get_first_cookie()
    go_params = get_second_cookie()
    get_response_data(go_params)

if __name__ == '__main__':
    main()

验证结果

完美通过!

【JS逆向案例】某加速乐cookie逆向分析_第8张图片

你可能感兴趣的:(JS逆向案例,python,爬虫,javascript)