备份: 完整开发状态(含反混淆脚本和临时文件)
This commit is contained in:
281
final_rename.js
Normal file
281
final_rename.js
Normal file
@@ -0,0 +1,281 @@
|
||||
/**
|
||||
* 最终变量重命名 - 处理剩余的简单模式
|
||||
*/
|
||||
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✅ 完成!');
|
||||
Reference in New Issue
Block a user