【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
逆向参数分析
需要解决的参数
-
URL请求参数:
- m
- f
-
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个值的数组:
- 前4个值:由
Date.parse(new Date())生成并经过_0x474032函数处理 - 第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()
关键点总结
-
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加密的识别与逆向
- 时间戳在反爬中的应用
- 环境补全的技巧