【JS 逆向百例】猿人学系列 web 比赛第五题:js 混淆 - 乱码增强,详细剖析
字数 1336 2025-08-11 08:35:55

JS逆向:猿人学Web比赛第五题 - JS混淆与乱码增强解析

逆向目标

  • 目标网站:猿人学反混淆刷题平台Web第五题
  • 任务:抓取全部5页直播间热度,计算前5名直播间热度的加和
  • 主页:https://match.yuanrenxue.com/match/5
  • 接口:https://match.yuanrenxue.com/api/match/5?m=XXX&f=XXX

逆向参数分析

需要解决的参数

  1. URL请求参数:

    • m
    • f
  2. Cookie参数:

    • m
    • RM4hZBv0dDon443M

逆向过程详解

1. 抓包分析

  • 数据通过XHR加载,接口为5?m=XXX&f=XXX
  • Cookie有效期仅为50秒,动态变化

2. Cookie加密参数分析

2.1 定位加密位置

使用Hook技术定位Cookie参数生成位置:

// Hook Cookie代码
(function () {
    'use strict';
    var cookieTemp = '';
    Object.defineProperty(document, 'cookie', {
        set: function (val) {
            if (val.indexOf('RM4hZBv0dDon443M') != -1) {
                debugger;
            }
            console.log('Hook捕获到cookie的值->', val);
            cookieTemp = val;
            return val;
        },
        get: function () {
            return cookieTemp;
        }
    });
})();

定位到关键代码行:

_0x3d0f3f[_$Fe] = 'R' + 'M' + '4' + 'h' + 'Z' + 'B' + 'v' + '0' + 'd' + 'D' + 'o' + 'n' + '4' + '4' + '3' + 'M=' + _0x4e96b4['_$ss'] + ';\x20path=/';

2.2 加密算法分析

关键加密部分为_0x4e96b4['_$ss'],进一步分析发现是AES加密:

_$Ww = _$Tk['enc']['utf-8']['parse'](_0x4e96b4['_$pr']['toString']()),
_0x29dd83 = _$Tk['AES'](_$Ww, _0x4e96b4['_$qF'], {
    'mode': _$Tk['mode']['ECB'],
    'padding': _$Tk['pad']['pkcs7']
}),
_0x4e96b4['_$ss'] = _0x29dd83['toString']();

加密参数说明:

  • 加密内容:_$Ww(由_0x4e96b4['_$pr']转换而来)
  • 密钥:_0x4e96b4['_$qF']
  • 加密模式:ECB
  • 填充方式:pkcs7

2.3 密钥生成

密钥生成逻辑:

_0x4e96b4['_$qF'] = CryptoJS['enc']['Utf8'][_$UH[0xff]](_0x4e96b4['btoa'](_0x4e96b4['_$is'])['slice'](0x0, 0x10));

即:将时间戳base64编码后取前16位作为密钥

2.4 加密内容生成

_0x4e96b4['_$pr']是一个包含5个值的数组:

  1. 前4个值:由Date.parse(new Date())生成并经过_0x474032函数处理
  2. 第5个值:时间戳经过_0x474032函数处理(也是m参数的值)

2.5 _0x474032函数分析

简化后的函数:

function _0x474032(_0x233f82, _0xe2ed33, _0x3229f9) {
    return _0x37614a(_0x233f82);
}

进一步分析:

function _0x37614a(_0x32e7c1) {
    return _0x499969(_0x41873d(_0x32e7c1));
}

2.6 关键环境变量

需要补全的环境变量:

window['_$6_'] = -389564586;
window['_$tT'] = -660478335;
window['_$Jy'] = -405537848;

3. 请求头参数分析

3.1 m参数

m的值是window._$is,即时间戳_$yw

3.2 f参数

f的值是window.$_zw[23],由时间戳生成:

let $_t1 = Date.parse(new Date());

完整代码实现

JavaScript代码

var _0x4e96b4 = window = {};
var _0x1171c8 = 0x67452301;
var _0x4dae05 = -0x10325477;
var _0x183a1d = -0x67452302;
var _0xcfa373 = 0x10325476;
var _0x30bc70 = String;

// 省略部分函数...

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

function rm4Encrypt(_$yw, pr) {
    var value = Buffer.from(_$yw).toString('base64').slice(0, 16);
    var _$Ww = CryptoJS.enc.Utf8.parse(pr);
    var key = CryptoJS.enc.Utf8.parse(value);
    var encrypted = CryptoJS.AES.encrypt(_$Ww, key, {
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7
    });
    return encrypted.toString();
}

function getParamers() {
    pr = [];
    for (i = 1; i < 5; i++) {
        var _$Wa = Date.parse(new Date());
        pr.push(_0x474032(_$Wa))
    }
    var _$yw = new Date().valueOf().toString();
    pr.push(_0x474032(_$yw));
    cookie_m = pr[4];
    cookie_rm4 = rm4Encrypt(_$yw, pr.toString());
    return {
        "cookie_m": cookie_m,
        "cookie_rm4": cookie_rm4,
        "m": _$yw,
        "f": Date.parse(new Date()).toString()
    }
}

console.log(getParamers());

Python代码

import execjs
import requests
import re

