183 lines
6.0 KiB
JavaScript
183 lines
6.0 KiB
JavaScript
/**
|
||
* 批量生成解码映射 - 为每个混淆文件生成 decoded_map.json
|
||
*/
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
const vm = require('vm');
|
||
|
||
const baseDir = 'D:/temp/破解/cursorpro-0.4.5';
|
||
|
||
/**
|
||
* 从代码中提取解码器并生成映射
|
||
*/
|
||
function generateDecodeMap(code, filename) {
|
||
console.log(`\n处理: ${filename}`);
|
||
console.log('='.repeat(40));
|
||
|
||
// 查找字符串数组函数
|
||
const arrayFuncMatch = code.match(/function\s+(_0x[a-f0-9]+)\s*\(\)\s*\{/);
|
||
if (!arrayFuncMatch) {
|
||
console.log(' 未找到字符串数组函数');
|
||
return null;
|
||
}
|
||
const arrayFuncName = arrayFuncMatch[1];
|
||
|
||
// 查找解码函数
|
||
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(` 数组函数: ${arrayFuncName}`);
|
||
console.log(` 解码函数: ${decoderFuncName}`);
|
||
|
||
// 提取所有解码器调用模式
|
||
const callPatterns = [
|
||
/_0x[a-f0-9]+\s*\(\s*(0x[a-f0-9]+)\s*,\s*'([^']*)'\s*\)/g,
|
||
/_0x[a-f0-9]+\s*\(\s*(0x[a-f0-9]+)\s*,\s*"([^"]*)"\s*\)/g
|
||
];
|
||
|
||
const calls = new Set();
|
||
for (const pattern of callPatterns) {
|
||
let match;
|
||
while ((match = pattern.exec(code)) !== null) {
|
||
calls.add(match[0]);
|
||
}
|
||
}
|
||
|
||
console.log(` 找到 ${calls.size} 个唯一调用`);
|
||
|
||
// 尝试设置沙盒执行解码器
|
||
// 提取从开头到第一个 exports 之前的所有代码
|
||
let exportIndex = code.indexOf('Object.defineProperty(exports');
|
||
if (exportIndex === -1) {
|
||
exportIndex = code.indexOf('exports.');
|
||
}
|
||
if (exportIndex === -1) {
|
||
exportIndex = code.length;
|
||
}
|
||
|
||
// 找到解码函数结束位置
|
||
const decoderStart = code.indexOf(`function ${decoderFuncName}(`);
|
||
let braceCount = 0, decoderEnd = decoderStart, 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 setupCode = code.substring(0, Math.min(decoderEnd + 500, exportIndex));
|
||
|
||
// 在沙盒中执行
|
||
const sandbox = {
|
||
console: { log: () => {}, warn: () => {}, error: () => {} },
|
||
parseInt,
|
||
String,
|
||
decodeURIComponent,
|
||
vip: 'cursor'
|
||
};
|
||
|
||
try {
|
||
vm.runInNewContext(setupCode, sandbox);
|
||
|
||
// 测试解码器
|
||
const testResult = vm.runInNewContext(`typeof ${decoderFuncName}`, sandbox);
|
||
if (testResult !== 'function') {
|
||
console.log(` 解码器不可用: ${testResult}`);
|
||
return null;
|
||
}
|
||
console.log(` 解码器设置成功`);
|
||
|
||
// 解码所有调用
|
||
const decodeMap = {};
|
||
let successCount = 0;
|
||
let failCount = 0;
|
||
|
||
for (const call of calls) {
|
||
// 提取参数
|
||
const paramMatch = call.match(/_0x[a-f0-9]+\s*\(\s*(0x[a-f0-9]+)\s*,\s*['"]([^'"]*)['"]\s*\)/);
|
||
if (!paramMatch) continue;
|
||
|
||
const num = paramMatch[1];
|
||
const key = paramMatch[2];
|
||
|
||
try {
|
||
const decoded = vm.runInNewContext(
|
||
`${decoderFuncName}(${num},'${key.replace(/'/g, "\\'")}')`,
|
||
sandbox
|
||
);
|
||
if (typeof decoded === 'string') {
|
||
decodeMap[call] = decoded;
|
||
successCount++;
|
||
} else {
|
||
failCount++;
|
||
}
|
||
} catch (e) {
|
||
failCount++;
|
||
}
|
||
}
|
||
|
||
console.log(` 成功解码: ${successCount}`);
|
||
console.log(` 解码失败: ${failCount}`);
|
||
|
||
return decodeMap;
|
||
} catch (e) {
|
||
console.log(` 沙盒执行失败: ${e.message}`);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
// 主函数
|
||
function main() {
|
||
console.log('╔════════════════════════════════════════╗');
|
||
console.log('║ 批量生成解码映射 ║');
|
||
console.log('╚════════════════════════════════════════╝');
|
||
|
||
const files = [
|
||
{ input: '原版本/extension/out/webview/provider.js', output: 'provider_decoded_map.json' },
|
||
{ input: '原版本/extension/out/extension.js', output: 'extension_decoded_map.json' },
|
||
{ 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(outputPath)) {
|
||
const existing = JSON.parse(fs.readFileSync(outputPath, 'utf8'));
|
||
console.log(`\n${file.output}: 已存在 (${Object.keys(existing).length} 条)`);
|
||
continue;
|
||
}
|
||
|
||
if (!fs.existsSync(inputPath)) {
|
||
console.log(`\n跳过: ${file.input} (不存在)`);
|
||
continue;
|
||
}
|
||
|
||
const code = fs.readFileSync(inputPath, 'utf8');
|
||
const decodeMap = generateDecodeMap(code, file.input);
|
||
|
||
if (decodeMap && Object.keys(decodeMap).length > 0) {
|
||
fs.writeFileSync(outputPath, JSON.stringify(decodeMap, null, 2));
|
||
console.log(` 已保存: ${outputPath}`);
|
||
} else {
|
||
console.log(` 无法生成映射`);
|
||
}
|
||
}
|
||
|
||
console.log('\n完成!');
|
||
}
|
||
|
||
main();
|