/** * 简化 switch 控制流平坦化 * 将 while(true) { switch(arr[i++]) { case '0': ... } } 转换为顺序执行 */ const fs = require('fs'); const babel = require('@babel/core'); const traverse = require('@babel/traverse').default; const generate = require('@babel/generator').default; const t = require('@babel/types'); const inputPath = 'D:/temp/破解/cursorpro-0.4.5/deobfuscated_full/extension/out/webview/provider_simplified.js'; const outputPath = 'D:/temp/破解/cursorpro-0.4.5/deobfuscated_full/extension/out/webview/provider_final.js'; console.log('╔════════════════════════════════════════════════════╗'); console.log('║ Switch 控制流还原工具 ║'); console.log('╚════════════════════════════════════════════════════╝'); const code = fs.readFileSync(inputPath, 'utf8'); console.log(`读取文件: ${(code.length / 1024).toFixed(2)} KB`); console.log('\n[1] 解析 AST...'); let ast; try { ast = babel.parseSync(code, { sourceType: 'script', plugins: [] }); console.log('AST 解析成功'); } catch (e) { console.error('AST 解析失败:', e.message); process.exit(1); } console.log('\n[2] 查找并还原 switch 控制流...'); let restoredCount = 0; // 查找并收集变量定义 function findVariableValue(path, varName) { let value = null; // 在当前作用域向上查找 const binding = path.scope.getBinding(varName); if (binding && binding.path.isVariableDeclarator()) { const init = binding.path.node.init; if (t.isCallExpression(init) && t.isMemberExpression(init.callee) && t.isStringLiteral(init.callee.object) && t.isIdentifier(init.callee.property, { name: 'split' })) { // "1|4|0|3|2".split('|') value = init.callee.object.value.split('|'); } } return value; } traverse(ast, { WhileStatement(path) { // 检查是否是 while(true) 或 while(1) const test = path.node.test; if (!t.isBooleanLiteral(test, { value: true }) && !t.isNumericLiteral(test, { value: 1 })) { return; } const body = path.node.body; if (!t.isBlockStatement(body)) return; // 查找 switch 语句 const switchStmt = body.body.find(stmt => t.isSwitchStatement(stmt)); if (!switchStmt) return; // 检查 discriminant 是否是 arr[i++] 形式 const disc = switchStmt.discriminant; if (!t.isMemberExpression(disc)) return; if (!t.isUpdateExpression(disc.property) || disc.property.operator !== '++') return; const arrName = disc.object.name; const indexName = disc.property.argument.name; // 获取顺序数组 const order = findVariableValue(path, arrName); if (!order) return; // 收集 case 语句 const cases = new Map(); for (const caseStmt of switchStmt.cases) { if (!caseStmt.test) continue; // default case let caseValue; if (t.isStringLiteral(caseStmt.test)) { caseValue = caseStmt.test.value; } else if (t.isNumericLiteral(caseStmt.test)) { caseValue = String(caseStmt.test.value); } else { continue; } // 过滤掉 continue 和 break const consequent = caseStmt.consequent.filter(stmt => !t.isContinueStatement(stmt) && !t.isBreakStatement(stmt) ); cases.set(caseValue, consequent); } // 按顺序组装语句 const newStatements = []; for (const key of order) { const stmts = cases.get(key); if (stmts) { newStatements.push(...stmts); } } if (newStatements.length > 0) { // 查找并移除相关变量声明 const parentBody = path.parentPath; if (t.isBlockStatement(parentBody.node) || t.isProgram(parentBody.node)) { // 替换 while 语句 path.replaceWithMultiple(newStatements); restoredCount++; } } } }); console.log(`还原了 ${restoredCount} 处 switch 控制流`); console.log('\n[3] 清理冗余变量...'); // 清理只用于 switch 控制流的变量 let cleanedVars = 0; traverse(ast, { VariableDeclarator(path) { if (!t.isIdentifier(path.node.id)) return; const name = path.node.id.name; const init = path.node.init; // 检查是否是 "x|x|x".split('|') 形式 if (t.isCallExpression(init) && t.isMemberExpression(init.callee) && t.isStringLiteral(init.callee.object) && /^\d+(\|\d+)+$/.test(init.callee.object.value)) { // 检查是否还在使用 const binding = path.scope.getBinding(name); if (binding && binding.references === 0) { path.remove(); cleanedVars++; } } // 检查是否是用于索引的变量 (初始化为 0) if (t.isNumericLiteral(init, { value: 0 })) { const binding = path.scope.getBinding(name); if (binding && binding.references === 0) { path.remove(); cleanedVars++; } } } }); console.log(`清理了 ${cleanedVars} 个冗余变量`); console.log('\n[4] 生成代码...'); const output = generate(ast, { comments: false, compact: false, concise: false }, code); console.log('\n[5] 保存文件...'); fs.writeFileSync(outputPath, output.code); console.log(`保存到: ${outputPath}`); console.log(`新文件大小: ${(output.code.length / 1024).toFixed(2)} KB`); console.log('\n✅ 完成!');