【中等】 猿人学web第一届 第5题 js混淆-乱码增强

文章目录

  • 请求流程
    • 请求参数
    • cookie信息
  • 加密参数定位
    • Hook Cookie
    • AST 还原混淆代码
      • 解密函数还原字符串
      • 还原数组引用
      • 还原浏览器内置对象 / 变量值引用
      • 还原逗号表达式
      • 还原 unicode, 16进制数值
      • 字符串相加
      • AST 解混淆完整代码
  • 加密参数还原
    • cookie m字段
      • m字段坑点
    • cookie RM4hZBv0dDon443M 字段
      • hook window\["_$ss"\]
      • Hook window\['_$qF'\]
    • 请求参数
  • 请求代码

请求流程

打开 调试工具,查看数据接口 https://match.yuanrenxue.cn/api/match/5

在这里插入图片描述

请求参数

请求参数携带了 page, m, f 3个字段,
page为页数,
m 为时间戳 像是 new Date().getTIme() 生成的
f 为时间戳 像是 Date.parse(new Date()) 生成的
在这里插入图片描述

cookie信息

请求的 cookie 携带了两个字段
RM4hZBv0dDon443M字段 和 m字段
在这里插入图片描述

加密参数定位

Hook Cookie

cookie 中有两个加密字段 m, RM4hZBv0dDon443M
Hook Cookie 找到生成这两个字段信息的关键代码

// Hook Cookie
(function () {let cookie_func = Object.getOwnPropertyDescriptor(Document.prototype, 'cookie')Object.defineProperty(document, 'cookie', {get() {return cookie_func.get.call(this);},set(val) {console.log(val);debugger;return cookie_func.set.call(this, val);}})
})();

勾选事件监听断点中的脚本断点在这里插入图片描述并刷新页面
刷新页面之后将 脚本断点取消 将 Hook Cookie 的代码在控制台注入之后放开断点
在这里插入图片描述
断点断住之后查看对应生成 cookie 的位置,对应的 js 文件是做了混淆的
解个混淆先
在这里插入图片描述

这段代码是在 eval 函数里执行的,向上查看堆栈,是在 5.html 文件中生成的代码,然后放入 eval 函数中执行
在这里插入图片描述

这段代码是经过混淆的,解混淆以后会容易看很多

AST 还原混淆代码

解密函数还原字符串

文件开头定义了一个数组 _0x34bd
后定义了解密函数,解密函数依赖 _0x34bd
后又将解密函数 _0x34bd 赋值给了 _0x1383f7
调用方式就为 _0x1383f7(…)
在这里插入图片描述

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

将解密函数和依赖一起放入 AST 文件中
遍历 CallExpression 节点
且 callee 类型为 Identifier name属性值为 _0x1383f7
arguments长度为1,且获取 arguments 参数中的 value 值

