const fs = require('fs') const parser = require('@babel/parser') // 解析 JavaScript 代码 const traverse = require('@babel/traverse').default // 遍历 AST const generator = require('@babel/generator').default // 生成代码 const t = require('@babel/types') // 定义文件路径 const input_js = './encode.js' const output_js = './decode.js' // 读取文件内容并解析成 AST const js_code = fs.readFileSync(input_js, {encoding: 'utf-8'}) const ast = parser.parse(js_code) // 解析代码为 AST // ------ 得出来 3元表达式 // 只获取指纹数组的代码,全部获取还原后并不准确 // 查找所有 lA()[Sr(l2)](rs, U3, pb) 和 Zb()[G9(Yx)].apply(null, [cg, N9]) encode = {} const visitor_call = { ConditionalExpression(path) { js = path.toString() encode[js] = null; }, CallExpression(path) { // 检查是否在三元表达式内部 const isInsideTernary = path.findParent(p => p.isConditionalExpression() ); if (isInsideTernary) return; let {callee,} = path.node // let argumentsPathList = path.get('arguments') if (!t.isMemberExpression(callee)) return; // 匹配2种混淆表达式 let {object, property} = callee if (!t.isCallExpression(object) && !t.isMemberExpression(object)) return; // 处理 参数中有 三元表达式的(没必要) // argumentsPathList.forEach(argPath => { // argPath.traverse({ // ConditionalExpression(innerPath) { // js = innerPath.toString() // console.log('找到条件表达式完', js) // } // }) // }) // 更细节的处理 if (t.isCallExpression(object) && t.isIdentifier(object.callee) && object.arguments.length === 0) { js = path.toString() encode[js] = null; // 要设置值为 null 否则转 json字符串时会无值,因为值为 undefind 的json转不了 } if (t.isMemberExpression(object) && t.isIdentifier(property)) { // 跳过嵌套的成员表达式 只还原这种 Zb()[G9(Yx)].apply(null, [cg, N9]) if (!t.isCallExpression(object.object)) return; js = path.toString() encode[js] = null; } // if(!t.isCallExpression(object) || !t.isMemberExpression(object)) return; // // if(!) return; // encode.push({key: js}) }, Program: { exit() { // console.log(encode) const jsonData = JSON.stringify(encode); console.log(jsonData); // 输出 JSON 字符串 } } }; decode = { "zK()[GQ(fp)](d5, X0)": "Object", "RP(typeof RT()[N5(Sj)], 'undefined') ? RT()[N5(xQ)].call(null, EN, BX7, Z2, OR) : RT()[N5(JI)](pN, tH7, QG, CF)": "keys", "HR(typeof pQ()[vP(b5)], 'undefined') ? pQ()[vP(TN)].apply(null, [jK, jc, B0, YU]) : pQ()[vP(OR)](DA7, Pd, cW, EN)": "map" } const visitor2 = { CallExpression(path) { let {callee,} = path.node // let argumentsPathList = path.get('arguments') if (!t.isMemberExpression(callee)) return; // 匹配2种混淆表达式 let {object, property} = callee if (!t.isCallExpression(object) && !t.isMemberExpression(object)) return; // console.log(path.toString()) // 更细节的处理 if (t.isCallExpression(object) && t.isIdentifier(object.callee) && object.arguments.length === 0) { js = path.toString() if (decode[js] !== null) { value = decode[js] console.log(js, '=>', value) path.replaceWith(t.valueToNode(value)) } } if (t.isMemberExpression(object) && t.isIdentifier(property)) { // 跳过嵌套的成员表达式 只还原这种 Zb()[G9(Yx)].apply(null, [cg, N9]) if (!t.isCallExpression(object.object)) return; js = path.toString() // try { if (decode[js] !== null) { value = decode[js] console.log(js, '=>', value) path.replaceWith(t.valueToNode(value)) } // } catch (e) { // console.log(e) // } } }, ConditionalExpression(path) { js = path.toString() if (decode[js] !== null) { value = decode[js] console.log(js, '=>', value) path.replaceWith(t.valueToNode(value)) } } }; // traverse(ast, visitor_call) // 获取混淆的表达式 traverse(ast, visitor2) // 还原 // 使用 Babel 生成新的代码 let {code} = generator(ast) // 将生成的代码写入指定的文件 fs.writeFile(output_js, code, (err) => { })