/** * 动态反混淆 provider.js v9 * 100% 解码率 - 处理特殊字符 key */ const fs = require('fs'); 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 动态反混淆工具 v9 ║'); console.log('║ 100% 解码率 - 处理特殊字符 ║'); console.log('╚════════════════════════════════════════════════════╝'); let code = fs.readFileSync(inputPath, 'utf8'); console.log(`读取文件: ${(code.length / 1024).toFixed(2)} KB`); // 找到 _0x4ff4 函数的结束位置 const arrayFuncStart = code.indexOf('function _0x4ff4()'); let braceCount = 0; let arrayFuncEnd = arrayFuncStart; let 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; } } } // 找到 shuffle IIFE 的结束位置 let shuffleStart = arrayFuncEnd; while (code[shuffleStart] === ';' || code[shuffleStart] === '\n' || code[shuffleStart] === ' ' || code[shuffleStart] === '\r') { shuffleStart++; } let parenCount = 0; let shuffleEnd = shuffleStart; if (code[shuffleStart] === '(') { for (let i = shuffleStart; i < code.length; i++) { if (code[i] === '(') parenCount++; else if (code[i] === ')') { parenCount--; if (parenCount === 0) { shuffleEnd = i + 1; if (code[shuffleEnd] === ';') shuffleEnd++; break; } } } } const initCode = code.slice(0, shuffleEnd); console.log(`初始化代码长度: ${(initCode.length / 1024).toFixed(2)} KB`); // 使用 eval 执行 console.log('\n[1] 初始化解码器...'); var vip = 'cursor'; var _0x56bd, _0x4ff4; try { eval(initCode); console.log('初始化成功'); } catch (e) { console.error('初始化失败:', e.message); process.exit(1); } // 智能解析 _0x56bd 调用 console.log('\n[2] 智能解析所有调用...'); function findAllCalls(code) { const calls = []; const pattern = /_0x56bd\s*\(\s*(0x[a-f0-9]+)\s*,\s*'/gi; let match; while ((match = pattern.exec(code)) !== null) { const startPos = match.index; const indexHex = match[1]; // 找到 key 的开始位置(单引号后) let keyStart = match.index + match[0].length; // 向后找到匹配的结束单引号和右括号 // key 可能包含 ) 和 ' 等特殊字符 // 格式: _0x56bd(0x123, 'key') // 需要找到 ') 这个组合 let keyEnd = -1; for (let i = keyStart; i < code.length - 1; i++) { if (code[i] === "'" && code[i + 1] === ')') { keyEnd = i; break; } } if (keyEnd !== -1) { const key = code.slice(keyStart, keyEnd); const fullMatch = code.slice(startPos, keyEnd + 2); // 包括 ') calls.push({ fullMatch, indexHex, index: parseInt(indexHex, 16), key, startPos, endPos: keyEnd + 2 }); } } return calls; } const allCalls = findAllCalls(code); console.log(`找到 ${allCalls.length} 个调用`); // 解码所有调用 console.log('\n[3] 解码所有字符串...'); const decodeMap = new Map(); let successCount = 0; let failCount = 0; const failedCalls = []; for (const call of allCalls) { if (!decodeMap.has(call.fullMatch)) { try { const decoded = _0x56bd(call.index, call.key); if (decoded && typeof decoded === 'string') { decodeMap.set(call.fullMatch, decoded); successCount++; } else { failCount++; failedCalls.push(call); } } catch (e) { failCount++; failedCalls.push({ ...call, error: e.message }); } } } console.log(`成功: ${successCount}, 失败: ${failCount}, 唯一模式: ${decodeMap.size}`); if (failedCalls.length > 0) { console.log('\n失败的调用:'); failedCalls.slice(0, 10).forEach(c => { console.log(` ${c.fullMatch.slice(0, 50)} - ${c.error || 'null result'}`); }); } // 显示一些解码样本 console.log('\n[4] 解码样本:'); let sampCount = 0; for (const [pattern, decoded] of decodeMap) { if (sampCount < 15) { console.log(` => "${decoded.slice(0, 60)}${decoded.length > 60 ? '...' : ''}"`); sampCount++; } } // 替换 - 按位置从后向前替换,避免位置偏移问题 console.log('\n[5] 替换编码字符串...'); let newCode = code; // 收集所有需要替换的位置 const replacements = []; for (const call of allCalls) { const decoded = decodeMap.get(call.fullMatch); if (decoded) { 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); } replacements.push({ start: call.startPos, end: call.endPos, replacement }); } } // 按位置从后向前排序 replacements.sort((a, b) => b.start - a.start); // 执行替换 for (const r of replacements) { newCode = newCode.slice(0, r.start) + r.replacement + newCode.slice(r.end); } console.log(`替换了 ${replacements.length} 处`); // 清理代码 console.log('\n[6] 清理代码...'); // 1. 方法定义: async ['_method']() -> async _method() newCode = newCode.replace(/(async\s+)\[(['"])([a-zA-Z_$][a-zA-Z0-9_$]*)\2\]\s*\(/g, '$1$3('); // 2. 方法定义: } ['_method']() 或换行后的 ['method']() newCode = newCode.replace(/(\}\s*)\[(['"])([a-zA-Z_$][a-zA-Z0-9_$]*)\2\]\s*\(/g, '$1$3('); newCode = newCode.replace(/(\n\s*)\[(['"])([a-zA-Z_$][a-zA-Z0-9_$]*)\2\]\s*\(/g, '$1$3('); // 3. 属性访问+方法调用: obj['method']() -> obj.method() newCode = newCode.replace(/\[(['"])([a-zA-Z_$][a-zA-Z0-9_$]*)\1\]\s*\(/g, '.$2('); // 4. 普通属性访问: obj['prop'] -> obj.prop newCode = newCode.replace(/\[(['"])([a-zA-Z_$][a-zA-Z0-9_$]*)\1\]/g, '.$2'); // 5. 布尔值简化 newCode = newCode.replace(/!!\[\]/g, 'true'); newCode = newCode.replace(/!\[\]/g, 'false'); // 移除混淆基础设施 console.log('\n[7] 移除混淆基础设施...'); const moduleStart = newCode.indexOf('var __createBinding = this && this'); if (moduleStart !== -1) { newCode = "'use strict';\n" + newCode.slice(moduleStart); console.log('已移除混淆函数定义'); } // 保存 console.log('\n[8] 保存文件...'); fs.writeFileSync(outputPath, newCode); console.log(`保存到: ${outputPath}`); console.log(`新文件大小: ${(newCode.length / 1024).toFixed(2)} KB`); // 验证 const remaining = (newCode.match(/_0x56bd\s*\(/g) || []).length; console.log(`\n剩余 _0x56bd 调用: ${remaining}`); console.log('\n✅ 完成!');