/** * 完整反混淆脚本 - 使用多种工具清洗代码 */ 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);