245 lines
9.5 KiB
JavaScript
245 lines
9.5 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',
|
|
plugins: []
|
|
});
|
|
console.log('AST 解析成功');
|
|
} catch (e) {
|
|
console.error('AST 解析失败:', e.message);
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log('\n[2] 分析变量用途并重命名...');
|
|
|
|
// 常见模式的语义化命名
|
|
const semanticPatterns = {
|
|
// 函数参数
|
|
'extensionUri': ['_extensionUri', 'extensionUri'],
|
|
'context': ['_context', 'context', 'globalState'],
|
|
'webview': ['webview', 'Webview'],
|
|
'message': ['message', 'Message', 'postMessage'],
|
|
'key': ['key', 'Key', 'verifyKey'],
|
|
'path': ['path', 'Path', 'getPath'],
|
|
'result': ['result', 'Result', 'success'],
|
|
'response': ['response', 'Response'],
|
|
'error': ['error', 'Error', 'catch'],
|
|
'data': ['data', 'Data'],
|
|
'config': ['config', 'Config', 'configuration'],
|
|
'options': ['options', 'Options'],
|
|
'callback': ['callback', 'Callback'],
|
|
'handler': ['handler', 'Handler'],
|
|
'listener': ['listener', 'Listener'],
|
|
'event': ['event', 'Event'],
|
|
'token': ['token', 'Token'],
|
|
'email': ['email', 'Email'],
|
|
'status': ['status', 'Status'],
|
|
};
|
|
|
|
// 收集需要重命名的变量
|
|
const renameMap = new Map();
|
|
let renamedCount = 0;
|
|
|
|
// 分析每个作用域中的变量
|
|
traverse(ast, {
|
|
// 处理函数参数
|
|
Function(path) {
|
|
const params = path.node.params;
|
|
|
|
// 对于有意义的函数,分析参数
|
|
if (path.node.id && path.node.id.name) {
|
|
const funcName = path.node.id.name;
|
|
|
|
// 根据函数名推断参数名
|
|
params.forEach((param, index) => {
|
|
if (t.isIdentifier(param) && /^arg\d+$/.test(param.name)) {
|
|
let newName = null;
|
|
|
|
// 常见模式
|
|
if (funcName.includes('activate') || funcName.includes('Activate')) {
|
|
if (index === 0) newName = 'key';
|
|
} else if (funcName.includes('message') || funcName.includes('Message')) {
|
|
if (index === 0) newName = 'message';
|
|
} else if (funcName.includes('toggle') || funcName.includes('Toggle')) {
|
|
if (index === 0) newName = 'enabled';
|
|
}
|
|
|
|
if (newName) {
|
|
const binding = path.scope.getBinding(param.name);
|
|
if (binding) {
|
|
binding.path.node.name = newName;
|
|
binding.referencePaths.forEach(ref => {
|
|
ref.node.name = newName;
|
|
});
|
|
renamedCount++;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
// 处理类方法
|
|
ClassMethod(path) {
|
|
const methodName = path.node.key.name || '';
|
|
const params = path.node.params;
|
|
|
|
params.forEach((param, index) => {
|
|
if (t.isIdentifier(param) && /^arg\d+$/.test(param.name)) {
|
|
let newName = null;
|
|
|
|
// 根据方法名推断参数名
|
|
if (methodName === 'constructor') {
|
|
if (index === 0) newName = 'extensionUri';
|
|
else if (index === 1) newName = 'context';
|
|
} else if (methodName === 'resolveWebviewView') {
|
|
if (index === 0) newName = 'webviewView';
|
|
else if (index === 1) newName = 'context';
|
|
else if (index === 2) newName = 'token';
|
|
} else if (methodName.includes('Activate')) {
|
|
if (index === 0) newName = 'key';
|
|
} else if (methodName.includes('Message')) {
|
|
if (index === 0) newName = 'message';
|
|
} else if (methodName.includes('Toggle')) {
|
|
if (index === 0) newName = 'enabled';
|
|
else if (index === 1) newName = 'silent';
|
|
} else if (methodName.includes('Write')) {
|
|
if (index === 0) newName = 'content';
|
|
} else if (methodName.includes('Path')) {
|
|
if (index === 0) newName = 'filePath';
|
|
} else if (methodName.includes('Account')) {
|
|
if (index === 0) newName = 'accountData';
|
|
} else if (methodName.includes('Usage')) {
|
|
if (index === 0) newName = 'checkLimit';
|
|
} else if (methodName.includes('Inject') || methodName.includes('Restore')) {
|
|
// 无参数或特定参数
|
|
}
|
|
|
|
if (newName) {
|
|
const binding = path.scope.getBinding(param.name);
|
|
if (binding) {
|
|
binding.path.node.name = newName;
|
|
binding.referencePaths.forEach(ref => {
|
|
ref.node.name = newName;
|
|
});
|
|
renamedCount++;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
// 处理变量声明
|
|
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;
|
|
|
|
// 根据初始化值推断
|
|
if (t.isAwaitExpression(init) && t.isCallExpression(init.argument)) {
|
|
const call = init.argument;
|
|
if (t.isMemberExpression(call.callee)) {
|
|
const methodName = call.callee.property.name || '';
|
|
|
|
if (methodName.includes('verify')) newName = 'verifyResult';
|
|
else if (methodName.includes('switch')) newName = 'switchResult';
|
|
else if (methodName.includes('get')) newName = 'result';
|
|
else if (methodName.includes('read')) newName = 'content';
|
|
else if (methodName.includes('exec')) newName = 'execResult';
|
|
}
|
|
} else if (t.isCallExpression(init)) {
|
|
const call = init;
|
|
if (t.isMemberExpression(call.callee)) {
|
|
const objName = call.callee.object.name || '';
|
|
const methodName = call.callee.property.name || '';
|
|
|
|
if (methodName === 'get') newName = 'value';
|
|
else if (methodName === 'join') newName = 'fullPath';
|
|
else if (methodName === 'readFileSync') newName = 'fileContent';
|
|
else if (methodName === 'existsSync') newName = 'exists';
|
|
else if (methodName === 'getOwnPropertyDescriptor') newName = 'descriptor';
|
|
else if (methodName === 'getOwnPropertyNames') newName = 'propNames';
|
|
}
|
|
} else if (t.isObjectExpression(init)) {
|
|
// 对象字面量
|
|
newName = 'options';
|
|
} else if (t.isArrayExpression(init)) {
|
|
newName = 'items';
|
|
} else if (t.isMemberExpression(init)) {
|
|
const propName = init.property.name || '';
|
|
if (propName === 'length') newName = 'len';
|
|
else if (propName === 'globalState') newName = 'state';
|
|
}
|
|
|
|
if (newName) {
|
|
// 确保名称唯一
|
|
const scope = path.scope;
|
|
let finalName = newName;
|
|
let counter = 1;
|
|
while (scope.hasBinding(finalName)) {
|
|
finalName = newName + counter++;
|
|
}
|
|
|
|
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] 生成代码...');
|
|
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[4] 保存文件...');
|
|
fs.writeFileSync(outputPath, finalCode);
|
|
console.log(`保存到: ${outputPath}`);
|
|
console.log(`新文件大小: ${(finalCode.length / 1024).toFixed(2)} KB`);
|
|
|
|
// 统计剩余的通用变量名
|
|
const remainingGeneric = (finalCode.match(/\b(var|arg|v)\d+\b/g) || []);
|
|
const uniqueGeneric = [...new Set(remainingGeneric)];
|
|
console.log(`\n剩余通用变量名: ${uniqueGeneric.length} 个唯一名称`);
|
|
|
|
console.log('\n✅ 完成!');
|