def encrypt_yrx5():
    room_heat_all = []
    for page_num in range(1, 6):
        with open('yrx5.js', 'r', encoding='utf-8') as f:
            encrypt = f.read()
        encrypt_params = execjs.compile(encrypt).call('getParamers')
        
        headers = {
            "user-agent": "yuanrenxue,project",
        }
        cookies = {
            "sessionid": "your sessionid",
            "m": encrypt_params['cookie_m'],
            "RM4hZBv0dDon443M": encrypt_params['cookie_rm4']
        }
        params = {
            "m": encrypt_params['m'],
            "f": encrypt_params['f']
        }
        
        url = "https://match.yuanrenxue.com/api/match/5?page=%s" % page_num
        response = requests.get(url, headers=headers, cookies=cookies, params=params)
        
        for i in range(10):
            value = response.json()['data'][i]
            room_heat = re.findall(r"'value': (\d+)", str(value))[0]
            room_heat_all.append(room_heat)
    
    room_heat_all.sort(reverse=True)
    top_five_total = 0
    for i in range(5):
        top_five_total += int(room_heat_all[i])
    print(top_five_total)

if __name__ == '__main__':
    encrypt_yrx5()

关键点总结

  1. Cookie参数生成

    • m参数:时间戳经过_0x474032函数处理
    • RM4hZBv0dDon443M参数:AES加密结果
  2. AES加密细节

    • 密钥:时间戳base64编码后前16位
    • 加密内容:包含5个时间相关值的数组
    • 加密模式:ECB
    • 填充方式:pkcs7
  3. 请求参数

    • m:当前时间戳
    • fDate.parse(new Date())生成的时间戳
  4. 环境补全

    • 需要补全window['_$6_']window['_$tT']window['_$Jy']等变量
    • 注意op_0x42fb36b64pad等固定值
  5. 时间相关

    • Cookie有效期50秒,与时间戳差值对应
    • 代码中有50秒的定时器

学习资源

  • B站关注K哥爬虫:https://space.bilibili.com/1622879192
  • GitHub关注K哥爬虫:https://github.com/kgepachong/

通过本题可以学习到:

  1. JS混淆代码的分析方法
  2. Hook技术的应用
  3. AES加密的识别与逆向
  4. 时间戳在反爬中的应用
  5. 环境补全的技巧
JS逆向:猿人学Web比赛第五题 - JS混淆与乱码增强解析 逆向目标 目标网站:猿人学反混淆刷题平台Web第五题 任务:抓取全部5页直播间热度,计算前5名直播间热度的加和 主页:https://match.yuanrenxue.com/match/5 接口:https://match.yuanrenxue.com/api/match/5?m=XXX&f=XXX 逆向参数分析 需要解决的参数 URL请求参数: m f Cookie参数: m RM4hZBv0dDon443M 逆向过程详解 1. 抓包分析 数据通过XHR加载,接口为 5?m=XXX&f=XXX Cookie有效期仅为50秒,动态变化 2. Cookie加密参数分析 2.1 定位加密位置 使用Hook技术定位Cookie参数生成位置: 定位到关键代码行: 2.2 加密算法分析 关键加密部分为 _0x4e96b4['_$ss'] ,进一步分析发现是AES加密: 加密参数说明: 加密内容: _$Ww (由 _0x4e96b4['_$pr'] 转换而来) 密钥: _0x4e96b4['_$qF'] 加密模式:ECB 填充方式:pkcs7 2.3 密钥生成 密钥生成逻辑: 即:将时间戳base64编码后取前16位作为密钥 2.4 加密内容生成 _0x4e96b4['_$pr'] 是一个包含5个值的数组: 前4个值:由 Date.parse(new Date()) 生成并经过 _0x474032 函数处理 第5个值:时间戳经过 _0x474032 函数处理(也是m参数的值) 2.5 _ 0x474032函数分析 简化后的函数: 进一步分析: 2.6 关键环境变量 需要补全的环境变量: 3. 请求头参数分析 3.1 m参数 m 的值是 window._$is ,即时间戳 _$yw 3.2 f参数 f 的值是 window.$_zw[23] ,由时间戳生成: 完整代码实现 JavaScript代码 Python代码 关键点总结 Cookie参数生成 : m 参数:时间戳经过 _0x474032 函数处理 RM4hZBv0dDon443M 参数:AES加密结果 AES加密细节 : 密钥:时间戳base64编码后前16位 加密内容:包含5个时间相关值的数组 加密模式:ECB 填充方式:pkcs7 请求参数 : m :当前时间戳 f : Date.parse(new Date()) 生成的时间戳 环境补全 : 需要补全 window['_$6_'] 、 window['_$tT'] 、 window['_$Jy'] 等变量 注意 op 、 _0x42fb36 、 b64pad 等固定值 时间相关 : Cookie有效期50秒,与时间戳差值对应 代码中有50秒的定时器 学习资源 B站关注K哥爬虫:https://space.bilibili.com/1622879192 GitHub关注K哥爬虫:https://github.com/kgepachong/ 通过本题可以学习到: JS混淆代码的分析方法 Hook技术的应用 AES加密的识别与逆向 时间戳在反爬中的应用 环境补全的技巧