Files
cursornew2026/deobfuscate_provider_dynamic.js

163 lines
5.1 KiB
JavaScript

/**
* 动态反混淆 provider.js
* 执行原始解码器并替换所有编码字符串
*/
const fs = require('fs');
const path = require('path');
// 读取部分反混淆后的文件
const inputPath = 'D:/temp/破解/cursorpro-0.4.5/deobfuscated_full/extension/out/webview/provider_clean.js';
const outputPath = 'D:/temp/破解/cursorpro-0.4.5/deobfuscated_full/extension/out/webview/provider.js';
console.log('╔════════════════════════════════════════════════════╗');
console.log('║ Provider.js 动态反混淆工具 ║');
console.log('╚════════════════════════════════════════════════════╝');
let code = fs.readFileSync(inputPath, 'utf8');
console.log(`读取文件: ${(code.length / 1024).toFixed(2)} KB`);
// 提取字符串数组函数和解码器函数
// 找到 _0x4ff4 函数(字符串数组)
const arrayFuncMatch = code.match(/(function _0x4ff4\(\)\s*\{[\s\S]*?return _0x4ff4\(\);\s*\})/);
if (!arrayFuncMatch) {
console.error('未找到字符串数组函数 _0x4ff4');
process.exit(1);
}
// 找到 _0x56bd 解码器函数
const decoderMatch = code.match(/(function _0x56bd\(_0x[a-f0-9]+,\s*_0x[a-f0-9]+\)\s*\{[\s\S]*?return _0x[a-f0-9]+;\s*\})/);
if (!decoderMatch) {
console.error('未找到解码器函数 _0x56bd');
process.exit(1);
}
console.log('找到字符串数组函数和解码器函数');
// 构建可执行的解码环境
const decoderCode = `
var vip = 'cursor';
${arrayFuncMatch[1]}
${decoderMatch[1]}
// 返回解码器
module.exports = { _0x56bd, _0x4ff4 };
`;
// 写入临时文件并执行
const tempFile = path.join(__dirname, '_temp_decoder.js');
fs.writeFileSync(tempFile, decoderCode);
let decoder;
try {
decoder = require(tempFile);
console.log('解码器加载成功');
} catch (e) {
console.error('解码器加载失败:', e.message);
// 尝试直接eval
try {
eval(`var vip = 'cursor'; ${arrayFuncMatch[1]} ${decoderMatch[1]}`);
decoder = { _0x56bd };
console.log('使用 eval 加载解码器成功');
} catch (e2) {
console.error('eval 也失败:', e2.message);
process.exit(1);
}
}
// 清理临时文件
try { fs.unlinkSync(tempFile); } catch(e) {}
// 查找所有 _0x56bd 调用并解码
const callPattern = /_0x56bd\s*\(\s*(0x[a-f0-9]+)\s*,\s*'([^']*)'\s*\)/g;
const decodeMap = new Map();
let match;
let callCount = 0;
while ((match = callPattern.exec(code)) !== null) {
const fullMatch = match[0];
const indexHex = match[1];
const key = match[2];
if (!decodeMap.has(fullMatch)) {
try {
const index = parseInt(indexHex, 16);
const decoded = decoder._0x56bd(index, key);
if (decoded && typeof decoded === 'string') {
decodeMap.set(fullMatch, decoded);
callCount++;
}
} catch (e) {
// 忽略解码错误
}
}
}
console.log(`找到 ${decodeMap.size} 个唯一的编码字符串`);
// 替换所有编码调用
let newCode = code;
let replaceCount = 0;
for (const [pattern, decoded] of decodeMap) {
// 生成合适的字符串字面量
let replacement;
if (decoded.includes('\n') || decoded.includes('\r') || decoded.includes('`') || decoded.includes('${')) {
replacement = JSON.stringify(decoded);
} else if (decoded.includes("'") && !decoded.includes('"')) {
replacement = `"${decoded}"`;
} else if (decoded.includes('"') && !decoded.includes("'")) {
replacement = `'${decoded}'`;
} else {
replacement = JSON.stringify(decoded);
}
const before = newCode.length;
newCode = newCode.split(pattern).join(replacement);
if (newCode.length !== before) {
replaceCount++;
}
}
console.log(`替换了 ${replaceCount} 个模式`);
// 清理代码
// 1. 简化属性访问 obj['prop'] -> obj.prop
newCode = newCode.replace(/\['([a-zA-Z_$][a-zA-Z0-9_$]*)'\]/g, '.$1');
// 2. 简化布尔值
newCode = newCode.replace(/!!\[\]/g, 'true');
newCode = newCode.replace(/!\[\]/g, 'false');
// 3. 移除十六进制数字(转为十进制)
newCode = newCode.replace(/\b0x([a-fA-F0-9]+)\b/g, (match, hex) => {
const num = parseInt(hex, 16);
// 只转换较小的数字,避免破坏大数字
if (num < 10000) return num.toString();
return match;
});
// 保存
const outputDir = path.dirname(outputPath);
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
fs.writeFileSync(outputPath, newCode);
console.log(`\n保存到: ${outputPath}`);
console.log(`新文件大小: ${(newCode.length / 1024).toFixed(2)} KB`);
// 保存解码映射
const mapPath = 'D:/temp/破解/cursorpro-0.4.5/provider_decoded_strings.json';
const mapObj = {};
for (const [k, v] of decodeMap) {
if (v.length < 200) {
mapObj[k] = v;
}
}
fs.writeFileSync(mapPath, JSON.stringify(mapObj, null, 2));
console.log(`解码映射保存到: ${mapPath}`);
console.log('\n✅ 完成!');