// 解密函数还原
var _0x34bd = ["_$zr", ...数组太长了,剩下的省略了];
var _0x54e9 = function (_0x1b88e5, _0x1abb3d) {
_0x1b88e5 = _0x1b88e5 - 229;
var _0x34bd3d = _0x34bd[_0x1b88e5];
return _0x34bd3d;
};
var _0x1383f7 = _0x54e9;
(function (_0x5340a0, _0x2aca3b) {
var _0x595372 = _0x54e9;
while (!![]) {try {var _0x133a0b = parseInt(_0x595372(572)) + parseInt(_0x595372(418)) * -parseInt(_0x595372(834)) + -parseInt(_0x595372(350)) * -parseInt(_0x595372(483)) + parseInt(_0x595372(823)) + -parseInt(_0x595372(744)) + parseInt(_0x595372(382)) * parseInt(_0x595372(710)) + -parseInt(_0x595372(847)) * -parseInt(_0x595372(496));if (_0x133a0b === _0x2aca3b) break;else _0x5340a0["push"](_0x5340a0["shift"]());} catch (_0x28ba71) {_0x5340a0["push"](_0x5340a0["shift"]());}
}
})(_0x34bd, 997352)
traverse(ast, {CallExpression(path){// callee 类型为 Identifier name属性值为 _0x1383f7// arguments长度为1,且获取 arguments 参数中的 value 值if(path.get('callee').isIdentifier({name: '_0x1383f7'}) && path.node.arguments.length === 1){console.log('解密函数还原前: ', path + '')let Arg = path.node.arguments[0].value;  // 获取参数值// 将节点替换path.replaceWith(types.valueToNode(_0x1383f7(Arg)))console.log('解密函数还原后: ', path + '')console.log('==============================')}}
})

还原数组引用

在这里插入图片描述
在这里插入图片描述
文件中有很多引用到 _0xceb4b2 数组的地方
可以看到 _0xceb4b2 数组是通过 _0xac9d20() 方法执行后生成的
在浏览器中 copy(_0xceb4b2 ) 数组拿到本地就可以
_$UH 的值也是 _0xceb4b2 在文件中也有很多引用到的地方

注意
_0xceb4b2 在 _0xac9d20() 方法执行后生成了大数组后又赋值给了 _$UH
$UH 在随后的又进行了一系列操作,导致数组又变化了
在这里插入图片描述在这里插入图片描述
copy() 大数组时在文件最后的 return 处 copy()
在这里插入图片描述
单单 copy() 是行不通的,
$UH 后续赋值了 内置对象 window,导致 copy 之后只得到一串字符串

copy 代码

_$UH_copy = []
for(const index in _$UH){if (window === _$UH[index]){_$UH_copy.push('window')}else{_$UH_copy.push(_$UH[index])}
}
copy(_$UH_copy)

将取值代码放入ast网站中
在这里插入图片描述
在这里插入图片描述
遍历 MemberExpression 节点
object 为 Identifier 类型 且 name 属性值为 _0xceb4b2

object 为 Identifier 类型 且 name 属性值为 _$UH
property 为 NumericLiteral 类型,后续拿到对应的 value 值

// 数组引用还原
let _0xceb4b2 = ["name",// ... 数组太长了剩下的省略了
];
traverse(ast, {MemberExpression(path) {// object 为 Identifier 类型 且 name 属性值为字符串 _0xceb4b2// property 为 NumericLiteral 类型if (path.get('object').isIdentifier({name: '_0xceb4b2'}) || path.get('object').isIdentifier({name: '_$UH'}) && path.get('property').isNumericLiteral()) {// 拿到 property 节点中的 value 值let value = path.node.property.value;// 节点替换console.log('数组引用还原前: ', path.parentPath + '');if (_0xceb4b2[value] === 'window') {path.replaceWith(types.identifier('window'));} else {path.replaceWith(types.valueToNode(_0xceb4b2[value]));}console.log('数组引用还原后: ', path.parentPath + '');console.log('==============================')}}
})

还原浏览器内置对象 / 变量值引用

文件中有很多类似这样的操作
将一个浏览器内置对象赋值给一个变量,后续操作这个变量赋值给下一个变量
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
遍历 VariableDeclarator 节点
init 节点中 name 属性值为对应的 浏览器内置对象的值
后续获取节点中 id 属性中对应的 name 值
拿到 name 值后 获取对应的引用,将 name 值替换成对应的浏览器内置对象

function reductionVar(init, name, type) {traverse(ast, {Identifier(identPath) {if (identPath.node.name === name) {// _0x4e96b4 = window 这样的节点是不需要修改的// _0x4e96b4['$_zw'] 需要修改这样的 MemberExpression 节点if (type === 'CallExpression' && identPath.parentPath.isCallExpression()) {// identPath_.replaceWith(types.identifier(init))console.log('内置对象引用还原前:  ', identPath.parentPath + '');identPath.replaceWith(init);console.log('内置对象引用还原后:  ', identPath.parentPath + '');console.log('==============================')}if (type === 'MemberExpression' && identPath.parentPath.isMemberExpression()) {// identPath_.replaceWith(types.identifier(init))console.log('内置对象引用还原前:  ', identPath.parentPath + '');identPath.replaceWith(types.identifier(init));console.log('内置对象引用还原后:  ', identPath.parentPath + '');console.log('==============================')}}identPath.skip()}})
}
// 浏览器内置对象引用
let nativeArray = ['window','String','Error','Array','Math','parseInt','Date','document','Object','unescape','encodeURIComponent','Function','CryptoJS'
].join('...') + '...';
traverse(ast, {VariableDeclarator(path) {let init = path.get('init').isIdentifier() && path.node.init.name;if (init && nativeArray.indexOf(init + '...') !== -1) {let name = path.get('id').isIdentifier() && path.node.id.name;reductionVar(init, name, 'MemberExpression')}},AssignmentExpression(path) {if (path.get('left').isIdentifier() && path.get('right').isIdentifier()) {let init = path.node.right.name;if (init && nativeArray.indexOf(init + '...') !== -1) {let name = path.node.left.name;reductionVar(init, name, 'MemberExpression')}}}
})
// 变量值引用
traverse(ast, {VariableDeclarator(path) {if (path.get('id').isIdentifier() && path.get('init').isMemberExpression()) {let init = path.node.init;let init_name = path.node.init.object;for (let i=0; i < 10; i++) {if (types.isIdentifier(init_name)) {init_name = init_name.name;}if (types.isMemberExpression(init_name)) {init_name = init_name.object;}}let name = path.node.id.name;if (init && nativeArray.indexOf(init_name + '...') !== -1) {console.log('内置对象: ', generator(init).code, ' 引用对象:  ', name);reductionVar(init, name, 'CallExpression')}}}
})

还原逗号表达式

在这里插入图片描述
在这里插入图片描述
遍历 VariableDeclaration 节点,且改节点中 declarations 的长度大于 1
获取 declarations 数组,declarations数组中每个元素都创建新的 VariableDeclaration 节点
将当前节点替换成新创建的 VariableDeclaration 节点

在这里插入图片描述
在这里插入图片描述
遍历 SequenceExpression 节点,且 expressions 数组的元素大于1
获取 expressions 数组
将数组中的每个元素都创建为新的 ExpressionStatement 节点
将当前节点替换成新创建的 ExpressionStatement 节点

// 还原逗号表达式
// 逗号表达式
traverse(ast, {VariableDeclaration(path) {if (path.get('declarations').length > 1) {// 例如: var a, b, c// 拿到声明符号 varlet kind = path.node.kind;// 拿到 a, b, c 变量let Arg = path.get('declarations')// 创建的节点元素let nodeList = []for (const index in Arg) {// 创建一个新的 VariableDeclaration 节点// var a// var b// var clet varTionNode = types.variableDeclaration(kind, [Arg[index].node]);nodeList.push(varTionNode);console.log('逗号表达式:  ', generator(varTionNode).code.slice(0, 50).replaceAll('\n', ''));console.log('============================================================');}// 替换当前节点path.replaceWithMultiple(nodeList);}},SequenceExpression(path) {if (path.get('expressions').length > 1) {let Arg = path.get('expressions');let nodeList = []for (const index in Arg) {// 创建新的 ExpressionStatement 节点let experNode = types.expressionStatement(Arg[index].node);nodeList.push(experNode)console.log('逗号表达式:  ', generator(experNode).code.slice(0, 50).replaceAll('\n', ''));console.log('============================================================');}// 替换当前节点path.replaceWithMultiple(nodeList);path.skip();}}
})

还原 unicode, 16进制数值

// 还原 unicode, 16进制数值
traverse(ast, {"StringLiteral|NumericLiteral"(path) {if(path.node.extra){console.log('数值,unicode还原前:  ', path.node.extra.raw);delete path.node.extra.raw;console.log('数值,unicode还原后:  ', path.node.extra.rawValue);console.log('==============================')}}
});

字符串相加

// 字符串相加
function strConcat(path) {for (let i = 0; i <= 2; i++) {let node = path.node// left 节点为 StringLiteral 类型// right 节点为 StringLiteral 类型// operator 操作符属性为字符串 +if (types.isStringLiteral(node.left) && types.isStringLiteral(node.right) && node.operator === '+') {// 例 'e' + 'f'console.log('字符串相加前: ', path + '');// 例 'e' + 'f'let result = path.node.left.value + path.node.right.value;// 例: 'e' + 'f'// 替换成: 'ef'path.replaceWith(types.valueToNode(result));console.log('字符串相加后:  ', path + '');console.log('============================================================');} else {// 递归是针对多个字符串相加的// 例当前遍历到的节点: 'a' + 'b' + 'c' + 'd'// 这个节点在上面是不会处理的// path 对象的 traverse 方法是从当前节点继续遍历// 传入 strConcat 方法的节点就为:  'a' + 'b' + 'c' + 'd'// 调用过后还是会再次进入到 path.traverse 因为还是会有多个字符串相加// 上一次传入的节点被处理过了// 所以这一次传入的节点代码就为 'ab' + 'c' + 'd'// 一直递归到节点为 'abc' + 'd' 就会停止递归// 'abc' + 'd' 在 for 循环中会二次处理 (可以试着for循环只遍历一次看看效果path.traverse({BinaryExpression(path_) {strConcat(path_)}})}}
}
traverse(ast, {BinaryExpression(path) {  // 遍历 BinaryExpression 节点strConcat(path)}
})

AST 解混淆完整代码

// 安装 babel 库:  npm install @babel/core
const fs = require('fs');const traverse = require('@babel/traverse').default; // 用于遍历 AST 节点
const types = require('@babel/types');  // 用于判断, 生成 AST 节点const parser = require('@babel/parser');  // 将js代码解析成ast节点
const generator = require('@babel/generator').default;  // 将ast节点转换成js代码// 读取(路径记得改)
const ast_code = fs.readFileSync('demo.js', {encoding: 'utf-8'
});let ast = parser.parse(ast_code);  // 将js代码解析成ast语法树// 这里插入解析规则
///
// 解密函数还原
var _0x34bd = ["_$zr", "_$d5", ..];
var _0x54e9 = function (_0x1b88e5, _0x1abb3d) {_0x1b88e5 = _0x1b88e5 - 229;var _0x34bd3d = _0x34bd[_0x1b88e5];return _0x34bd3d;
};
var _0x1383f7 = _0x54e9;
(function (_0x5340a0, _0x2aca3b) {var _0x595372 = _0x54e9;while (!![]) {try {var _0x133a0b = parseInt(_0x595372(572)) + parseInt(_0x595372(418)) * -parseInt(_0x595372(834)) + -parseInt(_0x595372(350)) * -parseInt(_0x595372(483)) + parseInt(_0x595372(823)) + -parseInt(_0x595372(744)) + parseInt(_0x595372(382)) * parseInt(_0x595372(710)) + -parseInt(_0x595372(847)) * -parseInt(_0x595372(496));if (_0x133a0b === _0x2aca3b) break; else _0x5340a0["push"](_0x5340a0["shift"]());} catch (_0x28ba71) {_0x5340a0["push"](_0x5340a0["shift"]());}}
})(_0x34bd, 997352);
traverse(ast, {CallExpression(path) {// callee 类型为 Identifier name属性值为 _0x1383f7// arguments长度为1,且获取 arguments 参数中的 value 值if (path.get('callee').isIdentifier({name: '_0x1383f7'}) && path.node.arguments.length === 1) {console.log('解密函数还原前: ', path + '')let Arg = path.node.arguments[0].value;  // 获取参数值// 将节点替换path.replaceWith(types.valueToNode(_0x1383f7(Arg)))console.log('解密函数还原后: ', path + '')console.log('==============================')}}
});// 数组引用还原
let _0xceb4b2 = ["name","setAttribute",...
];
traverse(ast, {MemberExpression(path) {// object 为 Identifier 类型 且 name 属性值为字符串 _0xceb4b2// property 为 NumericLiteral 类型if (path.get('object').isIdentifier({name: '_0xceb4b2'}) || path.get('object').isIdentifier({name: '_$UH'}) && path.get('property').isNumericLiteral()) {// 拿到 property 节点中的 value 值let value = path.node.property.value;// 节点替换console.log('数组引用还原前: ', path.parentPath + '');if (_0xceb4b2[value] === 'window') {path.replaceWith(types.identifier('window'));} else {path.replaceWith(types.valueToNode(_0xceb4b2[value]));}console.log('数组引用还原后: ', path.parentPath + '');console.log('==============================')}}
})function reductionVar(init, name, type) {traverse(ast, {Identifier(identPath) {if (identPath.node.name === name) {// _0x4e96b4 = window 这样的节点是不需要修改的// _0x4e96b4['$_zw'] 需要修改这样的 MemberExpression 节点if (type === 'CallExpression' && identPath.parentPath.isCallExpression()) {// identPath_.replaceWith(types.identifier(init))console.log('内置对象引用还原前:  ', identPath.parentPath + '');identPath.replaceWith(init);console.log('内置对象引用还原后:  ', identPath.parentPath + '');console.log('==============================')}if (type === 'MemberExpression' && identPath.parentPath.isMemberExpression()) {// identPath_.replaceWith(types.identifier(init))console.log('内置对象引用还原前:  ', identPath.parentPath + '');identPath.replaceWith(types.identifier(init));console.log('内置对象引用还原后:  ', identPath.parentPath + '');console.log('==============================')}}identPath.skip()}})
}
// 浏览器内置对象引用
let nativeArray = ['window','String','Error','Array','Math','parseInt','Date','document','Object','unescape','encodeURIComponent','Function','CryptoJS'
].join('...') + '...';
traverse(ast, {VariableDeclarator(path) {let init = path.get('init').isIdentifier() && path.node.init.name;if (init && nativeArray.indexOf(init + '...') !== -1) {let name = path.get('id').isIdentifier() && path.node.id.name;reductionVar(init, name, 'MemberExpression')}},AssignmentExpression(path) {if (path.get('left').isIdentifier() && path.get('right').isIdentifier()) {let init = path.node.right.name;if (init && nativeArray.indexOf(init + '...') !== -1) {let name = path.node.left.name;reductionVar(init, name, 'MemberExpression')}}}
})
// 变量值引用
traverse(ast, {VariableDeclarator(path) {if (path.get('id').isIdentifier() && path.get('init').isMemberExpression()) {let init = path.node.init;let init_name = path.node.init.object;for (let i=0; i < 10; i++) {if (types.isIdentifier(init_name)) {init_name = init_name.name;}if (types.isMemberExpression(init_name)) {init_name = init_name.object;}}let name = path.node.id.name;if (init && nativeArray.indexOf(init_name + '...') !== -1) {console.log('内置对象: ', generator(init).code, ' 引用对象:  ', name);reductionVar(init, name, 'CallExpression')}}}
})// 逗号表达式
traverse(ast, {VariableDeclaration(path) {if (path.get('declarations').length > 1) {// 例如: var a, b, c// 拿到声明符号 varlet kind = path.node.kind;// 拿到 a, b, c 变量let Arg = path.get('declarations')// 创建的节点元素let nodeList = []for (const index in Arg) {// 创建一个新的 VariableDeclaration 节点// var a// var b// var clet varTionNode = types.variableDeclaration(kind, [Arg[index].node]);nodeList.push(varTionNode);console.log('逗号表达式:  ', generator(varTionNode).code.slice(0, 50).replaceAll('\n', ''));console.log('============================================================');}// 替换当前节点path.replaceWithMultiple(nodeList);}},SequenceExpression(path) {if (path.get('expressions').length > 1) {let Arg = path.get('expressions');let nodeList = []for (const index in Arg) {// 创建新的 ExpressionStatement 节点let experNode = types.expressionStatement(Arg[index].node);nodeList.push(experNode)console.log('逗号表达式:  ', generator(experNode).code.slice(0, 50).replaceAll('\n', ''));console.log('============================================================');}// 替换当前节点path.replaceWithMultiple(nodeList);path.skip();}}
})// 还原 unicode, 16进制数值
traverse(ast, {"StringLiteral|NumericLiteral|DirectiveLiteral"(path) {if(path.node.extra){console.log('数值,unicode还原前:  ', path.node.extra.raw);delete path.node.extra.raw;console.log('数值,unicode还原后:  ', path.node.extra.rawValue);console.log('==============================')}}
});// 字符串相加
function strConcat(path) {for (let i = 0; i <= 2; i++) {let node = path.node// left 节点为 StringLiteral 类型// right 节点为 StringLiteral 类型// operator 操作符属性为字符串 +if (types.isStringLiteral(node.left) && types.isStringLiteral(node.right) && node.operator === '+') {// 例 'e' + 'f'console.log('字符串相加前: ', path + '');// 例 'e' + 'f'let result = path.node.left.value + path.node.right.value;// 例: 'e' + 'f'// 替换成: 'ef'path.replaceWith(types.valueToNode(result));console.log('字符串相加后:  ', path + '');console.log('============================================================');} else {// 递归是针对多个字符串相加的// 例当前遍历到的节点: 'a' + 'b' + 'c' + 'd'// 这个节点在上面是不会处理的// path 对象的 traverse 方法是从当前节点继续遍历// 传入 strConcat 方法的节点就为:  'a' + 'b' + 'c' + 'd'// 调用过后还是会再次进入到 path.traverse 因为还是会有多个字符串相加// 上一次传入的节点被处理过了// 所以这一次传入的节点代码就为 'ab' + 'c' + 'd'// 一直递归到节点为 'abc' + 'd' 就会停止递归// 'abc' + 'd' 在 for 循环中会二次处理 (可以试着for循环只遍历一次看看效果path.traverse({BinaryExpression(path_) {strConcat(path_)}})}}
}
traverse(ast, {BinaryExpression(path) {  // 遍历 BinaryExpression 节点strConcat(path)}
})
///let js_code = generator(ast, {compact: true,  // 是否压缩,默认 false
}).code  // 将ast节点转换成js代码// 写入(路径记得改)
fs.writeFileSync('New_demo.js', js_code, {encoding: 'utf-8',
})

加密参数还原

将 5.html 文件开启替换,并将解混淆后的 js 代码替换到对应的 Script 标签
全局搜索 function _$KS() {
将这个函数内的代码替换成 解混淆后的js代码
在这里插入图片描述
在这里插入图片描述

开启脚本断点
刷新页面 Hook Cookie 后取消勾选脚本断点,开始调试

Hook Cookie

(function () {let cookie_func = Object.getOwnPropertyDescriptor(Document.prototype, 'cookie')Object.defineProperty(document, 'cookie', {get() {return cookie_func.get.call(this);},set(val) {if (val.indexOf('m') !== -1 || val.indexOf('RM4hZBv0dDon443M') !== -1){debuggerconsole.log(val);}return cookie_func.set.call(this, val);}})
})();

在 m 字段设置第 5 次之后 RM4 才会赋值
在这里插入图片描述

cookie m字段

m字段一共会生成 5 次

前 4 次生成的位置

_$Wa = _0x12eaf3();  // _0x12eaf3() 是 Date["parse"](new Date())
document[_$Fe] = "m=" + _0x474032(_$Wa) + "; path=/";
window["_$pr"]["push"](_0x474032(_$Wa));  // _$pr 刚开始是空数组
/*
_$tT 和 _$Jy 初始的定义为
window["_$tT"] = -172015004;
window["_$Jy"] = 461512024;
*/
delete window["_$Jy"];
delete window["_$tT"];
window["_$Jy"] = _0x2d5f5b();  // new Date()["valueOf"]()
window["_$tT"] = _0x2d5f5b() - _0x12eaf3();  // new Date()["valueOf"]() - Date["parse"](new Date())

_0x474032() 方法时只需要扣 return 最后一个方法,因为传进去的参数始终就只有一个

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

_0x11a7a2() 方法里有检测

try {// window["XMLHttpRequest"]["prototype"]["DONE"] 的值始终为 4var _0x42fb36 = window["XMLHttpRequest"]["prototype"]["DONE"] * 4;
} catch (_0x1b1b35) {var _0x42fb36 = 1;
}
// 改写为
var _0x42fb36 = 4 * 4;
try {window["$_z2"][0] = "Q";
} catch (_0x4c574d) {try {// window["$_zw"]["length"] 的值为 27op = window["$_zw"]["length"];} catch (_0x58af26) {var _0x3b7935 = 0;for (var _0x1badc3 = 0; _0x1badc3 < 1000000; _0x1badc3++) {_0x3b7935 = _0x3b7935 + _0x1badc3["toString"]();history["pushState"](0, 0, _0x3b7935);}}if (op > 20) {// 执行后 b64pad 的值为 1eval("b64pad = _0x4e96b4['$_zw'][9]['length'];");} else if (op < 10) {window["$_zw"] = [1, 8, 2, 4, 23, 45, 8, 15, 81, 68, 13, 72, 70];}
}
// 改写
op = 27;
b64pad = 1;
var _0x3e0c38 = _0x1171c8;
var _0xdb4d2c = _0x4dae05;
var _0x1724c5 = _0x183a1d;
var _0x257ec6 = _0xcfa373;
// 全局搜索, _0x1171c8 可以找到定义位置
// 定义在文件开头处
var _0x1171c8 = 1732584193;
var _0x4dae05 = -271733879;
var _0x183a1d = -1732584194;
var _0xcfa373 = 271733878;
try {if (window["_$6_"]) {} else {window["_$6_"] = 8821003647;}
} catch (_0x15bf3f) {window["_$6_"] = 37885443;
}
// 控制台查看对应的值为 8821003647
// 改写
window["_$6_"] = 8821003647;

第 5 次生成的位置

_$yw = _0x2d5f5b()["toString"]();  // new Date()["valueOf"]();
document[_$Fe] = "m=" + _0x474032(_$yw) + "; path=/";
window["_$is"] = _$yw;  // 这个在后面加密 rm4 字段时有用
window["_$pr"]["push"](_0x474032(_$yw));

m字段坑点

加密时依赖的几个变量

这几个变量都需要在  _0x11a7a2() 方法中用到
window["_$Jy"], window["_$tT"], _0x42fb36
b64pad, _0x1171c8, _0x4dae05, _0x183a1d, _0xcfa373, window["_$6_"]其实只要关注 
window["_$Jy"], window["_$tT"], window["_$6_"]

在 _0x11a7a2() 方法中插上条件断点

console.log("_$Jy  ", window["_$Jy"], '\n',"_$tT  ", window["_$tT"], '\n',"_$6_  ", window["_$6_"], '\n',
)

for (_0x1badc3 = 0; 处在这里插入图片描述

重新 hook Cookie 直到 RM4hZBv0dDon443M 字段有值为止
第 1-4 次
在这里插入图片描述
第 5 次(重点)
在这里插入图片描述
刷新页面第 5 次的值还是固定的

cookie RM4hZBv0dDon443M 字段

开启脚本断点,刷新页面注入 Hook 代码
在 Hook 到 RM4 字段并且有值的时候查看上一层堆栈
(前2次的值是 undefined 不用理)
(后两次的值是一样的)
在这里插入图片描述

RM4 生成位置

// _$Fe 是 ’cookie‘
document[_$Fe] = "RM4hZBv0dDon443M=" + window["_$ss"] + "; path=/";

hook window[“_$ss”]

Hook 代码

// 老样子开启脚本断点,刷新页面,注入 Hook 代码 + Cookie 代码// Hook Cookie
(function () {let cookie_func = Object.getOwnPropertyDescriptor(Document.prototype, 'cookie')Object.defineProperty(document, 'cookie', {get() {return cookie_func.get.call(this);},set(val) {console.log(val);debugger;return cookie_func.set.call(this, val);}})
})();// Hook window['_$ss']
(function () {let __$ss = window['_$ss'];Object.defineProperty(window, '_$ss', {get() {return __$ss},set(val) {debugger__$ss = val;}})
}
)()

在断点断住时查看上一层堆栈
_$ss 生成位置在这里插入图片描述

// window["_$pr"] 在前5次cookie生成的时候就有值了
_$Ww = CryptoJS["enc"]["Utf8"]["parse"](window["_$pr"]["toString"]());// _0xc77418("0x6", "OCbs") 执行之后是 '_$qF' 
_0x29dd83 = CryptoJS["AES"]["encrypt"](_$Ww, window[_0xc77418("0x6", "OCbs")], {"mode": CryptoJS["mode"]["ECB"],"padding": CryptoJS["pad"]["Pkcs7"]
});// _$ss 生成位置
window["_$" + "cs7"[1] + "cs7"[1]] = _0x29dd83["toString"]();

CryptoJS 在 nodejs 中直接导包就可以了 let CryptoJs = require(‘crypto-js’);
window[0xc77418(“0x6”, “OCbs”)] 也就是 window['$qF’] 生成的位置要找

Hook window[‘_$qF’]

// 和 Hook _$ss 的方式一样 开启脚本断点,注入代码后放开
// Hook Cookie
(function () {let cookie_func = Object.getOwnPropertyDescriptor(Document.prototype, 'cookie')Object.defineProperty(document, 'cookie', {get() {return cookie_func.get.call(this);},set(val) {console.log(val);debugger;return cookie_func.set.call(this, val);}})
})();// Hook window._$qF
(function () {let __$qF = window['_$qF'];Object.defineProperty(window, '_$qF', {get() {return __$qF},set(val) {debugger__$qF = val;}})
}
)()

_$qf 生成位置在这里插入图片描述

window["_$qF"] = CryptoJS["enc"]["Utf8"]["parse"](window["btoa"](window["_$is"])["slice"](0, 16));// window["_$is"] 在 m 第五次生成的时候有赋值
// window["_$is"] = _$yw;

这段代码会执行很多次,插个日志断点查看值即可
在这里插入图片描述

console.log(window["_$is"])
// 全局搜索 _0x456805 < 213

在 m 生成的时候会给 _$yw 赋值,在赋值的位置也打上日志断点,确认是否引用了这个值
在这里插入图片描述

console.log(_$yw)
// 全局搜索
// _$aA["_$ji"] = _$aA[_$aA["_$ji"]](_0x2566fa, _0x56717d);

插好日志断点以后,还是刷新页面 Hook Cookie

第 5 次设置 m字段后 _$ym 有值了
在这里插入图片描述

window[“_$is”] 的值与 _$ym 一致
所以可以确定 $ym 就是 window["$is"]的值
在这里插入图片描述

请求参数

查看请求堆栈中 requests 栈
在这里插入图片描述
在这里插入图片描述

var list = {"page": window.page,"m": window._$is,  // window["_$is"] 在 cookie 设置第五次时就有赋值了"f": window.$_zw[23]};

全局搜索 $_zw[23]
在这里插入图片描述
let $_t1 = Date.parse(new Date());
在这里插入图片描述

验证
在这里插入图片描述

在这里插入图片描述

在整个代码逻辑中,$_t1 是最先赋值的 (let $_t1 = Date.parse(new Date());)
在 node 也是最先定义

请求代码

完整的 js 代码

window = global;
window["_$tT"] = -172015004;
window["_$Jy"] = 461512024;
window["_$pr"] = [];
var _0x1171c8 = 1732584193;
var _0x4dae05 = -271733879;
var _0x183a1d = -1732584194;
var _0xcfa373 = 271733878;
window["_$6_"] = 8821003647;var CryptoJS = require('crypto-js');
var window = global;function _0x3180ec(_0x401705, _0x240e6a, _0x56b131, _0x5a5c20, _0x1f2a72, _0x2bfc1, _0x19741a) {return _0xaaef84(_0x240e6a & _0x5a5c20 | _0x56b131 & ~_0x5a5c20, _0x401705, _0x240e6a, _0x1f2a72, _0x2bfc1, _0x19741a);
}
function _0x32032f(_0x520fdf, _0x13921d, _0x1af9d5, _0x4a2311, _0xb6d40a, _0x1d58da, _0x361df0) {return _0xaaef84(_0x13921d ^ _0x1af9d5 ^ _0x4a2311, _0x520fdf, _0x13921d, _0xb6d40a, _0x1d58da, _0x361df0);
}
function _0x4b459d(_0x8d8f2a, _0x406d34, _0x53e7d7, _0x26c827, _0xec41ea, _0x52dead, _0x3f66e7) {return _0xaaef84(_0x53e7d7 ^ (_0x406d34 | ~_0x26c827), _0x8d8f2a, _0x406d34, _0xec41ea, _0x52dead, _0x3f66e7);
}
function _0x3634fc(_0x5803ba, _0x1ce5b2) {return _0x5803ba << _0x1ce5b2 | _0x5803ba >>> 32 - _0x1ce5b2;
}
function _0x12e4a8(_0x7542c8, _0x5eada0) {var _0x41f81f = (65535 & _0x7542c8) + (65535 & _0x5eada0);return (_0x7542c8 >> 16) + (_0x5eada0 >> 16) + (_0x41f81f >> 16) << 16 | 65535 & _0x41f81f;
}
function _0xaaef84(_0xaf3112, _0x2a165a, _0x532fb4, _0x10aa40, _0x41c4e7, _0x1cb4da) {return _0x12e4a8(_0x3634fc(_0x12e4a8(_0x12e4a8(_0x2a165a, _0xaf3112), _0x12e4a8(_0x10aa40, _0x1cb4da)), _0x41c4e7), _0x532fb4);
}
function _0x48d200(_0x4b706e, _0x3c3a85, _0x111154, _0x311f9f, _0x5439cf, _0x38cac7, _0x26bd2e) {return _0xaaef84(_0x3c3a85 & _0x111154 | ~_0x3c3a85 & _0x311f9f, _0x4b706e, _0x3c3a85, _0x5439cf, _0x38cac7, _0x26bd2e);
}
function _0x35f5f2(_0x243853) {var _0x139b8b;var _0xa791a1 = [];for (_0xa791a1[(_0x243853["length"] >> 2) - 1] = void 0,_0x139b8b = 0; _0x139b8b < _0xa791a1["length"]; _0x139b8b += 1)_0xa791a1[_0x139b8b] = 0;var _0x41a533 = 8 * _0x243853["length"];for (_0x139b8b = 0; _0x139b8b < _0x41a533; _0x139b8b += 8)_0xa791a1[_0x139b8b >> 5] |= (255 & _0x243853["charCodeAt"](_0x139b8b / 8)) << _0x139b8b % 32;return _0xa791a1;
}
function _0x474032(_0x233f82, _0xe2ed33, _0x3229f9) {return _0x37614a(_0x233f82);
}
function _0x37614a(_0x32e7c1) {return _0x499969(_0x41873d(_0x32e7c1));
}
function _0x41873d(_0x5a6962) {return _0x1ee7ec(_0x2b8a17(_0x5a6962));
}
function _0x2b8a17(_0x36f847) {return unescape(encodeURIComponent(_0x36f847));
}
function _0x1ee7ec(_0x206333) {return _0x12b47d(_0x11a7a2(_0x35f5f2(_0x206333), 8 * _0x206333["length"]));
}
function _0x499969(_0x82fe7e) {var _0x5bdda4;var _0x322a73;var _0xd0b5cd = "0123456789abcdef";var _0x21f411 = "";for (_0x322a73 = 0; _0x322a73 < _0x82fe7e["length"]; _0x322a73 += 1) {_0x5bdda4 = _0x82fe7e["charCodeAt"](_0x322a73);_0x21f411 += _0xd0b5cd["charAt"](_0x5bdda4 >>> 4 & 15) + _0xd0b5cd["charAt"](15 & _0x5bdda4);}return _0x21f411;
}
function _0x12b47d(_0x149183) {var _0xabbcb3;var _0x1145c3 = "";var _0x4fce58 = 32 * _0x149183["length"];for (_0xabbcb3 = 0; _0xabbcb3 < _0x4fce58; _0xabbcb3 += 8)_0x1145c3 += String["fromCharCode"](_0x149183[_0xabbcb3 >> 5] >>> _0xabbcb3 % 32 & 255);return _0x1145c3;
}
function _0x11a7a2(_0x193f00, _0x1cfe89) {_0x193f00[_0x1cfe89 >> 5] |= 128 << _0x1cfe89 % 32;_0x193f00[14 + (_0x1cfe89 + 64 >>> 9 << 4)] = _0x1cfe89;var _0x42fb36 = 4 * 4;op = 27;b64pad = 1;var _0x1badc3;var _0x38ca59;var _0x431764;var _0x43f1b4;var _0x5722c0;var _0x3e0c38 = _0x1171c8;var _0xdb4d2c = _0x4dae05;var _0x1724c5 = _0x183a1d;var _0x257ec6 = _0xcfa373;for (_0x1badc3 = 0; _0x1badc3 < _0x193f00["length"]; _0x1badc3 += _0x42fb36) {_0x38ca59 = _0x3e0c38;_0x431764 = _0xdb4d2c;_0x43f1b4 = _0x1724c5;_0x5722c0 = _0x257ec6;_0x3e0c38 = _0x48d200(_0x3e0c38, _0xdb4d2c, _0x1724c5, _0x257ec6, _0x193f00[_0x1badc3], 7, 513548);_0x257ec6 = _0x48d200(_0x257ec6, _0x3e0c38, _0xdb4d2c, _0x1724c5, _0x193f00[_0x1badc3 + 1], 12, window["_$6_"]);_0x1724c5 = _0x48d200(_0x1724c5, _0x257ec6, _0x3e0c38, _0xdb4d2c, _0x193f00[_0x1badc3 + 2], 17, 606105819);_0xdb4d2c = _0x48d200(_0xdb4d2c, _0x1724c5, _0x257ec6, _0x3e0c38, _0x193f00[_0x1badc3 + 3], 22, -1044525330);_0x3e0c38 = _0x48d200(_0x3e0c38, _0xdb4d2c, _0x1724c5, _0x257ec6, _0x193f00[_0x1badc3 + 4], 7, -176418897);_0x257ec6 = _0x48d200(_0x257ec6, _0x3e0c38, _0xdb4d2c, _0x1724c5, _0x193f00[_0x1badc3 + 5], 12, 1200080426);_0x1724c5 = _0x48d200(_0x1724c5, _0x257ec6, _0x3e0c38, _0xdb4d2c, _0x193f00[_0x1badc3 + 6], 17, -1473231341);_0xdb4d2c = _0x48d200(_0xdb4d2c, _0x1724c5, _0x257ec6, _0x3e0c38, _0x193f00[_0x1badc3 + 7], 22, -45705983);_0x3e0c38 = _0x48d200(_0x3e0c38, _0xdb4d2c, _0x1724c5, _0x257ec6, _0x193f00[_0x1badc3 + 8], 7, 1770035416);_0x257ec6 = _0x48d200(_0x257ec6, _0x3e0c38, _0xdb4d2c, _0x1724c5, _0x193f00[_0x1badc3 + 9], 12, -1958414417);_0x1724c5 = _0x48d200(_0x1724c5, _0x257ec6, _0x3e0c38, _0xdb4d2c, _0x193f00[_0x1badc3 + 10], 17, -42063);_0xdb4d2c = _0x48d200(_0xdb4d2c, _0x1724c5, _0x257ec6, _0x3e0c38, _0x193f00[_0x1badc3 + 11], 22, -1990404162);_0x3e0c38 = _0x48d200(_0x3e0c38, _0xdb4d2c, _0x1724c5, _0x257ec6, _0x193f00[_0x1badc3 + 12], 7, 1804603682);_0x257ec6 = _0x48d200(_0x257ec6, _0x3e0c38, _0xdb4d2c, _0x1724c5, _0x193f00[_0x1badc3 + 13], 12, -40341101);_0x1724c5 = _0x48d200(_0x1724c5, _0x257ec6, _0x3e0c38, _0xdb4d2c, _0x193f00[_0x1badc3 + 14], 17, -1502002290);_0xdb4d2c = _0x48d200(_0xdb4d2c, _0x1724c5, _0x257ec6, _0x3e0c38, _0x193f00[_0x1badc3 + 15], 22, 1236535329);_0x3e0c38 = _0x3180ec(_0x3e0c38, _0xdb4d2c, _0x1724c5, _0x257ec6, _0x193f00[_0x1badc3 + 1], 5, -165796510);_0x257ec6 = _0x3180ec(_0x257ec6, _0x3e0c38, _0xdb4d2c, _0x1724c5, _0x193f00[_0x1badc3 + 6], 9, -1069501632);_0x1724c5 = _0x3180ec(_0x1724c5, _0x257ec6, _0x3e0c38, _0xdb4d2c, _0x193f00[_0x1badc3 + 11], 14, 643717713);_0xdb4d2c = _0x3180ec(_0xdb4d2c, _0x1724c5, _0x257ec6, _0x3e0c38, _0x193f00[_0x1badc3], 20, -373897302);_0x3e0c38 = _0x3180ec(_0x3e0c38, _0xdb4d2c, _0x1724c5, _0x257ec6, _0x193f00[_0x1badc3 + 5], 5, -701558691);_0x257ec6 = _0x3180ec(_0x257ec6, _0x3e0c38, _0xdb4d2c, _0x1724c5, _0x193f00[_0x1badc3 + 10], 9, 38016083);_0x1724c5 = _0x3180ec(_0x1724c5, _0x257ec6, _0x3e0c38, _0xdb4d2c, _0x193f00[_0x1badc3 + 15], 14, window["_$tT"]);_0xdb4d2c = _0x3180ec(_0xdb4d2c, _0x1724c5, _0x257ec6, _0x3e0c38, _0x193f00[_0x1badc3 + 4], 20, window["_$Jy"]);_0x3e0c38 = _0x3180ec(_0x3e0c38, _0xdb4d2c, _0x1724c5, _0x257ec6, _0x193f00[_0x1badc3 + 9], 5, 568446438);_0x257ec6 = _0x3180ec(_0x257ec6, _0x3e0c38, _0xdb4d2c, _0x1724c5, _0x193f00[_0x1badc3 + 14], 9, -1019783690);_0x1724c5 = _0x3180ec(_0x1724c5, _0x257ec6, _0x3e0c38, _0xdb4d2c, _0x193f00[_0x1badc3 + 3], 14, -187363961);_0xdb4d2c = _0x3180ec(_0xdb4d2c, _0x1724c5, _0x257ec6, _0x3e0c38, _0x193f00[_0x1badc3 + 8], 20, 1163531501);_0x3e0c38 = _0x3180ec(_0x3e0c38, _0xdb4d2c, _0x1724c5, _0x257ec6, _0x193f00[_0x1badc3 + 13], 5, -1554681467);_0x257ec6 = _0x3180ec(_0x257ec6, _0x3e0c38, _0xdb4d2c, _0x1724c5, _0x193f00[_0x1badc3 + 2], 9, -51403784);_0x1724c5 = _0x3180ec(_0x1724c5, _0x257ec6, _0x3e0c38, _0xdb4d2c, _0x193f00[_0x1badc3 + 7], 14, 1735328473);_0xdb4d2c = _0x3180ec(_0xdb4d2c, _0x1724c5, _0x257ec6, _0x3e0c38, _0x193f00[_0x1badc3 + 12], 20, -1926607734);_0x3e0c38 = _0x32032f(_0x3e0c38, _0xdb4d2c, _0x1724c5, _0x257ec6, _0x193f00[_0x1badc3 + 5], 4, -37824558);_0x257ec6 = _0x32032f(_0x257ec6, _0x3e0c38, _0xdb4d2c, _0x1724c5, _0x193f00[_0x1badc3 + 8], 11, -2022574463);_0x1724c5 = _0x32032f(_0x1724c5, _0x257ec6, _0x3e0c38, _0xdb4d2c, _0x193f00[_0x1badc3 + 11], 16, 1839030562);_0xdb4d2c = _0x32032f(_0xdb4d2c, _0x1724c5, _0x257ec6, _0x3e0c38, _0x193f00[_0x1badc3 + 14], 23, -35309556);_0x3e0c38 = _0x32032f(_0x3e0c38, _0xdb4d2c, _0x1724c5, _0x257ec6, _0x193f00[_0x1badc3 + 1], 4, -1530992060 * b64pad);_0x257ec6 = _0x32032f(_0x257ec6, _0x3e0c38, _0xdb4d2c, _0x1724c5, _0x193f00[_0x1badc3 + 4], 11, 1272893353);_0x1724c5 = _0x32032f(_0x1724c5, _0x257ec6, _0x3e0c38, _0xdb4d2c, _0x193f00[_0x1badc3 + 7], 16, -155497632);_0xdb4d2c = _0x32032f(_0xdb4d2c, _0x1724c5, _0x257ec6, _0x3e0c38, _0x193f00[_0x1badc3 + 10], 23, -1094730640);_0x3e0c38 = _0x32032f(_0x3e0c38, _0xdb4d2c, _0x1724c5, _0x257ec6, _0x193f00[_0x1badc3 + 13], 4, 681279174);_0x257ec6 = _0x32032f(_0x257ec6, _0x3e0c38, _0xdb4d2c, _0x1724c5, _0x193f00[_0x1badc3], 11, -358537222);_0x1724c5 = _0x32032f(_0x1724c5, _0x257ec6, _0x3e0c38, _0xdb4d2c, _0x193f00[_0x1badc3 + 3], 16, -722521979);_0xdb4d2c = _0x32032f(_0xdb4d2c, _0x1724c5, _0x257ec6, _0x3e0c38, _0x193f00[_0x1badc3 + 6], 23, 760291289);_0x3e0c38 = _0x32032f(_0x3e0c38, _0xdb4d2c, _0x1724c5, _0x257ec6, _0x193f00[_0x1badc3 + 9], 4, -64036887);_0x257ec6 = _0x32032f(_0x257ec6, _0x3e0c38, _0xdb4d2c, _0x1724c5, _0x193f00[_0x1badc3 + 12], 11, -421815835);_0x1724c5 = _0x32032f(_0x1724c5, _0x257ec6, _0x3e0c38, _0xdb4d2c, _0x193f00[_0x1badc3 + 15], 16, 530742520);_0xdb4d2c = _0x32032f(_0xdb4d2c, _0x1724c5, _0x257ec6, _0x3e0c38, _0x193f00[_0x1badc3 + 2], 23, -995338651);_0x3e0c38 = _0x4b459d(_0x3e0c38, _0xdb4d2c, _0x1724c5, _0x257ec6, _0x193f00[_0x1badc3], 6, -198630844);_0x257ec6 = _0x4b459d(_0x257ec6, _0x3e0c38, _0xdb4d2c, _0x1724c5, _0x193f00[_0x1badc3 + 7], 10, 1126891415);_0x1724c5 = _0x4b459d(_0x1724c5, _0x257ec6, _0x3e0c38, _0xdb4d2c, _0x193f00[_0x1badc3 + 14], 15, -1416354905);_0xdb4d2c = _0x4b459d(_0xdb4d2c, _0x1724c5, _0x257ec6, _0x3e0c38, _0x193f00[_0x1badc3 + 5], 21, -57434055);_0x3e0c38 = _0x4b459d(_0x3e0c38, _0xdb4d2c, _0x1724c5, _0x257ec6, _0x193f00[_0x1badc3 + 12], 6, 1700485571);_0x257ec6 = _0x4b459d(_0x257ec6, _0x3e0c38, _0xdb4d2c, _0x1724c5, _0x193f00[_0x1badc3 + 3], 10, -1894746606);_0x1724c5 = _0x4b459d(_0x1724c5, _0x257ec6, _0x3e0c38, _0xdb4d2c, _0x193f00[_0x1badc3 + 10], 15, -105181523);_0xdb4d2c = _0x4b459d(_0xdb4d2c, _0x1724c5, _0x257ec6, _0x3e0c38, _0x193f00[_0x1badc3 + 1], 21, -2054922799);_0x3e0c38 = _0x4b459d(_0x3e0c38, _0xdb4d2c, _0x1724c5, _0x257ec6, _0x193f00[_0x1badc3 + 8], 6, 1873313359);_0x257ec6 = _0x4b459d(_0x257ec6, _0x3e0c38, _0xdb4d2c, _0x1724c5, _0x193f00[_0x1badc3 + 15], 10, -30611744);_0x1724c5 = _0x4b459d(_0x1724c5, _0x257ec6, _0x3e0c38, _0xdb4d2c, _0x193f00[_0x1badc3 + 6], 15, -1560198380);_0xdb4d2c = _0x4b459d(_0xdb4d2c, _0x1724c5, _0x257ec6, _0x3e0c38, _0x193f00[_0x1badc3 + 13], 21, 1309151649);_0x3e0c38 = _0x4b459d(_0x3e0c38, _0xdb4d2c, _0x1724c5, _0x257ec6, _0x193f00[_0x1badc3 + 4], 6, -145523070);_0x257ec6 = _0x4b459d(_0x257ec6, _0x3e0c38, _0xdb4d2c, _0x1724c5, _0x193f00[_0x1badc3 + 11], 10, -1120211379);_0x1724c5 = _0x4b459d(_0x1724c5, _0x257ec6, _0x3e0c38, _0xdb4d2c, _0x193f00[_0x1badc3 + 2], 15, 718787259);_0xdb4d2c = _0x4b459d(_0xdb4d2c, _0x1724c5, _0x257ec6, _0x3e0c38, _0x193f00[_0x1badc3 + 9], 21, -343485441);_0x3e0c38 = _0x12e4a8(_0x3e0c38, _0x38ca59);_0xdb4d2c = _0x12e4a8(_0xdb4d2c, _0x431764);_0x1724c5 = _0x12e4a8(_0x1724c5, _0x43f1b4);_0x257ec6 = _0x12e4a8(_0x257ec6, _0x5722c0);}return [_0x3e0c38, _0xdb4d2c, _0x1724c5, _0x257ec6];
}function sdk() {let $_t1 = Date.parse(new Date());// cookie_m  1-4 次for (let i = 0; i < 4; i++) {let _$Wa = Date["parse"](new Date());cookie_m = _0x474032(_$Wa);window["_$pr"].push(_0x474032(_$Wa));delete window["_$Jy"];delete window["_$tT"];window["_$Jy"] = new Date()["valueOf"]();window["_$tT"] = new Date()["valueOf"]() - Date["parse"](new Date());}// cookie_m  第五次window["_$Jy"] = -405537848;window["_$tT"] = -660478335;window["_$6_"] = -389564586;let _$yw = new Date()["valueOf"]();cookie_m = _0x474032(_$yw);window["_$is"] = _$yw;window["_$pr"]["push"](_0x474032(_$yw));// console.log(cookie_m);// console.log(_$pr);window["_$qF"] = CryptoJS["enc"]["Utf8"]["parse"](window["btoa"](window["_$is"])["slice"](0, 16));let _$Ww = CryptoJS["enc"]["Utf8"]["parse"](window["_$pr"]["toString"]());let cookie_rm4 = CryptoJS["AES"]["encrypt"](_$Ww, window['_$qF'], {"mode": CryptoJS["mode"]["ECB"],"padding": CryptoJS["pad"]["Pkcs7"]}).toString();// console.log(cookie_m);// console.log(cookie_rm4);return {cookie_m,cookie_rm4,params_m: window["_$is"],params_f: $_t1}
}
// console.log(sdk());

完整的 python 代码

import requests
import execjs
import timeheaders = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36",
}
cookies = {"sessionid": "你的sessionid","m": "","RM4hZBv0dDon443M": ""
}def call_js(file_name, func_name, *args):with open(file_name, mode='r', encoding='utf-8') as f:js_code = execjs.compile(f.read())return js_code.call(func_name, *args)def send_match5(page, param_dict):url = "https://match.yuanrenxue.cn/api/match/5"params = {"page": page,"m": param_dict['params_m'],"f": param_dict['params_f']}response = requests.get(url, headers=headers, cookies=cookies, params=params)cookies["m"] = param_dict['cookie_m']cookies["RM4hZBv0dDon443M"] = param_dict['cookie_rm4']print(params)print(cookies)print(response.json())print('==================================================')if __name__ == '__main__':time_ = int(str(int(time.time() * 1000))[:10] + '000')send_params = call_js('5.js', 'sdk')  # params_m, cookie_m, cookie_rm4send_params['params_f'] = time_for page in range(1, 3):send_match5(page, send_params)

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

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

相关文章

什么是云原生?(二)

1. 云原生的定义 云原生指构建和运行应用以充分利用通过云技术交付模式交付的分布式计算。云原生应用旨在充分利用云技术平台特有的可扩展性、弹性和灵活性优势。 根据云原生计算基金会 (CNCF) 的定义&#xff0c;云原生技术可帮助企业在公有云、私有云和混合云环境中构建和…

Unity Render Streaming项目实践经验

UnityRenderStreaming项目 项目github地址见上,我使用项目的3.1.0-exp.7版本、Unity 2023.1.0版本、windows11运行。 1下载项目包 2在Unity Hub中打开RenderStreaming~文件夹 3在package manager中导入com.unity.renderstreaming package 因为已经下载过了就选择install pa…

Word中加载Mathtype后粘贴复制快捷键(Ctrl+C/V)不能使用

操作环境 windows 11操作系统 word版本2021 mathtype版本7.4 这个问题只出现在word中&#xff0c;在excel和ppt中都不存在这个问题&#xff0c;而且之前在另一台电脑中使用word2016版本并没有这种问题的&#xff0c;然后网上搜了一下有不少人有这种问题&#xff0c;word直接取…

Docker Containerd初体验

Docker Containerd概述 ​ Containerd是一个开源的容器运行时&#xff0c;它提供了一种标准化的方式来管理容器的生命周期。该项目最初是由Docker开发团队创建的&#xff0c;并在后来成为了一个独立的项目&#xff0c;被纳入了Cloud Native Computing Foundation&#xff08;C…

Taos 常用命令工作笔记(二)

最近测试创建一个涛思的数据库和一堆表进行测试&#xff0c;通过json配置文件配置字段的类型、名称等&#xff0c;程序通过解析json文件的配置&#xff0c;动态创建数据库的表。 其中表字段为驼峰结构的规则命名&#xff0c;创建表也是成功的&#xff0c;插入的测试数据也是成功…

html页面缩放自适应

html页面缩放自适应 一、为什么页面要进行缩放自适应 在我们一般web端进行页面拼接完成后&#xff0c;在web端的显示正常&#xff08;毕竟我们是按照web端进行页面拼接完成的&#xff09;&#xff0c;那么要是用其他设备打开呢&#xff0c;比如手机或者平板&#xff0c;这时候…

【Datawhale AI夏令营第四期】魔搭-AIGC方向 Task02笔记 Scepter工具箱, 精读BaseLine代码

【Datawhale AI夏令营第四期】魔搭-AIGC方向 Task02笔记 Task02学习任务&#xff1a; https://linklearner.com/activity/14/10/32 传送门 我们继续看网课&#xff0c;并且在Kimi.AI的帮助下读一下BaseLine示例代码。 网课链接&#xff1a;https://space.bilibili.com/1069874…

WebService基础学习

一、XML回顾 二、HTTP协议回顾 三、复习准备 四、关于Web Service的几个问题 五、Web Service中的几个重要术语 六、开发webservice 七、WebService面试题

比char类型小的变量——位段

目录 开头1.什么是位段?2.位段的优缺点优点缺点 3.位段的实际应用…… 结尾 开头 大家好&#xff0c;我叫这是我58。在今天&#xff0c;我们将要介绍一个既比char类型小&#xff0c;又只用于结构体的一种东西——位段。 1.什么是位段? 位段&#xff0c;就是一种比char类型…

SpringBoot的事务/调度/缓存/邮件发送和一些Spring知识点总结

目录 1、SpringBoot的事务管理 2、SpringBoot的异步任务 3、SpringBoot定时任务调度 4、SpringBoot整合Mail发送邮件 5、Spring框架中的Bean的作用域 6、Spring框架中的Bean的线程安全 7、 Spring框架中的Bean生命周期 8、Spring框架如何解决循环依赖&#xff1f; 9、…

考研数学想考120,把李林880做到准确率80%以上够吗?

考研数学想考120&#xff0c;把880题做到正确率80%以上是不够的 因为最近几年的考研数学变化&#xff0c;很大&#xff0c;传统的背题型的备考方式已经没用了&#xff0c;而880题是这种模式的佼佼者&#xff0c;25版的880变动又很小&#xff0c;只加了40道比较综合的题目在每一…

前端 JavaScript 的 _ 语法是个什么鬼?

前言 我们有时候会看这样的前端代码&#xff1a; const doubled _.map(numbers, function(num) { return num * 2; });刚接触前端的童鞋可能会有点惊奇&#xff0c;不知道这个 _ 是什么语法&#xff0c;为什么这么神通广大&#xff1f; 其实 _ 是 Lodash 或 Underscore.js …

推荐浏览器爬虫插件:Instant Data Scraper 无需写一行代码

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

24暑假算法刷题 | Day30 | 贪心算法 IV | LeetCode 452. 用最少数量的箭引爆气球,435. 无重叠区间,763. 划分字母区间

目录 452. 用最少数量的箭引爆气球题目描述题解 435. 无重叠区间题目描述题解 763. 划分字母区间题目描述题解 452. 用最少数量的箭引爆气球 点此跳转题目链接 题目描述 有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points &#xff0c;其中…

传知代码-CENet及多模态情感计算实战(论文复现)

代码以及视频讲解 本文所涉及所有资源均在传知代码平台可获取 一、概述 本文对 “Cross-Modal Enhancement Network for Multimodal Sentiment Analysis” 论文进行讲解和手把手复现教学&#xff0c;解决当下热门的多模态情感计算问题&#xff0c;并展示在MOSI和MOSEI两个数…

拒绝内卷:利用4P营销理论打造汇报PPT

在当下的职场文化里&#xff0c;越来越激烈的“内卷”现象普遍存在。随着不得已的竞争压力、加班文化、以及技能和学历的通货膨胀&#xff0c;越来越多职场人不惜加大工作负荷和劳动投入。但这种过度的付出往往并未带来成比例的回报&#xff0c;有时还会因为过度工作而导致生产…

C程序设计——基本变量类型(指针1)

注释 我们先介绍一下程序设计语言中&#xff0c;很重要的一个部分——注释。注释通常用来说明源码的功能、作者、版权等。目前常见的C编译器&#xff0c;都支持两种注释&#xff0c;多行注释和单行注释。 多行注释 多行注释是 /* 和 */ 中间的内容&#xff0c;比如下面这样&…

1.微服务发展阶段

单体应用阶段 简介 系统业务量很小的时候我们把所有的代码都放在一个项目中&#xff0c;然后将这个项目部署在一台服务器上&#xff0c;整个项目所有的服务都由这台服务器去提供 优点 1.展现层、控制层、持久层全都在一个应用里面&#xff0c;调用方便、快速&#xff0c;单个请…

域名的常见解析记录类型有哪些,你了解多少?

域名的常见解析记录类型有哪些?域名解析记录用于存储有关域名及其关联 IP 地址的信息。一般&#xff0c;常见的记录有多种&#xff0c;每种类型都有其特定用途。在本文中&#xff0c;我们将探讨常见的几种域名解析记录类型&#xff0c;方便您了解。 A 记录&#xff1a;将域名映…

Python酷库之旅-第三方库Pandas(081)

目录 一、用法精讲 336、pandas.Series.str.rpartition方法 336-1、语法 336-2、参数 336-3、功能 336-4、返回值 336-5、说明 336-6、用法 336-6-1、数据准备 336-6-2、代码示例 336-6-3、结果输出 337、pandas.Series.str.slice方法 337-1、语法 337-2、参数 …