郑重声明
此处超星指代的是本人独立开发的自主单机游戏-》超级星星V0.1版
并非通俗意义的超星!请勿进行过度联想
本文全程为自攻自破
如有雷同纯属巧合
预览
开始
通过观察代码以及动态运行可以发现_0xdd65b4是解密函数
点进去直接下个断
然后字符串化一下拷贝出去字符数组
在nodejs里写出来解密函数,并且parse一下拷贝的字符串
观察代码发现是一个CallExpression节点
然后我们直接写一下代码
traverse(ast, {
CallExpression(path) {
if (path.node.callee.name === "_0xdd65b4") {
let loc = path.node.arguments[0].value;
let str_node = types.stringLiteral(crp_str(loc));
path.replaceInline(str_node);
}
},
});
可以发现已经解开一大堆字符串了
然后搜索一下,发现还有很多加密的函数调用
原来是在函数头上做了一下赋值,然后由函数的引用来做加密
我们丢到Ast看一下,可以发现是一个VariableDeclarator对象
id是赋值的名字,init是加密的字符串,那我们继续写VariableDeclarator的AST解析吧
但是根据测试发现一个比较头疼的问题
他对函数进行了多次赋值,所以我们必须写一个递归遍历的东西
直接上代码
function find_and_fuck_crp(path, func_name) {
let bind = path.scope.getBinding(func_name);
let refer_list = bind.referencePaths;
refer_list.forEach((item) => {
let parent_path = item.parentPath;
if (parent_path.node.type === "CallExpression") {
let loc = parent_path.node.arguments[0].value;
let str_node = types.stringLiteral(crp_str(loc));
parent_path.replaceInline(str_node);
} else {
if (parent_path.node.type === "VariableDeclarator") {
find_and_fuck_crp(parent_path, parent_path.node.id.name);
}
}
});
path.remove()
}
traverse(ast, {
VariableDeclarator(path) {
let func_name = path.node.id.name;
let init_name = path.node.init?.name;
if (init_name === "_0xdd65b4") {
find_and_fuck_crp(path, func_name);
}
},
});
经过递归遍历我们已经具备了一定的可读性了
然后发现还有一个加密的函数引用a0_0x1f3a,直接还按刚才的方法
处理之后删除加密的函数
再看一下,可以发现已经有了初步的样子
但是部分字符串里还有混淆
配置一下generator函数
let code = generator(ast, {
minified: true,
jsescOption: { minimal: true },
}).code;
到这里已经具备基本的调试条件了
剩下的大家也可以根据这个思路进行微妙
结语
撒花~