/** * 第五轮 - 全面清理剩余通用变量名 */ 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.js'; const outputPath = 'D:/temp/破解/cursorpro-0.4.5/deobfuscated_full/extension/out/webview/provider.js'; console.log('╔════════════════════════════════════════════════════╗'); console.log('║ 第五轮全面清理 ║'); 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' }); } catch (e) { console.error('AST 解析失败:', e.message); process.exit(1); } // 名称管理 const scopeNames = new Map(); function getUniqueName(scope, base) { const key = scope.uid; if (!scopeNames.has(key)) scopeNames.set(key, new Set()); const used = scopeNames.get(key); let name = base, i = 1; while (used.has(name) || scope.hasBinding(name)) name = base + i++; used.add(name); return name; } console.log('\n[2] 收集所有通用变量的上下文...'); // 分析每个变量的完整上下文 const varAnalysis = new Map(); traverse(ast, { VariableDeclarator(path) { if (!t.isIdentifier(path.node.id)) return; const name = path.node.id.name; if (!/^(var|arg|v)\d+$/.test(name)) return; const analysis = { name, scope: path.scope, path, init: path.node.init, usages: [], suggestedName: null }; // 收集使用点 const binding = path.scope.getBinding(name); if (binding) { analysis.references = binding.referencePaths; } varAnalysis.set(path, analysis); } }); console.log(`找到 ${varAnalysis.size} 个待处理变量`); console.log('\n[3] 分析初始化表达式...'); for (const [path, analysis] of varAnalysis) { const init = analysis.init; if (!init) continue; // 1. 成员访问 xxx.yyy if (t.isMemberExpression(init)) { const prop = init.property?.name; if (prop === 'platform') analysis.suggestedName = 'platform'; else if (prop === 'stdout') analysis.suggestedName = 'stdout'; else if (prop === 'stderr') analysis.suggestedName = 'stderr'; else if (prop === 'length') analysis.suggestedName = 'len'; else if (prop === 'code') analysis.suggestedName = 'code'; else if (prop === 'message') analysis.suggestedName = 'msg'; else if (prop === 'name') analysis.suggestedName = 'name'; else if (prop === 'value') analysis.suggestedName = 'value'; else if (prop === 'type') analysis.suggestedName = 'type'; else if (prop === 'path') analysis.suggestedName = 'pathStr'; else if (prop === 'data') analysis.suggestedName = 'data'; else if (prop === 'env') analysis.suggestedName = 'env'; else if (prop === 'webview') analysis.suggestedName = 'webview'; } // 2. 调用表达式 if (t.isCallExpression(init)) { const callee = init.callee; if (t.isMemberExpression(callee)) { const obj = callee.object; const method = callee.property?.name; // vscode.xxx if (t.isIdentifier(obj, { name: 'vscode' })) { if (method === 'workspace') analysis.suggestedName = 'workspace'; else if (method === 'window') analysis.suggestedName = 'window'; } // workspace.getConfiguration if (method === 'getConfiguration') analysis.suggestedName = 'config'; else if (method === 'get') analysis.suggestedName = 'configValue'; else if (method === 'readFileSync') analysis.suggestedName = 'fileContent'; else if (method === 'readdirSync') analysis.suggestedName = 'dirItems'; else if (method === 'existsSync') analysis.suggestedName = 'exists'; else if (method === 'statSync') analysis.suggestedName = 'stat'; else if (method === 'join') analysis.suggestedName = 'joinedPath'; else if (method === 'dirname') analysis.suggestedName = 'dirPath'; else if (method === 'basename') analysis.suggestedName = 'baseName'; else if (method === 'extname') analysis.suggestedName = 'ext'; else if (method === 'resolve') analysis.suggestedName = 'resolvedPath'; else if (method === 'split') analysis.suggestedName = 'parts'; else if (method === 'trim') analysis.suggestedName = 'trimmed'; else if (method === 'match') analysis.suggestedName = 'match'; else if (method === 'replace') analysis.suggestedName = 'replaced'; else if (method === 'toLowerCase') analysis.suggestedName = 'lower'; else if (method === 'toUpperCase') analysis.suggestedName = 'upper'; else if (method === 'slice') analysis.suggestedName = 'sliced'; else if (method === 'substring') analysis.suggestedName = 'substr'; else if (method === 'indexOf') analysis.suggestedName = 'idx'; else if (method === 'find') analysis.suggestedName = 'found'; else if (method === 'filter') analysis.suggestedName = 'filtered'; else if (method === 'map') analysis.suggestedName = 'mapped'; else if (method === 'forEach') continue; // void else if (method === 'push') continue; else if (method === 'pop') analysis.suggestedName = 'popped'; else if (method === 'shift') analysis.suggestedName = 'shifted'; else if (method === 'exec') analysis.suggestedName = 'execMatch'; else if (method === 'test') analysis.suggestedName = 'isMatch'; else if (method === 'normalize') analysis.suggestedName = 'normalized'; else if (method === 'toString') analysis.suggestedName = 'str'; else if (method === 'parse') analysis.suggestedName = 'parsed'; else if (method === 'stringify') analysis.suggestedName = 'jsonStr'; else if (method === 'keys') analysis.suggestedName = 'keys'; else if (method === 'values') analysis.suggestedName = 'values'; else if (method === 'entries') analysis.suggestedName = 'entries'; } // 独立函数调用 if (t.isIdentifier(callee)) { const fn = callee.name; if (fn === 'require') analysis.suggestedName = 'module'; else if (fn === 'parseInt') analysis.suggestedName = 'num'; else if (fn === 'parseFloat') analysis.suggestedName = 'num'; else if (fn === 'String') analysis.suggestedName = 'str'; else if (fn === 'Number') analysis.suggestedName = 'num'; else if (fn === 'Boolean') analysis.suggestedName = 'bool'; else if (fn === 'Array') analysis.suggestedName = 'arr'; else if (fn === 'Object') analysis.suggestedName = 'obj'; } } // 3. await 表达式 if (t.isAwaitExpression(init)) { const arg = init.argument; if (t.isCallExpression(arg) && t.isMemberExpression(arg.callee)) { const method = arg.callee.property?.name; if (method === 'exec' || method === 'execAsync') analysis.suggestedName = 'execResult'; else if (method?.startsWith('get')) { const rest = method.slice(3); analysis.suggestedName = rest.charAt(0).toLowerCase() + rest.slice(1); } else if (method?.startsWith('_get')) { const rest = method.slice(4); analysis.suggestedName = rest.charAt(0).toLowerCase() + rest.slice(1); } else if (method?.startsWith('read')) analysis.suggestedName = 'content'; else if (method?.startsWith('fetch')) analysis.suggestedName = 'response'; } } // 4. new 表达式 if (t.isNewExpression(init)) { const callee = init.callee; if (t.isIdentifier(callee)) { const cls = callee.name; if (cls === 'RegExp') analysis.suggestedName = 'regex'; else if (cls === 'Date') analysis.suggestedName = 'date'; else if (cls === 'Map') analysis.suggestedName = 'map'; else if (cls === 'Set') analysis.suggestedName = 'set'; else if (cls === 'Promise') analysis.suggestedName = 'promise'; else if (cls === 'Error') analysis.suggestedName = 'error'; else if (cls === 'URL') analysis.suggestedName = 'url'; } } // 5. 字面量 if (t.isStringLiteral(init)) analysis.suggestedName = 'str'; if (t.isNumericLiteral(init)) analysis.suggestedName = 'num'; if (t.isBooleanLiteral(init)) analysis.suggestedName = init.value ? 'isTrue' : 'isFalse'; if (t.isNullLiteral(init)) analysis.suggestedName = 'value'; if (t.isArrayExpression(init)) analysis.suggestedName = 'arr'; if (t.isObjectExpression(init)) analysis.suggestedName = 'obj'; if (t.isRegExpLiteral(init)) analysis.suggestedName = 'regex'; // 6. 二元/逻辑表达式 if (t.isBinaryExpression(init)) { const op = init.operator; if (['===', '!==', '==', '!=', '>', '<', '>=', '<='].includes(op)) { analysis.suggestedName = 'cond'; } else if (['+', '-', '*', '/', '%'].includes(op)) { analysis.suggestedName = 'result'; } } if (t.isLogicalExpression(init)) analysis.suggestedName = 'cond'; if (t.isConditionalExpression(init)) analysis.suggestedName = 'value'; if (t.isUnaryExpression(init, { operator: '!' })) analysis.suggestedName = 'not'; } // 统计推断结果 let suggested = 0; for (const [, analysis] of varAnalysis) { if (analysis.suggestedName) suggested++; } console.log(`推断了 ${suggested} / ${varAnalysis.size} 个变量名`); console.log('\n[4] 应用重命名...'); let renamed = 0; for (const [path, analysis] of varAnalysis) { if (!analysis.suggestedName) continue; const binding = analysis.scope.getBinding(analysis.name); if (!binding) continue; const newName = getUniqueName(analysis.scope, analysis.suggestedName); path.node.id.name = newName; binding.referencePaths.forEach(ref => { ref.node.name = newName; }); renamed++; } console.log(`重命名了 ${renamed} 个变量`); // 处理函数参数 console.log('\n[5] 处理函数/回调参数...'); let paramRenamed = 0; traverse(ast, { 'ArrowFunctionExpression|FunctionExpression'(path) { const params = path.node.params; // 获取父级上下文 const parent = path.parent; let contextHint = null; if (t.isCallExpression(parent) && t.isMemberExpression(parent.callee)) { const method = parent.callee.property?.name; if (['forEach', 'map', 'filter', 'find', 'some', 'every', 'reduce'].includes(method)) { contextHint = 'iterator'; } else if (method === 'then') { contextHint = 'then'; } else if (method === 'catch') { contextHint = 'catch'; } else if (method?.includes('Message')) { contextHint = 'message'; } else if (method?.includes('Change')) { contextHint = 'change'; } } params.forEach((param, idx) => { if (!t.isIdentifier(param)) return; if (!/^arg\d+$/.test(param.name)) return; let newName = null; if (contextHint === 'iterator') { newName = idx === 0 ? 'item' : idx === 1 ? 'index' : 'arr'; } else if (contextHint === 'then') { newName = 'res'; } else if (contextHint === 'catch') { newName = 'err'; } else if (contextHint === 'message') { newName = 'msg'; } else if (contextHint === 'change') { newName = 'change'; } else { newName = 'param' + idx; } if (newName) { const binding = path.scope.getBinding(param.name); if (binding) { const finalName = getUniqueName(path.scope, newName); param.name = finalName; binding.referencePaths.forEach(ref => { ref.node.name = finalName; }); paramRenamed++; } } }); } }); console.log(`重命名了 ${paramRenamed} 个参数`); console.log('\n[6] 生成代码...'); const output = generate(ast, { comments: false, compact: false }, code); let finalCode = output.code; finalCode = finalCode.replace(/\["([a-zA-Z_$][a-zA-Z0-9_$]*)"\]/g, '.$1'); console.log('\n[7] 保存文件...'); fs.writeFileSync(outputPath, finalCode); console.log(`新文件大小: ${(finalCode.length / 1024).toFixed(2)} KB`); const remaining = [...new Set((finalCode.match(/\b(var|arg|v)\d+\b/g) || []))]; console.log(`剩余通用变量名: ${remaining.length} 个`); console.log('\n✅ 完成!');