/** * 动态反混淆 provider.js * 执行原始解码器并替换所有编码字符串 */ const fs = require('fs'); const path = require('path'); // 读取部分反混淆后的文件 const inputPath = 'D:/temp/破解/cursorpro-0.4.5/deobfuscated_full/extension/out/webview/provider_clean.js'; const outputPath = 'D:/temp/破解/cursorpro-0.4.5/deobfuscated_full/extension/out/webview/provider.js'; console.log('╔════════════════════════════════════════════════════╗'); console.log('║ Provider.js 动态反混淆工具 ║'); console.log('╚════════════════════════════════════════════════════╝'); let code = fs.readFileSync(inputPath, 'utf8'); console.log(`读取文件: ${(code.length / 1024).toFixed(2)} KB`); // 提取字符串数组函数和解码器函数 // 找到 _0x4ff4 函数(字符串数组) const arrayFuncMatch = code.match(/(function _0x4ff4\(\)\s*\{[\s\S]*?return _0x4ff4\(\);\s*\})/); if (!arrayFuncMatch) { console.error('未找到字符串数组函数 _0x4ff4'); process.exit(1); } // 找到 _0x56bd 解码器函数 const decoderMatch = code.match(/(function _0x56bd\(_0x[a-f0-9]+,\s*_0x[a-f0-9]+\)\s*\{[\s\S]*?return _0x[a-f0-9]+;\s*\})/); if (!decoderMatch) { console.error('未找到解码器函数 _0x56bd'); process.exit(1); } console.log('找到字符串数组函数和解码器函数'); // 构建可执行的解码环境 const decoderCode = ` var vip = 'cursor'; ${arrayFuncMatch[1]} ${decoderMatch[1]} // 返回解码器 module.exports = { _0x56bd, _0x4ff4 }; `; // 写入临时文件并执行 const tempFile = path.join(__dirname, '_temp_decoder.js'); fs.writeFileSync(tempFile, decoderCode); let decoder; try { decoder = require(tempFile); console.log('解码器加载成功'); } catch (e) { console.error('解码器加载失败:', e.message); // 尝试直接eval try { eval(`var vip = 'cursor'; ${arrayFuncMatch[1]} ${decoderMatch[1]}`); decoder = { _0x56bd }; console.log('使用 eval 加载解码器成功'); } catch (e2) { console.error('eval 也失败:', e2.message); process.exit(1); } } // 清理临时文件 try { fs.unlinkSync(tempFile); } catch(e) {} // 查找所有 _0x56bd 调用并解码 const callPattern = /_0x56bd\s*\(\s*(0x[a-f0-9]+)\s*,\s*'([^']*)'\s*\)/g; const decodeMap = new Map(); let match; let callCount = 0; while ((match = callPattern.exec(code)) !== null) { const fullMatch = match[0]; const indexHex = match[1]; const key = match[2]; if (!decodeMap.has(fullMatch)) { try { const index = parseInt(indexHex, 16); const decoded = decoder._0x56bd(index, key); if (decoded && typeof decoded === 'string') { decodeMap.set(fullMatch, decoded); callCount++; } } catch (e) { // 忽略解码错误 } } } console.log(`找到 ${decodeMap.size} 个唯一的编码字符串`); // 替换所有编码调用 let newCode = code; let replaceCount = 0; for (const [pattern, decoded] of decodeMap) { // 生成合适的字符串字面量 let replacement; if (decoded.includes('\n') || decoded.includes('\r') || decoded.includes('`') || decoded.includes('${')) { replacement = JSON.stringify(decoded); } else if (decoded.includes("'") && !decoded.includes('"')) { replacement = `"${decoded}"`; } else if (decoded.includes('"') && !decoded.includes("'")) { replacement = `'${decoded}'`; } else { replacement = JSON.stringify(decoded); } const before = newCode.length; newCode = newCode.split(pattern).join(replacement); if (newCode.length !== before) { replaceCount++; } } console.log(`替换了 ${replaceCount} 个模式`); // 清理代码 // 1. 简化属性访问 obj['prop'] -> obj.prop newCode = newCode.replace(/\['([a-zA-Z_$][a-zA-Z0-9_$]*)'\]/g, '.$1'); // 2. 简化布尔值 newCode = newCode.replace(/!!\[\]/g, 'true'); newCode = newCode.replace(/!\[\]/g, 'false'); // 3. 移除十六进制数字(转为十进制) newCode = newCode.replace(/\b0x([a-fA-F0-9]+)\b/g, (match, hex) => { const num = parseInt(hex, 16); // 只转换较小的数字,避免破坏大数字 if (num < 10000) return num.toString(); return match; }); // 保存 const outputDir = path.dirname(outputPath); if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); } fs.writeFileSync(outputPath, newCode); console.log(`\n保存到: ${outputPath}`); console.log(`新文件大小: ${(newCode.length / 1024).toFixed(2)} KB`); // 保存解码映射 const mapPath = 'D:/temp/破解/cursorpro-0.4.5/provider_decoded_strings.json'; const mapObj = {}; for (const [k, v] of decodeMap) { if (v.length < 200) { mapObj[k] = v; } } fs.writeFileSync(mapPath, JSON.stringify(mapObj, null, 2)); console.log(`解码映射保存到: ${mapPath}`); console.log('\n✅ 完成!');