/** * 直接解码脚本 - 使用 RC4 + 非标准 Base64 算法 * 不依赖沙盒执行,直接实现解码逻辑 */ const fs = require('fs'); const path = require('path'); const baseDir = 'D:/temp/破解/cursorpro-0.4.5'; // 非标准 Base64 字母表 (小写在前) const BASE64_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/='; /** * 非标准 Base64 解码 */ function base64Decode(str) { let result = ''; let buffer = 0; let bufferLen = 0; for (let i = 0; i < str.length; i++) { const char = str[i]; const charIndex = BASE64_CHARS.indexOf(char); if (charIndex === -1) continue; if (charIndex === 64) continue; // '=' padding buffer = (buffer << 6) | charIndex; bufferLen += 6; if (bufferLen >= 8) { bufferLen -= 8; result += String.fromCharCode((buffer >> bufferLen) & 0xFF); } } return result; } /** * RC4 解密 */ function rc4Decrypt(data, key) { // 初始化 S-box const s = []; for (let i = 0; i < 256; i++) { s[i] = i; } let j = 0; 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 result = ''; 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]]; result += String.fromCharCode(data.charCodeAt(k) ^ s[(s[i] + s[j]) % 256]); } return result; } /** * 解码单个字符串 */ function decodeString(encodedStr, key) { try { const base64Decoded = base64Decode(encodedStr); const decrypted = rc4Decrypt(base64Decoded, key); return decrypted; } catch (e) { return null; } } /** * 提取字符串数组 */ function extractStringArray(code) { // 查找字符串数组 - 这是一个大的嵌套数组 const arrayMatch = code.match(/return\s*\[([^\]]*(?:\]\.concat\(function\s*\(\)\s*\{\s*return\s*\[[^\]]*\][^\}]*\}\(\)\))*[^\]]*)\]/s); if (!arrayMatch) return null; // 提取所有字符串 const strMatch = code.match(/return\s*\['([^']*)'(?:,'([^']*)')*\]/g); if (!strMatch) return null; const strings = []; const allStrings = code.match(/'[^']*'/g) || []; // 找到字符串数组的开始位置 const arrayStart = code.indexOf("const _0x") || code.indexOf("function _0x"); const arrayEnd = code.indexOf("Object.defineProperty(exports"); if (arrayStart !== -1 && arrayEnd !== -1) { const arraySection = code.substring(arrayStart, arrayEnd); // 提取这个区域内所有带引号的字符串 const stringMatches = arraySection.match(/'([^'\\]*(\\.[^'\\]*)*)'/g) || []; for (const match of stringMatches) { const str = match.slice(1, -1); // 移除引号 if (str.length > 3 && /^[a-zA-Z0-9+/=]+$/.test(str)) { strings.push(str); } } } console.log(` 提取了 ${strings.length} 个候选编码字符串`); return strings; } /** * 为文件生成解码映射 */ function generateDecodeMapForFile(code, filename) { console.log(`\n处理: ${filename}`); console.log('='.repeat(50)); // 找到所有解码函数调用 const callPattern = /(_0x[a-f0-9]+)\s*\(\s*(0x[a-f0-9]+)\s*,\s*'([^']*)'\s*\)/g; const calls = new Map(); let match; while ((match = callPattern.exec(code)) !== null) { const fullMatch = match[0]; const funcName = match[1]; const numHex = match[2]; const key = match[3]; calls.set(fullMatch, { funcName, numHex, key, num: parseInt(numHex, 16) }); } console.log(` 找到 ${calls.size} 个唯一调用`); // 提取字符串数组 // 找到类似这样的模式: // return [vip, 'encodedStr1', 'encodedStr2', ...] const stringArrayMatch = code.match(/return\s*\[\s*vip\s*,\s*('[^']*'(?:\s*,\s*'[^']*')*)\s*\]/); let stringArray = ['cursor']; // vip = 'cursor' if (stringArrayMatch) { const stringsSection = stringArrayMatch[1]; const strings = stringsSection.match(/'([^']*)'/g); if (strings) { for (const s of strings) { stringArray.push(s.slice(1, -1)); } } console.log(` 提取了 ${stringArray.length} 个数组元素`); } else { // 尝试另一种模式 - concat 嵌套数组 const concatPattern = /return\s*\[([^\]]*)\]\.concat/g; const allArrays = []; let cm; while ((cm = concatPattern.exec(code)) !== null) { const content = cm[1]; const strings = content.match(/'([^']*)'/g); if (strings) { for (const s of strings) { allArrays.push(s.slice(1, -1)); } } } if (allArrays.length > 0) { stringArray = ['cursor', ...allArrays]; console.log(` 通过 concat 提取了 ${stringArray.length} 个数组元素`); } } // 如果无法提取数组,返回空 if (stringArray.length < 10) { console.log(' 无法提取足够的字符串数组'); return null; } // 尝试解码 const decodeMap = {}; let successCount = 0; for (const [fullMatch, info] of calls) { const { num, key } = info; // 计算实际索引(减去偏移量) // 不同文件的偏移量不同,需要尝试 for (let offset = 0; offset <= 0x200; offset += 0x10) { const adjustedIndex = num - offset; if (adjustedIndex >= 0 && adjustedIndex < stringArray.length) { const encodedStr = stringArray[adjustedIndex]; const decoded = decodeString(encodedStr, key); if (decoded && decoded.length > 0 && /^[\x20-\x7E\u4e00-\u9fff]+$/.test(decoded)) { decodeMap[fullMatch] = decoded; successCount++; break; } } } } console.log(` 成功解码: ${successCount}/${calls.size}`); return decodeMap; } /** * 使用已有的解码器脚本为每个文件生成映射 */ async function generateWithExistingDecoder(inputPath, outputPath, filename) { console.log(`\n处理: ${filename}`); console.log('='.repeat(50)); if (fs.existsSync(outputPath)) { const existing = JSON.parse(fs.readFileSync(outputPath, 'utf8')); console.log(` 已存在: ${Object.keys(existing).length} 条映射`); return existing; } // 读取代码 const code = fs.readFileSync(inputPath, 'utf8'); // 查找解码器函数名 const decoderMatch = code.match(/function\s+(_0x[a-f0-9]+)\s*\(\s*_0x[a-f0-9]+\s*,\s*_0x[a-f0-9]+\s*\)\s*\{/); if (!decoderMatch) { console.log(' 未找到解码函数'); return null; } const decoderFuncName = decoderMatch[1]; console.log(` 解码函数: ${decoderFuncName}`); // 收集所有调用 const callPattern = new RegExp( `(_0x[a-f0-9]+)\\s*\\(\\s*(0x[a-f0-9]+)\\s*,\\s*'([^']*)'\\s*\\)`, 'g' ); const calls = new Set(); let match; while ((match = callPattern.exec(code)) !== null) { calls.add(match[0]); } console.log(` 找到 ${calls.size} 个调用`); // 对于没有映射的文件,我们需要用不同的方法 // 使用之前成功的解码器代码片段 return { size: calls.size, decoder: decoderFuncName }; } // 主函数 async function main() { console.log('╔════════════════════════════════════════════════════╗'); console.log('║ 直接解码映射生成器 ║'); console.log('║ 使用 RC4 + 非标准 Base64 ║'); console.log('╚════════════════════════════════════════════════════╝'); const files = [ { input: '原版本/extension/out/utils/account.js', output: 'account_decoded_map.json' }, { input: '原版本/extension/out/utils/sqlite.js', output: 'sqlite_decoded_map.json' }, { input: '原版本/extension/out/api/client.js', output: 'client_decoded_map.json' } ]; for (const file of files) { const inputPath = path.join(baseDir, file.input); const outputPath = path.join(baseDir, file.output); if (!fs.existsSync(inputPath)) { console.log(`\n跳过: ${file.input} (不存在)`); continue; } const code = fs.readFileSync(inputPath, 'utf8'); const decodeMap = generateDecodeMapForFile(code, file.input); if (decodeMap && Object.keys(decodeMap).length > 0) { fs.writeFileSync(outputPath, JSON.stringify(decodeMap, null, 2)); console.log(` 已保存: ${outputPath}`); } } console.log('\n完成!'); } main().catch(console.error);