Files
cursornew2026/final_rename5.js

324 lines
13 KiB
JavaScript

/**
* 第五轮 - 全面清理剩余通用变量名
*/
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✅ 完成!');