/** * 动态反混淆 provider.js v4 * 直接执行 provider_clean.js 前半部分代码来初始化解码器 */ const fs = require('fs'); const vm = require('vm'); 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 动态反混淆工具 v4 ║'); console.log('╚════════════════════════════════════════════════════╝'); let code = fs.readFileSync(inputPath, 'utf8'); console.log(`读取文件: ${(code.length / 1024).toFixed(2)} KB`); // 找到 _0x56bd 函数的结束位置 // 函数定义在文件开头附近 const decoderStart = code.indexOf('function _0x56bd('); if (decoderStart === -1) { console.error('未找到 _0x56bd 函数'); process.exit(1); } // 找到 _0x56bd 函数结束 - 通过匹配花括号 let braceCount = 0; let decoderEnd = decoderStart; let started = false; for (let i = decoderStart; i < code.length; i++) { if (code[i] === '{') { braceCount++; started = true; } else if (code[i] === '}') { braceCount--; if (started && braceCount === 0) { decoderEnd = i + 1; break; } } } console.log(`_0x56bd 函数结束位置: ${decoderEnd}`); // 找到 _0x4ff4 函数的结束位置 const arrayFuncStart = code.indexOf('function _0x4ff4()'); if (arrayFuncStart === -1) { console.error('未找到 _0x4ff4 函数'); process.exit(1); } // 找到 _0x4ff4 函数结束 braceCount = 0; let arrayFuncEnd = arrayFuncStart; started = false; for (let i = arrayFuncStart; i < code.length; i++) { if (code[i] === '{') { braceCount++; started = true; } else if (code[i] === '}') { braceCount--; if (started && braceCount === 0) { arrayFuncEnd = i + 1; break; } } } console.log(`_0x4ff4 函数结束位置: ${arrayFuncEnd}`); // 取前半部分代码(包括两个函数定义) const initCodeEnd = Math.max(decoderEnd, arrayFuncEnd); const initCode = code.slice(0, initCodeEnd); console.log(`初始化代码长度: ${(initCode.length / 1024).toFixed(2)} KB`); // 创建沙盒执行代码 const vmCode = ` ${initCode} // 导出解码器 ({ _0x56bd: _0x56bd, _0x4ff4: _0x4ff4 }); `; console.log('\n[1] 在沙盒中执行初始化代码...'); let decoder; try { const sandbox = { console: { log: () => {}, error: () => {} }, vip: 'cursor' // 可能需要这个变量 }; const context = vm.createContext(sandbox); const script = new vm.Script(vmCode, { timeout: 60000 }); decoder = script.runInContext(context, { timeout: 60000 }); console.log('解码器初始化成功'); } catch (e) { console.error('沙盒执行失败:', e.message); console.error(e.stack?.slice(0, 500)); process.exit(1); } // 测试解码 console.log('\n[2] 测试解码...'); try { // 尝试几个不同的调用来验证解码器 const tests = [ [0x532, 'ck7z'], [0x107, 'test'], [0x200, 'abcd'] ]; for (const [index, key] of tests) { try { const result = decoder._0x56bd(index, key); console.log(` _0x56bd(0x${index.toString(16)}, '${key}') = "${result?.slice(0, 50) || '(empty)'}${result?.length > 50 ? '...' : ''}"`); } catch (e) { console.log(` _0x56bd(0x${index.toString(16)}, '${key}') = ERROR: ${e.message}`); } } } catch (e) { console.log('测试解码失败:', e.message); } // 查找所有 _0x56bd 调用并解码 console.log('\n[3] 查找所有解码调用...'); // 两种模式: _0x56bd(0x..., '...') 和 _0x56bd(0x..., "...") const callPattern1 = /_0x56bd\s*\(\s*(0x[a-f0-9]+)\s*,\s*'([^']*)'\s*\)/gi; const callPattern2 = /_0x56bd\s*\(\s*(0x[a-f0-9]+)\s*,\s*"([^"]*)"\s*\)/gi; const decodeMap = new Map(); let match; let totalCalls = 0; let successCalls = 0; // 匹配单引号 while ((match = callPattern1.exec(code)) !== null) { const fullMatch = match[0]; const indexHex = match[1]; const key = match[2]; totalCalls++; 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); successCalls++; } } catch (e) { // 跳过解码失败的 } } } // 匹配双引号 while ((match = callPattern2.exec(code)) !== null) { const fullMatch = match[0]; const indexHex = match[1]; const key = match[2]; totalCalls++; 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); successCalls++; } } catch (e) { // 跳过解码失败的 } } } console.log(`总调用数: ${totalCalls}, 成功解码: ${successCalls}, 唯一模式: ${decodeMap.size}`); // 显示一些解码样本 console.log('\n[4] 解码样本:'); let sampleCount = 0; for (const [pattern, decoded] of decodeMap) { if (sampleCount < 10 && decoded.length < 50) { console.log(` ${pattern.slice(0, 30)}... => "${decoded}"`); sampleCount++; } } // 替换 console.log('\n[5] 替换编码字符串...'); 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} 个模式`); // 清理代码 console.log('\n[6] 清理代码...'); // 简化属性访问 obj['prop'] => obj.prop newCode = newCode.replace(/\['([a-zA-Z_$][a-zA-Z0-9_$]*)'\]/g, '.$1'); // 简化布尔值 newCode = newCode.replace(/!!\[\]/g, 'true'); newCode = newCode.replace(/!\[\]/g, 'false'); // 保存 console.log('\n[7] 保存文件...'); fs.writeFileSync(outputPath, newCode); console.log(`保存到: ${outputPath}`); console.log(`新文件大小: ${(newCode.length / 1024).toFixed(2)} KB`); console.log('\n✅ 完成!');