182 lines
5.3 KiB
JavaScript
182 lines
5.3 KiB
JavaScript
const fs = require('fs');
|
||
const vm = require('vm');
|
||
|
||
// 读取原始 provider.js
|
||
const code = fs.readFileSync('D:/temp/破解/cursorpro-0.4.5/原版本/extension/out/webview/provider.js', 'utf8');
|
||
|
||
console.log('文件大小:', code.length, '字节');
|
||
|
||
// 找到 _0x4ff4 函数的位置
|
||
const arrayFuncStart = code.indexOf('function _0x4ff4(){');
|
||
if (arrayFuncStart === -1) {
|
||
console.error('找不到 _0x4ff4 函数');
|
||
process.exit(1);
|
||
}
|
||
|
||
// 找到函数结束位置
|
||
let braceCount2 = 0;
|
||
let arrayFuncEnd = arrayFuncStart;
|
||
let foundStart2 = false;
|
||
for (let i = arrayFuncStart; i < code.length; i++) {
|
||
if (code[i] === '{') {
|
||
braceCount2++;
|
||
foundStart2 = true;
|
||
} else if (code[i] === '}') {
|
||
braceCount2--;
|
||
if (foundStart2 && braceCount2 === 0) {
|
||
arrayFuncEnd = i + 1;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
const arrayFunc = code.substring(arrayFuncStart, arrayFuncEnd);
|
||
console.log('1. 字符串数组函数已提取, 长度:', arrayFunc.length);
|
||
|
||
// 提取解码函数 _0x56bd
|
||
const decoderStart = code.indexOf('function _0x56bd(');
|
||
if (decoderStart === -1) {
|
||
console.error('找不到 _0x56bd 函数');
|
||
process.exit(1);
|
||
}
|
||
|
||
// 找到函数结束位置
|
||
let braceCount = 0;
|
||
let decoderEnd = decoderStart;
|
||
let foundStart = false;
|
||
for (let i = decoderStart; i < code.length; i++) {
|
||
if (code[i] === '{') {
|
||
braceCount++;
|
||
foundStart = true;
|
||
} else if (code[i] === '}') {
|
||
braceCount--;
|
||
if (foundStart && braceCount === 0) {
|
||
decoderEnd = i + 1;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
const decoderFunc = code.substring(decoderStart, decoderEnd);
|
||
console.log('2. 解码函数已提取');
|
||
|
||
// 提取 IIFE(用于打乱数组)- 在 _0x4ff4 函数之后
|
||
const iifeStart = code.indexOf('(function(_0x', arrayFuncEnd);
|
||
if (iifeStart === -1) {
|
||
console.error('找不到 IIFE');
|
||
process.exit(1);
|
||
}
|
||
|
||
// 找到 IIFE 结束 - 寻找 (_0x4ff4,0x 模式
|
||
let iifeEnd = code.indexOf('));', iifeStart);
|
||
if (iifeEnd === -1) {
|
||
console.error('找不到 IIFE 结束');
|
||
process.exit(1);
|
||
}
|
||
iifeEnd += 3; // 包含 ));
|
||
|
||
const iifeCode = code.substring(iifeStart, iifeEnd);
|
||
console.log('3. IIFE 已提取, 长度:', iifeCode.length);
|
||
|
||
// 在沙盒中执行
|
||
const sandbox = {};
|
||
const setupCode = `
|
||
${arrayFunc}
|
||
${decoderFunc}
|
||
${iifeCode}
|
||
`;
|
||
|
||
try {
|
||
vm.runInNewContext(setupCode, sandbox);
|
||
// 将函数添加到沙盒
|
||
vm.runInNewContext(`
|
||
globalThis._0x4ff4 = _0x4ff4;
|
||
globalThis._0x56bd = _0x56bd;
|
||
`, sandbox);
|
||
} catch (e) {
|
||
console.error('执行初始化代码失败:', e.message);
|
||
process.exit(1);
|
||
}
|
||
console.log('4. 沙盒环境已建立');
|
||
|
||
// 创建解码映射
|
||
const decodeMap = {};
|
||
let decodedCount = 0;
|
||
|
||
// 查找所有调用模式: _0x56bd(0x123,'xxxx') 或 _0xa6d6ac(0x123,'xxxx')
|
||
const callPattern = /(_0x56bd|_0xa6d6ac)\((0x[a-f0-9]+),\s*'([^']+)'\)/g;
|
||
let match;
|
||
|
||
while ((match = callPattern.exec(code)) !== null) {
|
||
const fullMatch = match[0];
|
||
const num = parseInt(match[2], 16);
|
||
const key = match[3];
|
||
|
||
if (!decodeMap[fullMatch]) {
|
||
try {
|
||
const decoded = vm.runInNewContext(`_0x56bd(${num},'${key}')`, sandbox);
|
||
if (typeof decoded === 'string') {
|
||
decodeMap[fullMatch] = decoded;
|
||
decodedCount++;
|
||
}
|
||
} catch (e) {
|
||
// 忽略错误
|
||
}
|
||
}
|
||
}
|
||
|
||
console.log('5. 已解码', decodedCount, '个字符串');
|
||
|
||
// 替换代码中的加密调用
|
||
let deobfuscated = code;
|
||
|
||
// 按长度降序排序,避免部分替换问题
|
||
const sortedEntries = Object.entries(decodeMap).sort((a, b) => b[0].length - a[0].length);
|
||
|
||
for (const [encrypted, decrypted] of sortedEntries) {
|
||
// 转义特殊字符
|
||
const escaped = encrypted.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||
const regex = new RegExp(escaped, 'g');
|
||
|
||
// 根据内容选择合适的引号
|
||
let replacement;
|
||
if (decrypted.includes("'") && !decrypted.includes('"')) {
|
||
replacement = JSON.stringify(decrypted);
|
||
} else if (decrypted.includes('"') && !decrypted.includes("'")) {
|
||
replacement = `'${decrypted}'`;
|
||
} else if (decrypted.includes("'") && decrypted.includes('"')) {
|
||
replacement = JSON.stringify(decrypted);
|
||
} else {
|
||
replacement = `'${decrypted}'`;
|
||
}
|
||
|
||
deobfuscated = deobfuscated.replace(regex, replacement);
|
||
}
|
||
|
||
console.log('6. 字符串替换完成');
|
||
|
||
// 移除解码函数定义和 IIFE
|
||
deobfuscated = deobfuscated.replace(arrayFunc, '// [STRING ARRAY REMOVED]');
|
||
deobfuscated = deobfuscated.replace(decoderFunc, '// [DECODER REMOVED]');
|
||
deobfuscated = deobfuscated.replace(iifeCode, '// [IIFE REMOVED]');
|
||
|
||
// 移除别名定义
|
||
deobfuscated = deobfuscated.replace(/var _0xa6d6ac=_0x56bd;?/g, '// [ALIAS REMOVED]');
|
||
|
||
console.log('7. 清理完成');
|
||
|
||
// 保存反混淆后的代码
|
||
const outputPath = 'D:/temp/破解/cursorpro-0.4.5/deobfuscated/provider/provider.js';
|
||
fs.mkdirSync('D:/temp/破解/cursorpro-0.4.5/deobfuscated/provider', { recursive: true });
|
||
fs.writeFileSync(outputPath, deobfuscated);
|
||
console.log('8. 已保存到:', outputPath);
|
||
|
||
// 输出一些关键字符串
|
||
console.log('\n=== 关键 API 字符串 ===');
|
||
const apiStrings = Object.entries(decodeMap).filter(([k, v]) =>
|
||
v.includes('cursor') || v.includes('api') || v.includes('http') || v.includes('verify')
|
||
);
|
||
apiStrings.slice(0, 30).forEach(([k, v]) => {
|
||
if (v.length < 100) console.log(v);
|
||
});
|