/** * 最终变量重命名 - 处理剩余的简单模式 */ 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', plugins: [] }); console.log('AST 解析成功'); } catch (e) { console.error('AST 解析失败:', e.message); process.exit(1); } console.log('\n[2] 智能变量重命名...'); let renamedCount = 0; // 追踪每个作用域中已使用的名称 const usedNamesPerScope = new Map(); function getScopeUsedNames(scope) { if (!usedNamesPerScope.has(scope.uid)) { usedNamesPerScope.set(scope.uid, new Set()); } return usedNamesPerScope.get(scope.uid); } function isNameUsedInScope(scope, name) { // 检查 babel binding if (scope.hasBinding(name)) return true; // 检查本次重命名中已使用的名称 let s = scope; while (s) { if (getScopeUsedNames(s).has(name)) return true; s = s.parent; } return false; } // 通过使用上下文推断变量名 traverse(ast, { VariableDeclarator(path) { if (!t.isIdentifier(path.node.id)) return; const varName = path.node.id.name; // 只处理 var/v + 数字 格式 if (!/^(var|v)\d+$/.test(varName)) return; const init = path.node.init; let newName = null; // await this._isSeamlessInjected() -> isSeamlessInjected if (t.isAwaitExpression(init)) { const arg = init.argument; if (t.isCallExpression(arg) && t.isMemberExpression(arg.callee)) { const methodName = arg.callee.property.name || ''; if (methodName.startsWith('_is')) { newName = methodName.slice(1); // 移除 _ } else if (methodName.startsWith('_get')) { newName = methodName.slice(4).toLowerCase() + 'Result'; } else if (methodName.startsWith('_check')) { newName = methodName.slice(6).toLowerCase() + 'Result'; } else if (methodName.includes('Path')) { newName = 'pathResult'; } else if (methodName.includes('Status')) { newName = 'status'; } } } // this._context.globalState.get(...) -> savedValue if (t.isCallExpression(init)) { const callee = init.callee; if (t.isMemberExpression(callee)) { const methodName = callee.property.name || ''; if (methodName === 'get' && t.isMemberExpression(callee.object)) { const objProp = callee.object.property?.name || ''; if (objProp === 'globalState') { // 根据 get 的参数推断 if (init.arguments.length > 0 && t.isStringLiteral(init.arguments[0])) { const key = init.arguments[0].value; if (key.includes('key')) newName = 'savedKey'; else if (key.includes('expire')) newName = 'expireDate'; else if (key.includes('switch')) newName = 'switchData'; else newName = 'savedValue'; } } } else if (methodName === 'join') { newName = 'joinedPath'; } else if (methodName === 'dirname') { newName = 'dirPath'; } else if (methodName === 'basename') { newName = 'baseName'; } else if (methodName === 'readFileSync') { newName = 'fileContent'; } else if (methodName === 'existsSync') { newName = 'fileExists'; } else if (methodName === 'match') { newName = 'matchResult'; } else if (methodName === 'exec') { newName = 'execResult'; } else if (methodName === 'split') { newName = 'parts'; } else if (methodName === 'trim') { newName = 'trimmed'; } else if (methodName === 'replace') { newName = 'replaced'; } else if (methodName === 'indexOf' || methodName === 'findIndex') { newName = 'index'; } else if (methodName === 'find') { newName = 'found'; } else if (methodName === 'filter') { newName = 'filtered'; } else if (methodName === 'map') { newName = 'mapped'; } } } // 成员访问 if (t.isMemberExpression(init)) { const propName = init.property?.name || ''; if (propName === 'length') newName = 'len'; else if (propName === 'webview') newName = 'webview'; else if (propName === 'fsPath') newName = 'fsPath'; else if (propName === 'uri') newName = 'uri'; else if (propName === 'path') newName = 'filePath'; } // 二元表达式结果通常是布尔值 if (t.isBinaryExpression(init)) { const op = init.operator; if (['===', '!==', '==', '!=', '>', '<', '>=', '<='].includes(op)) { newName = 'isMatch'; } } // 逻辑表达式 if (t.isLogicalExpression(init)) { newName = 'condition'; } // 数组 if (t.isArrayExpression(init)) { newName = 'items'; } // 对象 if (t.isObjectExpression(init)) { // 检查属性来推断 const props = init.properties; if (props.length > 0) { const firstProp = props[0]; if (t.isObjectProperty(firstProp)) { const key = firstProp.key.name || firstProp.key.value || ''; if (key === 'type') newName = 'message'; else if (key === 'success') newName = 'response'; else if (key === 'path') newName = 'pathInfo'; else newName = 'config'; } } } // new RegExp if (t.isNewExpression(init) && t.isIdentifier(init.callee, { name: 'RegExp' })) { newName = 'regex'; } if (newName) { // 确保名称唯一 const scope = path.scope; let finalName = newName; let counter = 1; while (isNameUsedInScope(scope, finalName)) { finalName = newName + counter++; } // 记录使用的名称 getScopeUsedNames(scope).add(finalName); const binding = scope.getBinding(varName); if (binding) { path.node.id.name = finalName; binding.referencePaths.forEach(ref => { ref.node.name = finalName; }); renamedCount++; } } } }); console.log(`重命名了 ${renamedCount} 个变量`); console.log('\n[3] 处理回调参数...'); let callbackCount = 0; traverse(ast, { ArrowFunctionExpression(path) { const params = path.node.params; if (params.length === 1 && t.isIdentifier(params[0])) { const paramName = params[0].name; if (/^arg\d+$/.test(paramName)) { // 根据父级上下文推断 const parent = path.parent; let newName = null; if (t.isCallExpression(parent)) { const callee = parent.callee; if (t.isMemberExpression(callee)) { const methodName = callee.property.name || ''; if (methodName === 'forEach') newName = 'item'; else if (methodName === 'map') newName = 'item'; else if (methodName === 'filter') newName = 'item'; else if (methodName === 'find') newName = 'item'; else if (methodName === 'some') newName = 'item'; else if (methodName === 'every') newName = 'item'; else if (methodName === 'then') newName = 'result'; else if (methodName === 'catch') newName = 'error'; else if (methodName.includes('Change')) newName = 'status'; else if (methodName.includes('Message')) newName = 'msg'; } } if (newName) { const binding = path.scope.getBinding(paramName); if (binding) { params[0].name = newName; binding.referencePaths.forEach(ref => { ref.node.name = newName; }); callbackCount++; } } } } } }); console.log(`处理了 ${callbackCount} 个回调参数`); console.log('\n[4] 生成代码...'); const output = generate(ast, { comments: false, compact: false, concise: false }, code); let finalCode = output.code; finalCode = finalCode.replace(/\["([a-zA-Z_$][a-zA-Z0-9_$]*)"\]/g, '.$1'); console.log('\n[5] 保存文件...'); fs.writeFileSync(outputPath, finalCode); console.log(`保存到: ${outputPath}`); console.log(`新文件大小: ${(finalCode.length / 1024).toFixed(2)} KB`); // 统计 const remaining = (finalCode.match(/\b(var|arg|v)\d+\b/g) || []); const unique = [...new Set(remaining)]; console.log(`\n剩余通用变量名: ${unique.length} 个唯一名称`); console.log('\n✅ 完成!');