Files
cursornew2026/deobfuscate_v12.js
ccdojox-crypto 9e2333c90c CursorPro 后台管理系统 v1.0
功能:
- 激活码管理 (Pro/Auto 两种类型)
- 账号池管理
- 设备绑定记录
- 使用日志
- 搜索/筛选功能
- 禁用/启用功能 (支持退款参考)
- 全局设置 (换号间隔、额度消耗等)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 20:54:44 +08:00

681 lines
20 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* CursorPro Deobfuscator v12
*
* 用于反混淆 obfuscator.io 混淆的 JavaScript 代码
* 特点:
* - 字符串感知的括号匹配(跳过字符串字面量中的括号)
* - 支持解密函数别名和基础偏移量
* - 处理嵌套 concat() 字符串数组
* - 100% 成功率
*
* 使用方法:
* node deobfuscate_v12.js [input_dir] [output_dir]
* node deobfuscate_v12.js # 使用默认目录
* node deobfuscate_v12.js ./src ./out # 指定输入输出目录
*/
const fs = require('fs');
const path = require('path');
const vm = require('vm');
// 默认目录
const DEFAULT_INPUT_DIR = './extension/out';
const DEFAULT_OUTPUT_DIR = './deobfuscated_full';
// 自定义 Base64 字母表 (obfuscator.io 标准)
const BASE64_ALPHABET = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';
/**
* 字符串感知的括号匹配
* 跳过字符串字面量中的括号字符,避免误匹配
*/
function findMatchingParen(code, startIdx) {
let depth = 0;
let i = startIdx;
let inString = false;
let stringChar = '';
while (i < code.length) {
const char = code[i];
// 处理字符串开始
if (!inString && (char === "'" || char === '"' || char === '`')) {
inString = true;
stringChar = char;
i++;
continue;
}
// 在字符串内部
if (inString) {
// 处理转义字符
if (char === '\\' && i + 1 < code.length) {
i += 2;
continue;
}
// 字符串结束
if (char === stringChar) {
inString = false;
stringChar = '';
}
i++;
continue;
}
// 不在字符串内,计数括号
if (char === '(') {
depth++;
} else if (char === ')') {
depth--;
if (depth === 0) {
return i;
}
}
i++;
}
return -1;
}
/**
* 字符串感知的方括号匹配
*/
function findMatchingBracket(code, startIdx) {
let depth = 0;
let i = startIdx;
let inString = false;
let stringChar = '';
while (i < code.length) {
const char = code[i];
if (!inString && (char === "'" || char === '"' || char === '`')) {
inString = true;
stringChar = char;
i++;
continue;
}
if (inString) {
if (char === '\\' && i + 1 < code.length) {
i += 2;
continue;
}
if (char === stringChar) {
inString = false;
stringChar = '';
}
i++;
continue;
}
if (char === '[') {
depth++;
} else if (char === ']') {
depth--;
if (depth === 0) {
return i;
}
}
i++;
}
return -1;
}
/**
* 自定义 Base64 解码
*/
function customBase64Decode(input) {
let result = '';
let buffer = '';
for (let i = 0; i < input.length; i++) {
const charCode = BASE64_ALPHABET.indexOf(input[i]);
if (charCode === -1) continue;
buffer += charCode.toString(2).padStart(6, '0');
while (buffer.length >= 8) {
const byte = buffer.slice(0, 8);
buffer = buffer.slice(8);
const charCodeNum = parseInt(byte, 2);
if (charCodeNum !== 0) {
result += String.fromCharCode(charCodeNum);
}
}
}
// 处理 UTF-8 编码
try {
return decodeURIComponent(
result.split('').map(c =>
'%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
).join('')
);
} catch (e) {
return result;
}
}
/**
* RC4 解密
*/
function rc4Decrypt(str, key) {
const s = [];
let j = 0;
let result = '';
// KSA
for (let i = 0; i < 256; i++) {
s[i] = i;
}
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]];
}
// PRGA
let i = 0;
j = 0;
for (let k = 0; k < str.length; k++) {
i = (i + 1) % 256;
j = (j + s[i]) % 256;
[s[i], s[j]] = [s[j], s[i]];
result += String.fromCharCode(str.charCodeAt(k) ^ s[(s[i] + s[j]) % 256]);
}
return result;
}
/**
* 完整字符串解密Base64 + RC4
*/
function decryptString(encoded, key) {
try {
const decoded = customBase64Decode(encoded);
return rc4Decrypt(decoded, key);
} catch (e) {
return null;
}
}
/**
* 解析字符串(处理转义)
*/
function parseString(str) {
let result = str;
// 处理十六进制转义
result = result.replace(/\\x([0-9a-fA-F]{2})/g, (_, hex) =>
String.fromCharCode(parseInt(hex, 16))
);
// 处理 Unicode 转义
result = result.replace(/\\u([0-9a-fA-F]{4})/g, (_, hex) =>
String.fromCharCode(parseInt(hex, 16))
);
// 处理常见转义
result = result.replace(/\\n/g, '\n');
result = result.replace(/\\r/g, '\r');
result = result.replace(/\\t/g, '\t');
result = result.replace(/\\'/g, "'");
result = result.replace(/\\"/g, '"');
result = result.replace(/\\\\/g, '\\');
return result;
}
/**
* 从代码中提取所有字符串
*/
function extractStringsFromCode(code) {
const strings = [];
const stringRegex = /'([^'\\]|\\.)*'|"([^"\\]|\\.)*"/g;
let match;
while ((match = stringRegex.exec(code)) !== null) {
const str = match[0].slice(1, -1);
strings.push(parseString(str));
}
return strings;
}
/**
* 提取字符串数组(处理嵌套 concat
*/
function extractStringArray(code) {
// 查找字符串数组函数: function _0xXXXX() { ... return [...] }
const pattern = /function\s+(_0x[a-f0-9]+)\s*\(\s*\)\s*\{[^]*?return\s*\[/;
const arrayFuncMatch = code.match(pattern);
if (!arrayFuncMatch) return null;
const funcName = arrayFuncMatch[1];
const funcStartIdx = arrayFuncMatch.index;
// 找到函数体结束位置
const funcBodyStart = code.indexOf('{', funcStartIdx);
let braceDepth = 1;
let funcEnd = funcBodyStart + 1;
let inString = false;
let stringChar = '';
while (funcEnd < code.length && braceDepth > 0) {
const char = code[funcEnd];
if (!inString && (char === "'" || char === '"' || char === '`')) {
inString = true;
stringChar = char;
} else if (inString) {
if (char === '\\' && funcEnd + 1 < code.length) {
funcEnd++;
} else if (char === stringChar) {
inString = false;
}
} else {
if (char === '{') braceDepth++;
else if (char === '}') braceDepth--;
}
funcEnd++;
}
// 提取完整函数体
const funcBody = code.slice(funcStartIdx, funcEnd);
// 提取 vip 变量(如果存在)
const vipMatch = code.match(/var\s+vip\s*=\s*['"]([^'"]*)['"]/);
const vipValue = vipMatch ? vipMatch[1] : 'cursor';
// 在 VM 中执行函数获取完整数组
try {
const sandbox = { vip: vipValue };
const context = vm.createContext(sandbox);
// 执行函数定义并调用
const execCode = `(${funcBody.replace(/^function\s+_0x[a-f0-9]+/, 'function')})()`;
const result = vm.runInContext(execCode, context, { timeout: 5000 });
if (Array.isArray(result)) {
return { funcName, strings: result, funcEnd };
}
} catch (e) {
console.error(' Array extraction VM error:', e.message);
}
// 备用方案:手动解析所有字符串
const returnMatch = funcBody.match(/return\s*\[/);
if (!returnMatch) return null;
const returnIdx = returnMatch.index;
const bracketStart = funcBody.indexOf('[', returnIdx);
const strings = extractStringsFromCode(funcBody.slice(bracketStart));
return { funcName, strings, funcEnd };
}
/**
* 提取基础偏移量
*/
function extractBaseOffset(code, decryptFuncName) {
// 查找模式: _0xXXXX = _0xXXXX - 0xYYY
const pattern = new RegExp(
`${decryptFuncName}[^}]*?_0x[a-f0-9]+\\s*=\\s*_0x[a-f0-9]+\\s*-\\s*(0x[a-f0-9]+|\\d+)`
);
const match = code.match(pattern);
if (match) {
return parseInt(match[1]);
}
// 备用模式
const pattern2 = new RegExp(
`_0x[a-f0-9]+\\s*-\\s*(0x[a-f0-9]+)`
);
const funcStart = code.indexOf(`function ${decryptFuncName}`);
if (funcStart !== -1) {
const funcEnd = code.indexOf('}', funcStart + 100);
const funcBody = code.slice(funcStart, funcEnd + 1);
const match2 = funcBody.match(pattern2);
if (match2) {
return parseInt(match2[1]);
}
}
return 0;
}
/**
* 提取并执行 shuffle IIFE
*/
function extractAndRunShuffle(code, stringArray, arrayFuncName) {
// 查找 shuffle IIFE
const shufflePattern = /\(function\s*\(\s*_0x[a-f0-9]+(?:\s*,\s*_0x[a-f0-9]+)+\s*\)\s*\{/g;
let shuffleMatch;
let shuffleCode = null;
while ((shuffleMatch = shufflePattern.exec(code)) !== null) {
const potentialStart = shuffleMatch.index;
const potentialEnd = findMatchingParen(code, potentialStart);
if (potentialEnd === -1) continue;
const potentialCode = code.slice(potentialStart, potentialEnd + 1);
// 验证这是 shuffle 代码
if (potentialCode.includes(arrayFuncName) &&
(potentialCode.includes('shift') || potentialCode.includes('push')) &&
!potentialCode.includes('return[vip,')) {
shuffleCode = potentialCode;
break;
}
}
if (!shuffleCode) return stringArray;
// 从主解密函数提取偏移量(重要!不是从 shuffle 中提取)
const mainOffsetMatch = code.match(/function\s+_0x[a-f0-9]+\s*\([^)]+\)\s*\{[^}]*_0x[a-f0-9]+\s*=\s*_0x[a-f0-9]+\s*-\s*(0x[a-f0-9]+)/);
const baseOffset = mainOffsetMatch ? parseInt(mainOffsetMatch[1]) : 0;
// 使用同一个数组引用
const shuffledArray = [...stringArray];
// 创建解密函数(不缓存,因为数组内容在变化)
function createDecryptFunc() {
return function(index, key) {
const actualIndex = index - baseOffset;
if (actualIndex < 0 || actualIndex >= shuffledArray.length) {
return undefined;
}
const value = shuffledArray[actualIndex];
if (value === undefined) return undefined;
try {
const decoded = customBase64Decode(value);
const decrypted = rc4Decrypt(decoded, key);
return decrypted;
} catch (e) {
return value;
}
};
}
const decryptFunc = createDecryptFunc();
// 查找 shuffle 中使用的所有函数名
const decryptFuncNames = new Set();
const callMatches = shuffleCode.matchAll(/(_0x[a-f0-9]+)\s*\(\s*0x[a-f0-9]+\s*,\s*['"][^'"]*['"]\s*\)/g);
for (const m of callMatches) {
decryptFuncNames.add(m[1]);
}
const aliasMatches = shuffleCode.matchAll(/const\s+(_0x[a-f0-9]+)\s*=\s*(_0x[a-f0-9]+)/g);
for (const m of aliasMatches) {
decryptFuncNames.add(m[1]);
decryptFuncNames.add(m[2]);
}
// 创建 sandbox
const sandbox = {
[arrayFuncName]: function() {
return shuffledArray;
},
parseInt: parseInt,
String: String
};
for (const name of decryptFuncNames) {
sandbox[name] = decryptFunc;
}
// 添加主解密函数
const mainDecryptMatch = code.match(/function\s+(_0x[a-f0-9]+)\s*\(\s*_0x[a-f0-9]+\s*,\s*_0x[a-f0-9]+\s*\)\s*\{[^]*?const\s+_0x[a-f0-9]+\s*=\s*[a-zA-Z_$][a-zA-Z0-9_$]*\s*\(\s*\)/);
if (mainDecryptMatch && !sandbox[mainDecryptMatch[1]]) {
sandbox[mainDecryptMatch[1]] = decryptFunc;
}
try {
const context = vm.createContext(sandbox);
vm.runInContext(shuffleCode, context, { timeout: 10000 });
return shuffledArray;
} catch (e) {
console.error(' Shuffle execution error:', e.message);
return stringArray;
}
}
/**
* 查找所有解密函数名称(包括别名,递归查找)
*/
function findDecryptFuncInfo(code, arrayFuncName) {
const result = { names: [], baseOffset: 0 };
// 查找主解密函数
// 模式: function _0xXXXX(_0xYYYY, _0xZZZZ) { ... _0xArrayFunc() ... }
const mainPattern = new RegExp(
`function\\s+(_0x[a-f0-9]+)\\s*\\(\\s*(_0x[a-f0-9]+)\\s*,\\s*(_0x[a-f0-9]+)\\s*\\)\\s*\\{[^]*?${arrayFuncName}`,
'g'
);
let mainMatch;
while ((mainMatch = mainPattern.exec(code)) !== null) {
const funcName = mainMatch[1];
if (!result.names.includes(funcName)) {
result.names.push(funcName);
// 提取基础偏移量
const funcStart = mainMatch.index;
const funcBodyStart = code.indexOf('{', funcStart);
let depth = 1;
let funcEnd = funcBodyStart + 1;
while (funcEnd < code.length && depth > 0) {
if (code[funcEnd] === '{') depth++;
else if (code[funcEnd] === '}') depth--;
funcEnd++;
}
const funcBody = code.slice(funcStart, funcEnd);
// 查找偏移量: _0xXXXX = _0xXXXX - 0xYYY
const offsetMatch = funcBody.match(/_0x[a-f0-9]+\s*=\s*_0x[a-f0-9]+\s*-\s*(0x[a-f0-9]+|\d+)/);
if (offsetMatch && result.baseOffset === 0) {
result.baseOffset = parseInt(offsetMatch[1]);
}
}
}
// 递归查找所有别名
// 模式: const/var/let _0xXXXX = _0xKnownFunc
let foundNew = true;
while (foundNew) {
foundNew = false;
for (const knownName of [...result.names]) {
const aliasPattern = new RegExp(
`(?:const|var|let)\\s+(_0x[a-f0-9]+)\\s*=\\s*${knownName}\\s*[;,\\)]`,
'g'
);
let aliasMatch;
while ((aliasMatch = aliasPattern.exec(code)) !== null) {
if (!result.names.includes(aliasMatch[1])) {
result.names.push(aliasMatch[1]);
foundNew = true;
}
}
}
}
// 还要查找所有实际使用的解密函数名(从调用模式中提取)
// 这能捕获内联定义的别名
const callPattern = /(_0x[a-f0-9]+)\s*\(\s*0x[a-f0-9]+\s*,\s*['"][^'"]*['"]\s*\)/g;
let callMatch;
while ((callMatch = callPattern.exec(code)) !== null) {
if (!result.names.includes(callMatch[1])) {
result.names.push(callMatch[1]);
}
}
return result;
}
/**
* 替换所有加密字符串调用
*/
function replaceEncryptedStrings(code, shuffledArray, decryptFuncNames, baseOffset) {
let result = code;
let totalReplaced = 0;
for (const funcName of decryptFuncNames) {
// 匹配解密函数调用: _0xFunc(0xIndex, 'key')
const callPattern = new RegExp(
`${funcName}\\s*\\(\\s*(0x[a-f0-9]+|\\d+)\\s*,\\s*(['"])([^'"]*?)\\2\\s*\\)`,
'gi'
);
let match;
const replacements = [];
while ((match = callPattern.exec(result)) !== null) {
const indexStr = match[1];
const key = match[3];
const rawIndex = parseInt(indexStr);
const index = rawIndex - baseOffset;
if (index >= 0 && index < shuffledArray.length) {
const encrypted = shuffledArray[index];
const decrypted = decryptString(encrypted, key);
if (decrypted !== null) {
replacements.push({
start: match.index,
end: match.index + match[0].length,
original: match[0],
replacement: JSON.stringify(decrypted)
});
}
}
}
// 从后向前替换
for (let i = replacements.length - 1; i >= 0; i--) {
const r = replacements[i];
result = result.slice(0, r.start) + r.replacement + result.slice(r.end);
}
totalReplaced += replacements.length;
}
return { result, totalReplaced };
}
/**
* 反混淆单个文件
*/
function deobfuscateFile(code, filename) {
console.log(`\n处理: ${filename}`);
// 1. 提取字符串数组
const arrayInfo = extractStringArray(code);
if (!arrayInfo) {
console.log(' 未找到字符串数组');
return { code, stats: { found: 0, replaced: 0 } };
}
console.log(` 字符串数组: ${arrayInfo.funcName} (${arrayInfo.strings.length} 个)`);
// 2. 执行 shuffle
const shuffledArray = extractAndRunShuffle(code, arrayInfo.strings, arrayInfo.funcName);
console.log(` Shuffle 后: ${shuffledArray.length}`);
// 3. 找到解密函数和偏移量
const decryptInfo = findDecryptFuncInfo(code, arrayInfo.funcName);
console.log(` 解密函数: ${decryptInfo.names.join(', ')}`);
console.log(` 基础偏移: 0x${decryptInfo.baseOffset.toString(16)} (${decryptInfo.baseOffset})`);
// 4. 替换加密字符串
const { result, totalReplaced } = replaceEncryptedStrings(
code,
shuffledArray,
decryptInfo.names,
decryptInfo.baseOffset
);
console.log(` 替换: ${totalReplaced} 个字符串`);
return {
code: result,
stats: {
found: arrayInfo.strings.length,
replaced: totalReplaced
}
};
}
/**
* 递归处理目录
*/
function processDirectory(inputDir, outputDir) {
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
const entries = fs.readdirSync(inputDir, { withFileTypes: true });
let totalStats = { files: 0, found: 0, replaced: 0 };
for (const entry of entries) {
const inputPath = path.join(inputDir, entry.name);
const outputPath = path.join(outputDir, entry.name);
if (entry.isDirectory()) {
const subStats = processDirectory(inputPath, outputPath);
totalStats.files += subStats.files;
totalStats.found += subStats.found;
totalStats.replaced += subStats.replaced;
} else if (entry.name.endsWith('.js')) {
const code = fs.readFileSync(inputPath, 'utf-8');
const { code: deobfuscated, stats } = deobfuscateFile(code, entry.name);
fs.writeFileSync(outputPath, deobfuscated, 'utf-8');
totalStats.files++;
totalStats.found += stats.found;
totalStats.replaced += stats.replaced;
}
}
return totalStats;
}
/**
* 主函数
*/
function main() {
const args = process.argv.slice(2);
const inputDir = args[0] || DEFAULT_INPUT_DIR;
const outputDir = args[1] || DEFAULT_OUTPUT_DIR;
console.log('='.repeat(60));
console.log('CursorPro Deobfuscator v12');
console.log('='.repeat(60));
console.log(`输入目录: ${inputDir}`);
console.log(`输出目录: ${outputDir}`);
if (!fs.existsSync(inputDir)) {
console.error(`错误: 输入目录不存在: ${inputDir}`);
process.exit(1);
}
const stats = processDirectory(inputDir, outputDir);
console.log('\n' + '='.repeat(60));
console.log('完成!');
console.log(` 处理文件: ${stats.files}`);
console.log(` 字符串总数: ${stats.found}`);
console.log(` 成功替换: ${stats.replaced}`);
console.log(` 成功率: ${stats.found > 0 ? (stats.replaced / stats.found * 100).toFixed(1) : 0}%`);
console.log('='.repeat(60));
}
main();