130 lines
4.0 KiB
JavaScript
130 lines
4.0 KiB
JavaScript
/**
|
|
* CursorPro 反编译脚本 v6
|
|
* 执行完整的初始化代码包括数组混淆
|
|
*/
|
|
const fs = require('fs');
|
|
|
|
// 读取原版代码
|
|
const code = fs.readFileSync('D:/temp/破解/cursorpro-0.4.5/原版本/extension/out/api/client.js', 'utf8');
|
|
|
|
// 找到第一个 var __createBinding 的位置,这是混淆初始化代码的结束位置
|
|
const initEndPos = code.indexOf('var __createBinding');
|
|
|
|
// 提取初始化代码 (包括 vip, 数组混淆IIFE, _0x81f8, _0x3fbb)
|
|
let initCode = code.substring(0, initEndPos);
|
|
|
|
// 还需要 _0x3fbb 函数
|
|
const func3fbbStart = code.indexOf('function _0x3fbb(');
|
|
const func3fbbEnd = code.indexOf(',_0x3fbb(_0x91e0a,_0x2e3a7e);}', func3fbbStart) + ',_0x3fbb(_0x91e0a,_0x2e3a7e);}'.length;
|
|
const func3fbbCode = code.substring(func3fbbStart, func3fbbEnd);
|
|
|
|
// 还需要 _0x81f8 函数
|
|
const func81f8Start = code.indexOf('function _0x81f8()');
|
|
const func81f8End = code.indexOf('return _0x81f8();}', func81f8Start) + 'return _0x81f8();}'.length;
|
|
const func81f8Code = code.substring(func81f8Start, func81f8End);
|
|
|
|
console.log('初始化代码长度:', initCode.length);
|
|
console.log('_0x81f8 函数长度:', func81f8Code.length);
|
|
console.log('_0x3fbb 函数长度:', func3fbbCode.length);
|
|
|
|
// 执行代码
|
|
try {
|
|
eval(initCode);
|
|
console.log('初始化代码执行成功');
|
|
console.log('vip 变量值:', typeof vip !== 'undefined' ? vip : 'undefined');
|
|
} catch (e) {
|
|
console.log('初始化代码执行失败:', e.message);
|
|
}
|
|
|
|
// 执行 _0x81f8 和 _0x3fbb
|
|
try {
|
|
eval(func81f8Code);
|
|
console.log('_0x81f8 函数执行成功');
|
|
} catch (e) {
|
|
console.log('_0x81f8 执行失败:', e.message);
|
|
}
|
|
|
|
try {
|
|
eval(func3fbbCode);
|
|
console.log('_0x3fbb 函数执行成功');
|
|
} catch (e) {
|
|
console.log('_0x3fbb 执行失败:', e.message);
|
|
}
|
|
|
|
// 检查数组内容
|
|
const arr = _0x81f8();
|
|
console.log('\n字符串数组前5项:', arr.slice(0, 5));
|
|
console.log('字符串数组长度:', arr.length);
|
|
|
|
const decode = _0x3fbb;
|
|
|
|
console.log('\n=== CursorPro 原版代码解码 ===\n');
|
|
|
|
// 测试解码
|
|
const testCases = [
|
|
[0x18a, 'yC20', 'DEFAULT_API_URL'],
|
|
[0x151, 'pIfk', 'vscode require'],
|
|
[0x177, ']8Ci', 'workspace'],
|
|
[0x15b, 'j#7G', 'apiUrl config'],
|
|
[0x197, 'Kfdi', '/api/verify'],
|
|
[0x186, 'dpeu', 'POST'],
|
|
[0x141, 'z&uV', '/api/switch'],
|
|
[0x144, '*1hl', '__esModule'],
|
|
[0x1b6, 'mBo%', 'getApiUrl'],
|
|
[0x146, 'pIfk', 'getOnlineStatus'],
|
|
[0x145, 'j#7G', 'switchAccount'],
|
|
[0x133, '3nFX', 'body'],
|
|
[0x19c, ']$%b', 'stringify'],
|
|
[0x172, ')0X3', 'json'],
|
|
[0x185, 'yC20', 'application/json'],
|
|
[0x181, '^UhV', 'offline'],
|
|
];
|
|
|
|
const results = {};
|
|
for (const [index, key, desc] of testCases) {
|
|
try {
|
|
const decoded = decode(index, key);
|
|
results[desc] = decoded;
|
|
console.log(`${desc} (0x${index.toString(16)}, '${key}'): "${decoded}"`);
|
|
} catch (e) {
|
|
console.log(`${desc}: ERROR - ${e.message}`);
|
|
}
|
|
}
|
|
|
|
console.log('\n=== 关键解码信息 ===');
|
|
console.log('API 地址 DEFAULT_API_URL:', results['DEFAULT_API_URL']);
|
|
|
|
// 扫描所有调用
|
|
console.log('\n=== 扫描代码中的所有调用 ===');
|
|
const regex = /_0x[a-zA-Z0-9]+\s*\(\s*(0x[0-9a-fA-F]+)\s*,\s*'([^']+)'\s*\)/g;
|
|
const allDecoded = new Map();
|
|
|
|
let match;
|
|
while ((match = regex.exec(code)) !== null) {
|
|
const index = parseInt(match[1], 16);
|
|
const key = match[2];
|
|
const callStr = `${match[1]},'${key}'`;
|
|
|
|
if (!allDecoded.has(callStr)) {
|
|
try {
|
|
const decoded = decode(index, key);
|
|
allDecoded.set(callStr, decoded);
|
|
} catch (e) {
|
|
allDecoded.set(callStr, `ERROR: ${e.message}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
console.log('\n所有唯一解码结果:');
|
|
for (const [call, decoded] of allDecoded) {
|
|
console.log(` (${call}) => "${decoded}"`);
|
|
}
|
|
|
|
// 保存解码映射表
|
|
const decodedMap = {};
|
|
for (const [call, decoded] of allDecoded) {
|
|
decodedMap[call] = decoded;
|
|
}
|
|
fs.writeFileSync('D:/temp/破解/cursorpro-0.4.5/decoded_strings.json', JSON.stringify(decodedMap, null, 2));
|
|
console.log('\n解码映射已保存到 decoded_strings.json');
|