备份: 完整开发状态(含反混淆脚本和临时文件)
This commit is contained in:
231
final_rename4.js
Normal file
231
final_rename4.js
Normal file
@@ -0,0 +1,231 @@
|
||||
/**
|
||||
* 第四轮 - 基于使用点的精确重命名
|
||||
*/
|
||||
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' });
|
||||
console.log('AST 解析成功');
|
||||
} catch (e) {
|
||||
console.error('AST 解析失败:', e.message);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const usedNames = new Map();
|
||||
|
||||
function getUniqueName(scope, baseName) {
|
||||
const key = scope.uid;
|
||||
if (!usedNames.has(key)) usedNames.set(key, new Set());
|
||||
const used = usedNames.get(key);
|
||||
|
||||
// 也检查 scope bindings
|
||||
let name = baseName;
|
||||
let counter = 1;
|
||||
while (used.has(name) || scope.hasBinding(name)) {
|
||||
name = baseName + counter++;
|
||||
}
|
||||
used.add(name);
|
||||
return name;
|
||||
}
|
||||
|
||||
console.log('\n[2] 分析对象属性赋值...');
|
||||
let renamedCount = 0;
|
||||
|
||||
// 收集变量被赋值到哪些属性
|
||||
const varToProps = new Map();
|
||||
|
||||
traverse(ast, {
|
||||
ObjectProperty(path) {
|
||||
const key = path.node.key;
|
||||
const value = path.node.value;
|
||||
|
||||
// { 'prop': varXXX }
|
||||
if (t.isIdentifier(value) && /^(var|v)\d+$/.test(value.name)) {
|
||||
let propName;
|
||||
if (t.isStringLiteral(key)) propName = key.value;
|
||||
else if (t.isIdentifier(key)) propName = key.name;
|
||||
|
||||
if (propName) {
|
||||
if (!varToProps.has(value.name)) {
|
||||
varToProps.set(value.name, new Set());
|
||||
}
|
||||
varToProps.get(value.name).add(propName);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 属性名到变量名的映射
|
||||
const propToVarName = {
|
||||
'is_injected': 'isInjected',
|
||||
'workbench_path': 'workbenchPath',
|
||||
'cursor_path': 'cursorPath',
|
||||
'machine_id': 'machineId',
|
||||
'email': 'email',
|
||||
'token': 'token',
|
||||
'success': 'success',
|
||||
'error': 'errorMsg',
|
||||
'message': 'message',
|
||||
'data': 'data',
|
||||
'result': 'result',
|
||||
'status': 'status',
|
||||
'enabled': 'enabled',
|
||||
'online': 'isOnline',
|
||||
'running': 'isRunning',
|
||||
'installed': 'isInstalled',
|
||||
'injected': 'isInjected',
|
||||
'can_switch': 'canSwitch',
|
||||
'switch_remaining': 'switchRemaining',
|
||||
'expire_date': 'expireDate',
|
||||
'version': 'version',
|
||||
'path': 'filePath',
|
||||
'content': 'content',
|
||||
'type': 'msgType',
|
||||
};
|
||||
|
||||
// 推断变量名
|
||||
const inferredNames = new Map();
|
||||
for (const [varName, props] of varToProps) {
|
||||
for (const prop of props) {
|
||||
if (propToVarName[prop]) {
|
||||
inferredNames.set(varName, propToVarName[prop]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`从属性推断了 ${inferredNames.size} 个变量名`);
|
||||
|
||||
// 应用推断
|
||||
traverse(ast, {
|
||||
VariableDeclarator(path) {
|
||||
if (!t.isIdentifier(path.node.id)) return;
|
||||
const varName = path.node.id.name;
|
||||
|
||||
if (!inferredNames.has(varName)) return;
|
||||
|
||||
const binding = path.scope.getBinding(varName);
|
||||
if (!binding) return;
|
||||
|
||||
const newName = getUniqueName(path.scope, inferredNames.get(varName));
|
||||
path.node.id.name = newName;
|
||||
binding.referencePaths.forEach(ref => {
|
||||
ref.node.name = newName;
|
||||
});
|
||||
renamedCount++;
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`重命名了 ${renamedCount} 个变量`);
|
||||
|
||||
// 第二轮:基于初始化值
|
||||
console.log('\n[3] 分析初始化值...');
|
||||
let initCount = 0;
|
||||
|
||||
traverse(ast, {
|
||||
VariableDeclarator(path) {
|
||||
if (!t.isIdentifier(path.node.id)) return;
|
||||
const varName = path.node.id.name;
|
||||
if (!/^(var|v|arg)\d+$/.test(varName)) return;
|
||||
|
||||
const init = path.node.init;
|
||||
let newName = null;
|
||||
|
||||
// 布尔字面量
|
||||
if (t.isBooleanLiteral(init)) {
|
||||
// 检查使用上下文
|
||||
const binding = path.scope.getBinding(varName);
|
||||
if (binding) {
|
||||
for (const ref of binding.referencePaths) {
|
||||
if (t.isObjectProperty(ref.parent)) {
|
||||
const key = ref.parent.key;
|
||||
let prop;
|
||||
if (t.isStringLiteral(key)) prop = key.value;
|
||||
else if (t.isIdentifier(key)) prop = key.name;
|
||||
if (prop && propToVarName[prop]) {
|
||||
newName = propToVarName[prop];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!newName) newName = init.value ? 'isTrue' : 'isFalse';
|
||||
}
|
||||
|
||||
// 数组字面量
|
||||
if (t.isArrayExpression(init) && init.elements.length === 0) {
|
||||
newName = 'items';
|
||||
}
|
||||
|
||||
// 字符串字面量
|
||||
if (t.isStringLiteral(init)) {
|
||||
const val = init.value;
|
||||
if (val.includes('/') || val.includes('\\')) newName = 'pathStr';
|
||||
else if (val.includes('@')) newName = 'emailStr';
|
||||
else if (val.length > 50) newName = 'longStr';
|
||||
else newName = 'str';
|
||||
}
|
||||
|
||||
// 数字字面量
|
||||
if (t.isNumericLiteral(init)) {
|
||||
if (init.value === 0) newName = 'count';
|
||||
else newName = 'num';
|
||||
}
|
||||
|
||||
// 正则表达式
|
||||
if (t.isRegExpLiteral(init)) {
|
||||
newName = 'regex';
|
||||
}
|
||||
|
||||
if (newName) {
|
||||
const binding = path.scope.getBinding(varName);
|
||||
if (binding) {
|
||||
const finalName = getUniqueName(path.scope, newName);
|
||||
path.node.id.name = finalName;
|
||||
binding.referencePaths.forEach(ref => {
|
||||
ref.node.name = finalName;
|
||||
});
|
||||
initCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`基于初始化值重命名了 ${initCount} 个变量`);
|
||||
|
||||
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