提示!本文章仅供学习交流,严禁用于任何商业和非法用途,未经许可禁止转载,禁止任何修改后二次传播,如有侵权,可联系本文作者删除!
目标网站
aHR0cHM6Ly9jcmVkaXQuaGVmZWkuZ292LmNuL2NyZWRpdC13ZWJzaXRlL3B1YmxpY2l0eS94eWNuL3h5Y24tbGlzdC5kbz9uYXZJZD1DRTlGRkY1MTFENkUyQzRGRTA1Mzg4QkQwNDBBREVEMyZjb2x1bW5JZD1CNkE5NzlEQ0I2QTg0OTg0RTA1MzEyMDAxRTBBQzI3NiZyZWxlYXNlSWQ9QjZBOTc5RENCNkE4NDk4NEUwNTMxMjAwMUUwQUMyNzY=
抓包分析
破解的流程 请求分成三个请求:
1、不携带任何cookie的请求521, 拿到详情JS代码
2、携带第一个请求的set-cookie 和js 自执行的cookie 请求521
3、根据第二个请求的js 设置的cookie 发请求 拿到正常页面
第一个请求返回的内容 可以直接执行 拿到结果, 只需要分析第二个请求的js 内容
解混淆
const parser = require("@babel/parser");
const traverse = require("@babel/traverse").default;
const t = require("@babel/types");
const generator = require("@babel/generator").default;
const fs = require("fs");
// js混淆代码
process.argv.length > 2 ? encode_file = process.argv[2] : encode_file = "./input/jsl.js";
process.argv.length > 3 ? decode_file = process.argv[3] : decode_file = "./output/jsl_decode.js";
// #######################################
// AST解析函数
// #######################################
// 获取全局函数
function getGlobalFunc(){
let program_body= ast.program.body;
for (var i=0; i<3; i++){
globalCode += generator(program_body[i]).code + "\n";
}
return globalCode
}
// AST还原流程
// #######################################
// 读取需要解码的js文件, 注意文件编码为utf-8格式
let jscode = fs.readFileSync(encode_file, {encoding: "utf-8"});
// 将js代码修转成AST语法树
let ast = parser.parse(jscode);
console.time("处理完毕,耗时");
var globalCode = '';
// 获取自执行方法
globalCode = getGlobalFunc();
eval(globalCode);
const deal_CallExpression = {
CallExpression(path){
let {callee, arguments} = path.node;
if (callee === undefined || callee.name === undefined)
return;
if (callee.name != '_0xfecf' || arguments.length !=2 )
return;
let value = _0xfecf(arguments[0].value, arguments[1].value);
// 创建节点并替换结果
let string_node = t.stringLiteral(value);
path.replaceWith(string_node)
}
};
// 遍历语法树节点,调用修改函数
traverse(ast, deal_CallExpression);
// 合并字符串
const BinaryExpressionFix = {
BinaryExpression: {
exit: function (path) {
try {
eval(path.toString()).toString();
path.replaceWith(t.stringLiteral(eval(path.toString()).toString()));
} catch (e) {
}
}
}
};
traverse(ast, BinaryExpressionFix);
// 删除无用方法
nodesToRemove = [];
const remove_path = {
enter(path) {
// 只在顶层语句中收集前三个节点
if (path.parentPath && path.parentPath.isProgram() && nodesToRemove.length < 3) {
nodesToRemove.push(path);
}
}
};
traverse(ast, remove_path);
nodesToRemove.forEach(path => path.remove());
console.timeEnd("处理完毕,耗时");
// 将ast转成js代码,{jsescOption: {"minimal": true}} unicode -> 中文
let {code} = generator(ast, opts = {jsescOption: {"minimal": true}});
// 将js代码保存到文件
fs.writeFile(decode_file, code, (err) => {
});
console.log("end");
解混淆后的代码直接执行 调试,把缺少的环境补上
如下:
window = global;
window.navigator = {};
navigator.userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36";
document = {};
直接执行得到 结果, 和浏览器对比发现是一致的
通过分析多个JS 会发现 整体js 根据参数 执行 MD5, sha1,sha256 加密运算,结果和ct 值作比对
结语
可以通过补环境,提取参数的方式通过执行js拿到cookie 结果, 也可以通过Python改写的方法去完成
ps: 觉得不错点个赞 。。。