195 lines
5.5 KiB
JavaScript
195 lines
5.5 KiB
JavaScript
/**
|
|
* 完整反混淆脚本 - 使用多种工具清洗代码
|
|
*/
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
// 尝试导入反混淆库
|
|
let deobfuscateIO, synchrony, beautify;
|
|
|
|
try {
|
|
deobfuscateIO = require('obfuscator-io-deobfuscator').deobfuscate;
|
|
console.log('✓ obfuscator-io-deobfuscator 已加载');
|
|
} catch (e) {
|
|
console.log('✗ obfuscator-io-deobfuscator 未安装');
|
|
}
|
|
|
|
try {
|
|
synchrony = require('deobfuscator').deobfuscate;
|
|
console.log('✓ deobfuscator (synchrony) 已加载');
|
|
} catch (e) {
|
|
console.log('✗ deobfuscator (synchrony) 未安装');
|
|
}
|
|
|
|
try {
|
|
beautify = require('js-beautify').js;
|
|
console.log('✓ js-beautify 已加载');
|
|
} catch (e) {
|
|
console.log('✗ js-beautify 未安装');
|
|
}
|
|
|
|
const inputDir = 'D:/temp/破解/cursorpro-0.4.5/原版本/extension/out';
|
|
const outputDir = 'D:/temp/破解/cursorpro-0.4.5/deobfuscated_full/extension/out';
|
|
|
|
// 确保输出目录存在
|
|
function ensureDir(dir) {
|
|
if (!fs.existsSync(dir)) {
|
|
fs.mkdirSync(dir, { recursive: true });
|
|
}
|
|
}
|
|
|
|
// 使用 obfuscator-io-deobfuscator
|
|
async function deobfuscateWithIO(code, filename) {
|
|
if (!deobfuscateIO) return null;
|
|
|
|
try {
|
|
console.log(` [obfuscator-io] 处理 ${filename}...`);
|
|
const result = deobfuscateIO(code);
|
|
return result;
|
|
} catch (e) {
|
|
console.log(` [obfuscator-io] 失败: ${e.message}`);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// 使用 synchrony deobfuscator
|
|
async function deobfuscateWithSynchrony(code, filename) {
|
|
if (!synchrony) return null;
|
|
|
|
try {
|
|
console.log(` [synchrony] 处理 ${filename}...`);
|
|
const result = await synchrony(code);
|
|
return result;
|
|
} catch (e) {
|
|
console.log(` [synchrony] 失败: ${e.message}`);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// 美化代码
|
|
function beautifyCode(code) {
|
|
if (!beautify) return code;
|
|
|
|
return beautify(code, {
|
|
indent_size: 4,
|
|
space_in_empty_paren: true,
|
|
preserve_newlines: true,
|
|
max_preserve_newlines: 2,
|
|
jslint_happy: false,
|
|
brace_style: 'collapse',
|
|
keep_array_indentation: false,
|
|
keep_function_indentation: false,
|
|
space_before_conditional: true,
|
|
break_chained_methods: false,
|
|
eval_code: false,
|
|
unescape_strings: true,
|
|
wrap_line_length: 0
|
|
});
|
|
}
|
|
|
|
// 自定义清理:移除控制流混淆的 switch-case
|
|
function cleanControlFlow(code) {
|
|
// 匹配 '2|5|3|4|6|1|0|7'['split']('|') 模式的控制流
|
|
const controlFlowPattern = /const\s+_0x[a-f0-9]+\s*=\s*'[\d\|]+'(\['split'\]|\.\s*split)\s*\('\|'\);?\s*let\s+_0x[a-f0-9]+\s*=\s*0x0;?\s*while\s*\(!!\[\]\)\s*\{\s*switch\s*\(_0x[a-f0-9]+\[_0x[a-f0-9]+\+\+\]\)\s*\{/g;
|
|
|
|
// 这个比较复杂,暂时只做标记
|
|
let count = 0;
|
|
code = code.replace(controlFlowPattern, (match) => {
|
|
count++;
|
|
return `/* [CONTROL_FLOW_${count}] */ ${match}`;
|
|
});
|
|
|
|
if (count > 0) {
|
|
console.log(` 发现 ${count} 处控制流混淆`);
|
|
}
|
|
|
|
return code;
|
|
}
|
|
|
|
// 清理对象属性访问
|
|
function cleanPropertyAccess(code) {
|
|
// 将 obj['property'] 转换为 obj.property (对于合法标识符)
|
|
const validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
|
|
code = code.replace(/\['([a-zA-Z_$][a-zA-Z0-9_$]*)'\]/g, (match, prop) => {
|
|
if (validIdentifier.test(prop)) {
|
|
return `.${prop}`;
|
|
}
|
|
return match;
|
|
});
|
|
|
|
return code;
|
|
}
|
|
|
|
// 处理单个文件
|
|
async function processFile(inputPath, outputPath, filename) {
|
|
console.log(`\n处理: ${filename}`);
|
|
|
|
let code = fs.readFileSync(inputPath, 'utf8');
|
|
console.log(` 原始大小: ${(code.length / 1024).toFixed(2)} KB`);
|
|
|
|
let result = null;
|
|
|
|
// 方法1: 尝试 obfuscator-io-deobfuscator
|
|
result = await deobfuscateWithIO(code, filename);
|
|
|
|
// 方法2: 如果失败,尝试 synchrony
|
|
if (!result) {
|
|
result = await deobfuscateWithSynchrony(code, filename);
|
|
}
|
|
|
|
// 如果两个库都失败,使用原始代码
|
|
if (!result) {
|
|
console.log(` 使用原始代码(反混淆库失败)`);
|
|
result = code;
|
|
}
|
|
|
|
// 自定义清理
|
|
result = cleanPropertyAccess(result);
|
|
result = cleanControlFlow(result);
|
|
|
|
// 美化
|
|
result = beautifyCode(result);
|
|
|
|
console.log(` 处理后大小: ${(result.length / 1024).toFixed(2)} KB`);
|
|
|
|
// 保存
|
|
ensureDir(path.dirname(outputPath));
|
|
fs.writeFileSync(outputPath, result);
|
|
console.log(` ✓ 已保存: ${outputPath}`);
|
|
|
|
return result;
|
|
}
|
|
|
|
// 主函数
|
|
async function main() {
|
|
console.log('========================================');
|
|
console.log(' 完整反混淆脚本');
|
|
console.log('========================================\n');
|
|
|
|
const files = [
|
|
{ input: 'extension.js', output: 'extension.js' },
|
|
{ input: 'webview/provider.js', output: 'webview/provider.js' },
|
|
{ input: 'utils/account.js', output: 'utils/account.js' },
|
|
{ input: 'utils/sqlite.js', output: 'utils/sqlite.js' },
|
|
];
|
|
|
|
for (const file of files) {
|
|
const inputPath = path.join(inputDir, file.input);
|
|
const outputPath = path.join(outputDir, file.output);
|
|
|
|
if (fs.existsSync(inputPath)) {
|
|
await processFile(inputPath, outputPath, file.input);
|
|
} else {
|
|
console.log(`\n跳过: ${file.input} (文件不存在)`);
|
|
}
|
|
}
|
|
|
|
console.log('\n========================================');
|
|
console.log(' 完成!');
|
|
console.log('========================================');
|
|
console.log(`输出目录: ${outputDir}`);
|
|
}
|
|
|
|
main().catch(console.error);
|