/** * 动态反混淆 provider.js v5 * 独立实现 RC4 + Base64 解码器 */ 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 动态反混淆工具 v5 ║'); 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; } } } const initCode = code.slice(0, arrayFuncEnd); // 获取字符串数组 const vmCode1 = ` ${initCode} _0x4ff4(); `; console.log('\n[1] 获取字符串数组...'); let stringArray; try { const sandbox = { vip: 'cursor' }; const context = vm.createContext(sandbox); const script = new vm.Script(vmCode1, { timeout: 60000 }); stringArray = script.runInContext(context, { timeout: 60000 }); console.log(`数组长度: ${stringArray.length}`); } catch (e) { console.error('获取数组失败:', e.message); process.exit(1); } // 独立实现解码器 // Base64 字母表 (小写优先) const base64Chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/='; // Base64 解码 function customBase64Decode(input) { let result = ''; for (let i = 0, charCode, bits; i < input.length;) { charCode = base64Chars.indexOf(input.charAt(i++)); if (charCode === -1) continue; if (bits === undefined) { bits = charCode; continue; } bits = (bits * 64) + charCode; if (i % 4 === 1) continue; result += String.fromCharCode(0xFF & (bits >> ((-2 * i) & 6))); } return result; } // 改进的 Base64 解码 function base64Decode(str) { let output = ''; let temp = ''; let i = 0; let charCode; for (let j = 0; j < str.length; j++) { charCode = base64Chars.indexOf(str.charAt(j)); if (charCode === -1 || charCode === 64) continue; // 跳过无效字符和 '=' i++; temp = (i % 4 === 1) ? charCode : (temp * 64 + charCode); if (i % 4 !== 1) { output += String.fromCharCode(0xFF & (temp >> ((-2 * i) & 6))); } } return output; } // RC4 解密 function rc4Decrypt(data, key) { const S = []; let j = 0; let result = ''; // 初始化 S 盒 for (let i = 0; i < 256; i++) { S[i] = i; } // 打乱 S 盒 for (let i = 0; i < 256; i++) { j = (j + S[i] + key.charCodeAt(i % key.length)) % 256; [S[i], S[j]] = [S[j], S[i]]; } // 生成密钥流并解密 let i = 0; j = 0; for (let k = 0; k < data.length; k++) { i = (i + 1) % 256; j = (j + S[i]) % 256; [S[i], S[j]] = [S[j], S[i]]; const keyByte = S[(S[i] + S[j]) % 256]; result += String.fromCharCode(data.charCodeAt(k) ^ keyByte); } return result; } // 完整解码函数 function decode(index, key) { const actualIndex = index - 0x107; // 263 if (actualIndex < 0 || actualIndex >= stringArray.length) { return null; } const encoded = stringArray[actualIndex]; if (!encoded) return null; try { const decoded1 = base64Decode(encoded); const decoded2 = rc4Decrypt(decoded1, key); return decoded2; } catch (e) { return null; } } // 测试解码 console.log('\n[2] 测试解码...'); // 尝试找到代码中实际使用的一些调用来验证 const testCalls = [ [0x532, 'ck7z'], [0x108, 'test'], [0x109, 'abcd'] ]; for (const [index, key] of testCalls) { const actualIndex = index - 0x107; const encoded = stringArray[actualIndex]; const result = decode(index, key); console.log(` index=${index} (actual=${actualIndex})`); console.log(` encoded: ${encoded?.slice(0, 30) || '(none)'}...`); console.log(` decoded: ${result?.slice(0, 50) || '(null)'}${result?.length > 50 ? '...' : ''}`); } // 查找代码中实际的调用并验证 console.log('\n[3] 从代码中提取实际调用测试...'); const samplePattern = /_0x56bd\s*\(\s*(0x[a-f0-9]+)\s*,\s*'([^']*)'\s*\)/gi; let sampleMatch; let sampleCount = 0; while ((sampleMatch = samplePattern.exec(code)) !== null && sampleCount < 5) { const idx = parseInt(sampleMatch[1], 16); const k = sampleMatch[2]; const result = decode(idx, k); console.log(` ${sampleMatch[0].slice(0, 40)}... => "${result?.slice(0, 40) || '(null)'}"`); sampleCount++; } // 查找所有 _0x56bd 调用并解码 console.log('\n[4] 查找所有解码调用...'); 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)) { const index = parseInt(indexHex, 16); const decoded = decode(index, key); if (decoded && typeof decoded === 'string') { decodeMap.set(fullMatch, decoded); successCalls++; } } } // 匹配双引号 while ((match = callPattern2.exec(code)) !== null) { const fullMatch = match[0]; const indexHex = match[1]; const key = match[2]; totalCalls++; if (!decodeMap.has(fullMatch)) { const index = parseInt(indexHex, 16); const decoded = decode(index, key); if (decoded && typeof decoded === 'string') { decodeMap.set(fullMatch, decoded); successCalls++; } } } console.log(`总调用数: ${totalCalls}, 成功解码: ${successCalls}, 唯一模式: ${decodeMap.size}`); // 显示一些解码样本 console.log('\n[5] 解码样本:'); 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[6] 替换编码字符串...'); 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[7] 清理代码...'); // 简化属性访问 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[8] 保存文件...'); fs.writeFileSync(outputPath, newCode); console.log(`保存到: ${outputPath}`); console.log(`新文件大小: ${(newCode.length / 1024).toFixed(2)} KB`); console.log('\n✅ 完成!');