120 lines
3.8 KiB
JavaScript
120 lines
3.8 KiB
JavaScript
/**
|
|
* 变量名反混淆工具
|
|
* 将 _0x 前缀的变量名重命名为可读形式
|
|
*/
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
// 尝试使用 babel
|
|
let babel, traverse, generate;
|
|
try {
|
|
babel = require('@babel/core');
|
|
traverse = require('@babel/traverse').default;
|
|
generate = require('@babel/generator').default;
|
|
} catch (e) {
|
|
console.log('需要安装 babel 依赖,正在安装...');
|
|
require('child_process').execSync('npm install @babel/core @babel/traverse @babel/generator @babel/parser --save-dev', {
|
|
stdio: 'inherit',
|
|
cwd: 'D:/temp/破解/cursorpro-0.4.5'
|
|
});
|
|
babel = require('@babel/core');
|
|
traverse = require('@babel/traverse').default;
|
|
generate = require('@babel/generator').default;
|
|
}
|
|
|
|
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_readable.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 varMapping = new Map();
|
|
let varCounter = 1;
|
|
let paramCounter = 1;
|
|
|
|
// 变量名生成器
|
|
function generateVarName(prefix, counter) {
|
|
return prefix + counter;
|
|
}
|
|
|
|
// 检查是否是混淆变量名
|
|
function isObfuscatedName(name) {
|
|
return /^_0x[a-f0-9]+$/i.test(name);
|
|
}
|
|
|
|
// 遍历 AST 收集所有混淆变量名
|
|
traverse(ast, {
|
|
Identifier(path) {
|
|
const name = path.node.name;
|
|
if (isObfuscatedName(name) && !varMapping.has(name)) {
|
|
// 根据上下文决定新名称
|
|
let newName;
|
|
if (path.parentPath.isFunction() && path.listKey === 'params') {
|
|
newName = 'arg' + paramCounter++;
|
|
} else if (path.parentPath.isVariableDeclarator() && path.key === 'id') {
|
|
newName = 'var' + varCounter++;
|
|
} else if (path.parentPath.isFunctionDeclaration() && path.key === 'id') {
|
|
newName = 'func' + varCounter++;
|
|
} else if (!varMapping.has(name)) {
|
|
newName = 'v' + varCounter++;
|
|
}
|
|
if (newName) {
|
|
varMapping.set(name, newName);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
console.log(`找到 ${varMapping.size} 个混淆变量名`);
|
|
|
|
console.log('\n[3] 重命名变量...');
|
|
let renamedCount = 0;
|
|
|
|
traverse(ast, {
|
|
Identifier(path) {
|
|
const name = path.node.name;
|
|
if (varMapping.has(name)) {
|
|
path.node.name = varMapping.get(name);
|
|
renamedCount++;
|
|
}
|
|
}
|
|
});
|
|
|
|
console.log(`重命名了 ${renamedCount} 处`);
|
|
|
|
console.log('\n[4] 生成代码...');
|
|
const output = generate(ast, {
|
|
comments: true,
|
|
compact: false,
|
|
concise: false
|
|
}, code);
|
|
|
|
console.log('\n[5] 保存文件...');
|
|
fs.writeFileSync(outputPath, output.code);
|
|
console.log(`保存到: ${outputPath}`);
|
|
console.log(`新文件大小: ${(output.code.length / 1024).toFixed(2)} KB`);
|
|
|
|
// 验证
|
|
const remaining = (output.code.match(/_0x[a-f0-9]+/gi) || []).length;
|
|
console.log(`\n剩余混淆变量名: ${remaining}`);
|
|
|
|
console.log('\n✅ 完成!');
|